diff --git a/lib/config/definitions.js b/lib/config/definitions.js index bdded628db61d120cc873710d26dfab15af1ea0c..bab0d6f0ae7b83833bdff08e630054dc8f22a951 100644 --- a/lib/config/definitions.js +++ b/lib/config/definitions.js @@ -378,6 +378,14 @@ const options = [ env: false, }, // Version behaviour + { + name: 'allowedVersions', + description: 'A semver range defining allowed versions for dependencies', + type: 'string', + stage: 'package', + cli: false, + env: false, + }, { name: 'pinDigests', description: 'Whether to add digests to Dockerfile source images', diff --git a/lib/config/validation.js b/lib/config/validation.js index 836fbd0ef43b15368f6713ccbdaa7f0bf9a32b03..e0fe44d25eb23575bb8ce7c91f109e4e4f6bca3a 100644 --- a/lib/config/validation.js +++ b/lib/config/validation.js @@ -1,3 +1,4 @@ +const semver = require('semver'); const options = require('./definitions').getOptions(); const { hasValidSchedule } = require('../workers/branch/schedule'); @@ -60,6 +61,13 @@ function validateConfig(config) { message: `Invalid schedule: \`${errorMessage}\``, }); } + } else if (key === 'allowedVersions' && val !== null) { + if (!semver.validRange(val)) { + errors.push({ + depName: 'Configuration Error', + message: `Invalid semver range for allowedVersions: \`${val}\``, + }); + } } else if (val != null) { const type = optionTypes[key]; if (type === 'boolean') { diff --git a/lib/workers/package/versions.js b/lib/workers/package/versions.js index 4ee23863881c1f34201b9e0919920153516515d1..83b5d32b4821bcdfb1df25935f04ea077fd0be5b 100644 --- a/lib/workers/package/versions.js +++ b/lib/workers/package/versions.js @@ -18,7 +18,12 @@ function determineUpgrades(npmDep, config) { const result = { type: 'warning', }; - const { currentVersion, lockedVersion, pinVersions } = config; + const { + currentVersion, + lockedVersion, + pinVersions, + allowedVersions, + } = config; const { versions } = npmDep; if (!versions || Object.keys(versions).length === 0) { result.message = `No versions returned from registry for this package`; @@ -82,6 +87,10 @@ function determineUpgrades(npmDep, config) { _(versionList) // Filter out older versions as we can't upgrade to those .filter(version => semver.gt(version, changeLogFromVersion)) + // fillter out non-allowed versions if preference is set + .reject( + version => allowedVersions && !semver.satisfies(version, allowedVersions) + ) // Ignore unstable versions, unless the current version is unstable .reject( version => diff --git a/test/config/__snapshots__/validation.spec.js.snap b/test/config/__snapshots__/validation.spec.js.snap index 63af4b2400174b152853531fc5bfbdace882a2ad..fcc172e25b9edcca991af685377806a2409c0a88 100644 --- a/test/config/__snapshots__/validation.spec.js.snap +++ b/test/config/__snapshots__/validation.spec.js.snap @@ -2,6 +2,10 @@ exports[`config/validation validateConfig(config) errors for all types 1`] = ` Array [ + Object { + "depName": "Configuration Error", + "message": "Invalid semver range for allowedVersions: \`foo\`", + }, Object { "depName": "Configuration Error", "message": "Configuration option \`enabled\` should be boolean. Found: 1 (number)", diff --git a/test/config/validation.spec.js b/test/config/validation.spec.js index 213386278a2f4dcbbc2698680c6cd2e133be3d98..3c2f725da2b687d58c8fcb5b015c5d4a299b6baf 100644 --- a/test/config/validation.spec.js +++ b/test/config/validation.spec.js @@ -18,6 +18,7 @@ describe('config/validation', () => { }); it('errors for all types', () => { const config = { + allowedVersions: 'foo', enabled: 1, schedule: ['every 15 mins every weekday'], labels: 5, @@ -31,7 +32,7 @@ describe('config/validation', () => { }; const { warnings, errors } = configValidation.validateConfig(config); expect(warnings).toHaveLength(0); - expect(errors).toHaveLength(6); + expect(errors).toHaveLength(7); expect(errors).toMatchSnapshot(); }); }); diff --git a/website/docs/_posts/2017-10-05-configuration-options.md b/website/docs/_posts/2017-10-05-configuration-options.md index a7b7e63aa4d0f2d68d1fe6b2988f86241edecfa9..834e5d68c65685bc2084d0ddfc9565be1f915979 100644 --- a/website/docs/_posts/2017-10-05-configuration-options.md +++ b/website/docs/_posts/2017-10-05-configuration-options.md @@ -14,6 +14,23 @@ Also, be sure to check out Renovate's [shareable config presets](/docs/configura If you have any questions about the below config options, or would like to get help/feedback about a config, please post it as an issue in [renovateapp/config-help](https://github.com/renovateapp/config-help) where it will be promptly answered. +## allowedVersions + +A semver range defining allowed versions for dependencies + +| name | value | +| ---- | ------ | +| type | string | + +Use this - usually within a packageRule - to limit how far to upgrade a dependency. For example, if you wish to upgrade to angular v1.5 but not to `angular` v1.6 or higher, you could defined this to be `<= 1.5` or `< 1.6.0`: + +``` + "packageRules": [{ + "packageNames": ["angular"], + "allowedVersions": "<=1.5" + }] +``` + ## assignees Assignees for Pull Requests