diff --git a/lib/config/definitions.js b/lib/config/definitions.js index 024377e0063b31ba996c4a3d38f04febd81558a7..52ea17761f94d293d1e6f2f36980f5411fe041e0 100644 --- a/lib/config/definitions.js +++ b/lib/config/definitions.js @@ -14,6 +14,7 @@ function template(name, subdir = 'default/') { module.exports = { getOptions, + getDeprecatedOptions, }; const options = [ @@ -373,3 +374,19 @@ const options = [ function getOptions() { return options; } + +const deprecatedOptions = [ + 'maintainYarnLock', + 'yarnMaintenanceBranchName', + 'yarnMaintenanceCommitMessage', + 'yarnMaintenancePrTitle', + 'yarnMaintenancePrBody', + 'groupBranchName', + 'groupBranchName', + 'groupPrTitle', + 'groupPrBody', +]; + +function getDeprecatedOptions() { + return deprecatedOptions; +} diff --git a/lib/config/validation.js b/lib/config/validation.js index 993dc1ee91b8c99d91423d8923d7144bc9bffa7f..4d4a38b635383b4ca2b83a20361b29fa017cdd4d 100644 --- a/lib/config/validation.js +++ b/lib/config/validation.js @@ -1,4 +1,5 @@ const options = require('./definitions').getOptions(); +const deprecatedOptions = require('./definitions').getDeprecatedOptions(); const optionTypes = {}; options.forEach(option => { @@ -11,6 +12,7 @@ module.exports = { function validateConfig(config) { let errors = []; + let warnings = []; function isIgnored(key) { const ignoredNodes = ['api', 'depType']; @@ -26,9 +28,12 @@ function validateConfig(config) { return Object.prototype.toString.call(obj) === '[object Object]'; } + const foundDeprecated = []; for (const key of Object.keys(config)) { let val = config[key]; - if ( + if (deprecatedOptions.includes(key)) { + foundDeprecated.push(key); + } else if ( !isIgnored(key) && // We need to ignore some reserved keys !isAFunction(val) // Ignore all functions ) { @@ -72,7 +77,9 @@ function validateConfig(config) { } } else if (type === 'json') { if (isObject(val)) { - errors = errors.concat(module.exports.validateConfig(val)); + const subValidation = module.exports.validateConfig(val); + warnings = warnings.concat(subValidation.warnings); + errors = errors.concat(subValidation.errors); } else { errors.push({ depName: 'Configuration Error', @@ -83,5 +90,11 @@ function validateConfig(config) { } } } - return errors; + if (foundDeprecated.length) { + warnings.push({ + depName: 'Deprecation warning', + message: `The following configutation options are now unsupported and should be removed from renovate.json: ${foundDeprecated}`, + }); + } + return { errors, warnings }; } diff --git a/lib/workers/global/index.js b/lib/workers/global/index.js index 9118166c5b15cdb8204770d6abaceea8d7b48b75..1b74ca1456857b1e99806839d110ef7b514b0d4f 100644 --- a/lib/workers/global/index.js +++ b/lib/workers/global/index.js @@ -12,9 +12,12 @@ module.exports = { async function start() { try { const config = await configParser.parseConfigs(process.env, process.argv); - const configErrors = configValidation.validateConfig(config); - if (configErrors.length) { - logger.error({ configErrors }, 'Found config errors'); + const { warnings, errors } = configValidation.validateConfig(config); + if (warnings.length) { + logger.warn({ warnings }, 'Found config warnings'); + } + if (errors.length) { + logger.error({ errors }, 'Found config errors'); } config.logger = logger; config.versions = versions.detectVersions(config); diff --git a/lib/workers/package-file/index.js b/lib/workers/package-file/index.js index 267d488a70d420f27f96d133efac65d1f1d6f907..ac1d2a99e4e29cd43607ce9f444946ebd333fadf 100644 --- a/lib/workers/package-file/index.js +++ b/lib/workers/package-file/index.js @@ -35,7 +35,15 @@ async function renovatePackageFile(packageFileConfig) { { config: packageContent.renovate }, 'package.json>renovate config' ); - const errors = configValidation.validateConfig(packageContent.renovate); + const { warnings, errors } = configValidation.validateConfig( + packageContent.renovate + ); + if (warnings.length) { + logger.debug( + { warnings }, + 'Found package.json>renovate configuration warnings' + ); + } if (errors.length) { logger.warn( { errors }, diff --git a/lib/workers/repository/apis.js b/lib/workers/repository/apis.js index 97afea74b5074c113691fd3fdcc63b9b61d43c70..d627768589a87b56d94b22e5a5f639e209d82ee9 100644 --- a/lib/workers/repository/apis.js +++ b/lib/workers/repository/apis.js @@ -120,9 +120,12 @@ async function mergeRenovateJson(config, branchName) { } renovateJson = JSON.parse(renovateJsonContent); config.logger.debug({ config: renovateJson }, 'renovate.json config'); - const renovateJsonErrors = configValidation.validateConfig(renovateJson); - if (renovateJsonErrors.length) { - config.logger.warn({ renovateJsonErrors }, 'Found renovate.json errors'); + const { warnings, errors } = configValidation.validateConfig(renovateJson); + if (warnings.length) { + config.logger.debug({ warnings }, 'Found renovate.json warnings'); + } + if (errors.length) { + config.logger.warn({ errors }, 'Found renovate.json errors'); /* TODO #556 renovateJsonErrors.forEach(error => { config.errors.push( diff --git a/test/config/validation.spec.js b/test/config/validation.spec.js index bb5c210fec1725a816c314dd9bbfaf94ac642212..1c0db1422c2363b0df740e174a1e6e0b2a6ba2b0 100644 --- a/test/config/validation.spec.js +++ b/test/config/validation.spec.js @@ -11,7 +11,8 @@ describe('config/validation', () => { bar: 2, }, }; - const errors = configValidation.validateConfig(config); + const { warnings, errors } = configValidation.validateConfig(config); + expect(warnings).toHaveLength(0); expect(errors).toHaveLength(2); expect(errors).toMatchSnapshot(); }); @@ -23,7 +24,8 @@ describe('config/validation', () => { githubAppId: 'none', lockFileMaintenance: false, }; - const errors = configValidation.validateConfig(config); + const { warnings, errors } = configValidation.validateConfig(config); + expect(warnings).toHaveLength(0); expect(errors).toHaveLength(5); expect(errors).toMatchSnapshot(); }); diff --git a/test/workers/global/index.spec.js b/test/workers/global/index.spec.js index 551f8a41b9649df5667e5409f37a50aec737ae55..c70c580efbbf8324a5da448b527e21b5541fe80c 100644 --- a/test/workers/global/index.spec.js +++ b/test/workers/global/index.spec.js @@ -11,9 +11,10 @@ describe('lib/workers/global', () => { configParser.getRepositoryConfig = jest.fn(); repositoryWorker.renovateRepository = jest.fn(); }); - it('handles config errors', async () => { + it('handles config warnings and errors', async () => { configParser.parseConfigs.mockReturnValueOnce({ repositories: [], + maintainYarnLock: true, foo: 1, }); await globalWorker.start(); diff --git a/test/workers/package-file/__snapshots__/index.spec.js.snap b/test/workers/package-file/__snapshots__/index.spec.js.snap index c1631b61984beb5b13be226919b43d43c2efd80d..6652c791e1a7d645d41a098f00a10b9e3717fe09 100644 --- a/test/workers/package-file/__snapshots__/index.spec.js.snap +++ b/test/workers/package-file/__snapshots__/index.spec.js.snap @@ -1,3 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`packageFileWorker renovatePackageFile(config) handles renovate config errors 1`] = `Array []`; +exports[`packageFileWorker renovatePackageFile(config) handles renovate config warnings and errors 1`] = `Array []`; diff --git a/test/workers/package-file/index.spec.js b/test/workers/package-file/index.spec.js index 2141b83bf79856d35b7fcb86142aed68aba1d897..4223c385872f550b37af771593ee9797b642e721 100644 --- a/test/workers/package-file/index.spec.js +++ b/test/workers/package-file/index.spec.js @@ -22,9 +22,11 @@ describe('packageFileWorker', () => { logger, }); }); - it('handles renovate config errors', async () => { + it('handles renovate config warnings and errors', async () => { config.enabled = false; - config.api.getFileJson.mockReturnValueOnce({ renovate: { foo: 1 } }); + config.api.getFileJson.mockReturnValueOnce({ + renovate: { foo: 1, maintainYarnLock: true }, + }); const res = await packageFileWorker.renovatePackageFile(config); expect(res).toMatchSnapshot(); }); diff --git a/test/workers/repository/__snapshots__/apis.spec.js.snap b/test/workers/repository/__snapshots__/apis.spec.js.snap index c9858fc3fe527d15a2466cefcf9f13e837451040..143e1e3f2a1881943a2ba7c2e32a9dea8c7eb360 100644 --- a/test/workers/repository/__snapshots__/apis.spec.js.snap +++ b/test/workers/repository/__snapshots__/apis.spec.js.snap @@ -66,4 +66,4 @@ Array [ ] `; -exports[`workers/repository/apis mergeRenovateJson(config) returns error plus extended config if unknown keys 1`] = `Array []`; +exports[`workers/repository/apis mergeRenovateJson(config) returns warning + error plus extended config if unknown keys 1`] = `Array []`; diff --git a/test/workers/repository/apis.spec.js b/test/workers/repository/apis.spec.js index 4ece3f4b6d3ecb107f0ddf0a6d518b53ae873e63..39a1503ac77e2f6cca048d85e2aef72971cab1c9 100644 --- a/test/workers/repository/apis.spec.js +++ b/test/workers/repository/apis.spec.js @@ -135,9 +135,9 @@ describe('workers/repository/apis', () => { expect(returnConfig.renovateJsonPresent).toBe(true); expect(returnConfig.errors).toHaveLength(0); }); - it('returns error plus extended config if unknown keys', async () => { + it('returns warning + error plus extended config if unknown keys', async () => { config.api.getFileContent.mockReturnValueOnce( - '{ "enabled": true, "foo": false }' + '{ "enabled": true, "foo": false, "maintainYarnLock": true }' ); const returnConfig = await apis.mergeRenovateJson(config); expect(returnConfig.enabled).toBe(true); diff --git a/test/workers/repository/index.spec.js b/test/workers/repository/index.spec.js index dffe0fe3d6055cbadf3dd9ddf018c64484971a71..1c5d73be5cc6b544c507b9c3d701a2a0ef21b941 100644 --- a/test/workers/repository/index.spec.js +++ b/test/workers/repository/index.spec.js @@ -21,6 +21,7 @@ describe('workers/repository', () => { upgrades.branchifyUpgrades = jest.fn(() => ({ branchUpgrades: {} })); branchWorker.processBranchUpgrades = jest.fn(() => 'some-branch'); config = { + lockFileMaintenance: true, api: { getFileJson: jest.fn(), setBaseBranch: jest.fn(),