From 16d88aee4c3c0ff48ddc18f6e066255399f3cd9e Mon Sep 17 00:00:00 2001 From: Rhys Arkins <rhys@arkins.net> Date: Thu, 5 Jul 2018 15:10:50 +0200 Subject: [PATCH] feat: ignoreDeprecated Renovate now ignores any upgrades that are marked as deprecated, unless the current version is itself also deprecated. The new config option `ignoreDeprecated` can be set to false to disable this if necessary. Closes #1988 --- lib/config/definitions.js | 8 ++++ lib/datasource/npm.js | 3 ++ .../repository/process/lookup/filter.js | 26 ++++++++++++- .../repository/process/lookup/index.js | 3 +- .../datasource/__snapshots__/npm.spec.js.snap | 1 + .../lookup/__snapshots__/index.spec.js.snap | 37 +++++++++++++++++++ .../repository/process/lookup/index.spec.js | 15 ++++++++ website/docs/configuration-options.md | 4 ++ 8 files changed, 95 insertions(+), 2 deletions(-) diff --git a/lib/config/definitions.js b/lib/config/definitions.js index 0a4dfd2c08..b15de71a5a 100644 --- a/lib/config/definitions.js +++ b/lib/config/definitions.js @@ -476,6 +476,14 @@ const options = [ stage: 'package', type: 'boolean', }, + { + name: 'ignoreDeprecated', + description: + 'Ignore deprecated versions unless the current version is deprecated', + stage: 'package', + type: 'boolean', + default: true, + }, { name: 'unstablePattern', description: 'Regex for identifying unstable versions (docker only)', diff --git a/lib/datasource/npm.js b/lib/datasource/npm.js index bb20f7d472..14c66fdb70 100644 --- a/lib/datasource/npm.js +++ b/lib/datasource/npm.js @@ -227,6 +227,9 @@ async function getDependencyInner(name, retries = 5) { release.canBeUnpublished = moment().diff(moment(release.releaseTimestamp), 'days') === 0; } + if (res.versions[version].deprecated) { + release.isDeprecated = true; + } return release; }); logger.trace({ dep }, 'dep'); diff --git a/lib/workers/repository/process/lookup/filter.js b/lib/workers/repository/process/lookup/filter.js index 0ead9b86a7..93052ccf8d 100644 --- a/lib/workers/repository/process/lookup/filter.js +++ b/lib/workers/repository/process/lookup/filter.js @@ -4,10 +4,17 @@ module.exports = { filterVersions, }; -function filterVersions(config, fromVersion, latestVersion, versions) { +function filterVersions( + config, + fromVersion, + latestVersion, + versions, + releases +) { const { versionScheme, ignoreUnstable, + ignoreDeprecated, respectLatest, allowedVersions, } = config; @@ -23,6 +30,23 @@ function filterVersions(config, fromVersion, latestVersion, versions) { isGreaterThan(version, fromVersion) ); + // Don't upgrade from non-deprecated to deprecated + const fromRelease = releases.find(release => release.version === fromVersion); + if (ignoreDeprecated && fromRelease && !fromRelease.isDeprecated) { + filteredVersions = filteredVersions.filter(version => { + const versionRelease = releases.find( + release => release.version === version + ); + if (versionRelease.isDeprecated) { + logger.debug( + `Skipping ${config.depName}@${version} because it is deprecated` + ); + return false; + } + return true; + }); + } + if (allowedVersions) { if (isValid(allowedVersions)) { filteredVersions = filteredVersions.filter(version => diff --git a/lib/workers/repository/process/lookup/index.js b/lib/workers/repository/process/lookup/index.js index 920ffa16ff..1f23f69372 100644 --- a/lib/workers/repository/process/lookup/index.js +++ b/lib/workers/repository/process/lookup/index.js @@ -102,7 +102,8 @@ async function lookupUpdates(config) { config, fromVersion, dependency.latestVersion, - allVersions + allVersions, + releases ); if (!filteredVersions.length) { return res; diff --git a/test/datasource/__snapshots__/npm.spec.js.snap b/test/datasource/__snapshots__/npm.spec.js.snap index 68ed4c27fd..dbed38b2aa 100644 --- a/test/datasource/__snapshots__/npm.spec.js.snap +++ b/test/datasource/__snapshots__/npm.spec.js.snap @@ -146,6 +146,7 @@ Marking the latest version of an npm package as deprecated results in the entire Object { "canBeUnpublished": false, "gitRef": undefined, + "isDeprecated": true, "releaseTimestamp": "2018-05-07T07:21:53+02:00", "version": "0.0.2", }, diff --git a/test/workers/repository/process/lookup/__snapshots__/index.spec.js.snap b/test/workers/repository/process/lookup/__snapshots__/index.spec.js.snap index 248972d544..63d8a42d37 100644 --- a/test/workers/repository/process/lookup/__snapshots__/index.spec.js.snap +++ b/test/workers/repository/process/lookup/__snapshots__/index.spec.js.snap @@ -121,6 +121,43 @@ Array [ ] `; +exports[`manager/npm/lookup .lookupUpdates() ignores deprecated 1`] = ` +Object { + "deprecationMessage": "On registry \`https://registry.npmjs.org/\`, the \\"latest\\" version (v1.4.1) of dependency \`q2\` has the following deprecation notice: + +\`true\` + +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.", + "releases": Array [ + Object { + "canBeUnpublished": false, + "gitRef": "b26cace16f6070e756b6a546cf2693bece03f8f8", + "releaseTimestamp": "2015-04-26T16:42:11.311Z", + "version": "1.3.0", + }, + Object { + "canBeUnpublished": false, + "gitRef": "05e20dc704421ca820553721c7178168a8461506", + "releaseTimestamp": "2015-05-09T16:52:40.699Z", + "version": "1.4.0", + }, + ], + "repositoryUrl": "https://github.com/kriskowal/q", + "updates": Array [ + Object { + "canBeUnpublished": false, + "fromVersion": "1.3.0", + "newMajor": 1, + "newMinor": 4, + "newValue": "1.4.0", + "releaseTimestamp": "2015-05-09T16:52:40.699Z", + "toVersion": "1.4.0", + "updateType": "minor", + }, + ], +} +`; + exports[`manager/npm/lookup .lookupUpdates() ignores pinning for ranges when other upgrade exists 1`] = ` Array [ Object { diff --git a/test/workers/repository/process/lookup/index.spec.js b/test/workers/repository/process/lookup/index.spec.js index a0f1bad64f..8fd4807ae6 100644 --- a/test/workers/repository/process/lookup/index.spec.js +++ b/test/workers/repository/process/lookup/index.spec.js @@ -858,5 +858,20 @@ describe('manager/npm/lookup', () => { expect(res.releases).toHaveLength(3); expect(res.repositoryUrl).toBeDefined(); }); + it('ignores deprecated', async () => { + config.currentValue = '1.3.0'; + config.depName = 'q2'; + config.purl = 'pkg:npm/q2'; + const returnJson = JSON.parse(JSON.stringify(qJson)); + returnJson.name = 'q2'; + returnJson.versions['1.4.1'].deprecated = 'true'; + nock('https://registry.npmjs.org') + .get('/q2') + .reply(200, returnJson); + const res = await lookup.lookupUpdates(config); + expect(res).toMatchSnapshot(); + expect(res.releases).toHaveLength(2); + expect(res.updates[0].toVersion).toEqual('1.4.0'); + }); }); }); diff --git a/website/docs/configuration-options.md b/website/docs/configuration-options.md index 30bd58f7c4..48be7c0962 100644 --- a/website/docs/configuration-options.md +++ b/website/docs/configuration-options.md @@ -216,6 +216,10 @@ By default, Renovate will "slugify" the groupName to determine the branch name. And then the branchName would be `renovate/eslint` instead. +## ignoreDeprecated + +By default, Renovate won't update any packages to deprecated versions unless the package version was _already_ deprecated. The goal of this is to make sure you don't upgrade from a non-deprecated version to a deprecated one just because it's higher than the current version. If for some reason you wish to _force_ deprecated updates on Renovate, you can set `ignoreDeprecated` to `false`, but this is not recommended for most situations. + ## ignoreDeps The `ignoreDeps` configuration field allows you to define a list of dependency names to be ignored by Renovate. Currently it supports only "exact match" dependency names and not any patterns. e.g. to ignore both `eslint` and `eslint-config-base` you would add this to your config: -- GitLab