diff --git a/lib/config/definitions.js b/lib/config/definitions.js index a133080633490d0185c66f68293315cca82e397a..bb844f547fb0385600e280a298f54536c58aacba 100644 --- a/lib/config/definitions.js +++ b/lib/config/definitions.js @@ -1042,6 +1042,12 @@ const options = [ mergeable: true, cli: false, }, + { + name: 'raiseDeprecationWarnings', + description: 'Raise deprecation warnings in issues whenever found', + type: 'boolean', + default: true, + }, ]; function getOptions() { diff --git a/lib/datasource/npm.js b/lib/datasource/npm.js index 9362ea1e3fd62130a0e5c056d56a4dd039a02395..4d871d39770e7c46e36b43a7c062c303135e2cf4 100644 --- a/lib/datasource/npm.js +++ b/lib/datasource/npm.js @@ -159,13 +159,6 @@ async function getDependencyInner(name, retries = 5) { } const latestVersion = res.versions[res['dist-tags'].latest]; - if (latestVersion.deprecated) { - logger.info( - { depName: name, deprecated: latestVersion.deprecated }, - 'latest version is deprecated' - ); - res.deprecationMessage = latestVersion.deprecated; - } res.repository = res.repository || latestVersion.repository; res.homepage = res.homepage || latestVersion.homepage; @@ -206,6 +199,14 @@ async function getDependencyInner(name, retries = 5) { versions: {}, 'renovate-config': latestVersion['renovate-config'], }; + if (latestVersion.deprecated) { + dep.deprecationMessage = `On registry \`${regUrl}\`, the "latest" version (v${ + dep.latestVersion + }) of dependency \`${name}\` has the following deprecation notice:\n\n\`${ + latestVersion.deprecated + }\`\n\nMarking the latest version of an npm package as deprecated results in the entire package being considered deprecated, so contact the package author you think this is a mistake.`; + dep.deprecationSource = 'npm'; + } const versions = Object.keys(res.versions) .filter(isVersion) .sort(sortVersions); diff --git a/lib/workers/repository/process/lookup/index.js b/lib/workers/repository/process/lookup/index.js index 10e601ce96b9c571d3a3ee9b120cb07abe007787..1968c5f2f7011cae043b446fe06d2c03f753766f 100644 --- a/lib/workers/repository/process/lookup/index.js +++ b/lib/workers/repository/process/lookup/index.js @@ -37,6 +37,21 @@ async function lookupUpdates(config) { res.updates.push(result); return res; } + const { deprecationMessage, deprecationSource } = dependency; + // istanbul ignore if + if (deprecationMessage && config.raiseDeprecationWarnings) { + logger.info( + { + deprecationSource, + depName, + deprecationMessage, + }, + 'dependency is deprecated' + ); + const issueTitle = `Dependency deprecation warning: ${depName} (${deprecationSource})`; + const issueBody = `${deprecationMessage}\n\nPlease take the actions necessary to rename or substitute this deprecated package and commit to your base branch. If you wish to ignore this deprecation warning and continue using \`${depName}\` as-is, please add it to your [ignoreDeps](https://renovatebot.com/docs/configuration-options/#ignoredeps) array in Renovate config before closing this issue, otherwise another issue will be recreated the next time Renovate runs.`; + await platform.ensureIssue(issueTitle, issueBody); + } res.repositoryUrl = dependency.repositoryUrl && dependency.repositoryUrl.length ? dependency.repositoryUrl diff --git a/test/datasource/__snapshots__/npm.spec.js.snap b/test/datasource/__snapshots__/npm.spec.js.snap index 340fb93cf3303e8fde6c703e90a78d2ca64bb568..aa91c3b0a26dd5092090777187e818f0e58c93d1 100644 --- a/test/datasource/__snapshots__/npm.spec.js.snap +++ b/test/datasource/__snapshots__/npm.spec.js.snap @@ -127,6 +127,12 @@ exports[`api/npm should retry when 408 or 5xx 1`] = `null`; exports[`api/npm should return deprecated 1`] = ` Object { + "deprecationMessage": "On registry \`https://registry.npmjs.org/\`, the \\"latest\\" version (v0.0.2) of dependency \`foobar\` has the following deprecation notice: + +\`This is deprecated\` + +Marking the latest version of an npm package as deprecated results in the entire package being considered deprecated, so contact the package author you think this is a mistake.", + "deprecationSource": "npm", "homepage": undefined, "latestVersion": "0.0.2", "name": undefined, @@ -150,6 +156,14 @@ Object { } `; +exports[`api/npm should return deprecated 2`] = ` +"On registry \`https://registry.npmjs.org/\`, the \\"latest\\" version (v0.0.2) of dependency \`foobar\` has the following deprecation notice: + +\`This is deprecated\` + +Marking the latest version of an npm package as deprecated results in the entire package being considered deprecated, so contact the package author you think this is a mistake." +`; + exports[`api/npm should send an authorization header if provided 1`] = ` Object { "homepage": undefined, diff --git a/test/datasource/npm.spec.js b/test/datasource/npm.spec.js index 42b4646bfecaaf3fc2caed4d77365f18c069cb7a..c53f76c4693fe2fa2cf48401ad9f0bd672e02801 100644 --- a/test/datasource/npm.spec.js +++ b/test/datasource/npm.spec.js @@ -88,7 +88,7 @@ describe('api/npm', () => { .reply(200, deprecatedPackage); const res = await npm.getDependency('foobar'); expect(res).toMatchSnapshot(); - expect(res.deprecationMessage).toEqual(deprecatedPackage.deprecated); + expect(res.deprecationMessage).toMatchSnapshot(); }); it('should handle purl', async () => { nock('https://registry.npmjs.org') diff --git a/test/workers/repository/updates/__snapshots__/flatten.spec.js.snap b/test/workers/repository/updates/__snapshots__/flatten.spec.js.snap index 1bde98904545ac46fe2c57c0cf4a1ea18379293a..31fba8dbab3f57a7b31cf98ac4aa9cda89e64c9c 100644 --- a/test/workers/repository/updates/__snapshots__/flatten.spec.js.snap +++ b/test/workers/repository/updates/__snapshots__/flatten.spec.js.snap @@ -58,6 +58,7 @@ Array [ "prHourlyLimit": 0, "prNotPendingHours": 25, "prTitle": null, + "raiseDeprecationWarnings": true, "rebaseStalePrs": null, "recreateClosed": false, "requiredStatusChecks": Array [], @@ -129,6 +130,7 @@ Array [ "prHourlyLimit": 0, "prNotPendingHours": 25, "prTitle": null, + "raiseDeprecationWarnings": true, "rebaseStalePrs": null, "recreateClosed": false, "requiredStatusChecks": Array [], @@ -197,6 +199,7 @@ Array [ "prHourlyLimit": 0, "prNotPendingHours": 25, "prTitle": null, + "raiseDeprecationWarnings": true, "rebaseStalePrs": true, "recreateClosed": true, "requiredStatusChecks": Array [], @@ -273,6 +276,7 @@ Array [ "prHourlyLimit": 0, "prNotPendingHours": 25, "prTitle": null, + "raiseDeprecationWarnings": true, "rebaseStalePrs": null, "recreateClosed": false, "requiredStatusChecks": Array [], diff --git a/website/docs/configuration-options.md b/website/docs/configuration-options.md index 2b2dc47fe19df2a806c685b0d841d0891fa36b8e..87ad02bd5e5bc7c98e7eef59fb3db96bf20c0ce5 100644 --- a/website/docs/configuration-options.md +++ b/website/docs/configuration-options.md @@ -509,6 +509,8 @@ The PR title is important for some of Renovate's matching algorithms (e.g. deter Currently the only Python package manager is `pip` - specifically for `requirements.txt` and `requirequirements.pip` files - so adding any config to this `python` object is essentially the same as adding it to the `pip_requirements` object instead. +## raiseDeprecationWarnings + ## rangeStrategy Behaviour: