diff --git a/docs/configuration.md b/docs/configuration.md index baaefc4fbaee5c08c1c1b614dbcbb7a665e48613..ee0dc18522dd19ad5a3da4ca61cf09ce0baa87ae 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -84,7 +84,6 @@ $ node renovate --help --github-app-key <string> GitHub App Private Key (.pem file contents) --package-files <list> Package file paths --ignore-node-modules [boolean] Skip any package.json files found within node_modules folders - --dep-types <list> Dependency types --ignore-deps <list> Dependencies to ignore --pin-versions [boolean] Convert ranged versions in package.json to pinned versions --separate-major-releases [boolean] If set to false, it will upgrade dependencies to latest release only, and not separate major/minor branches @@ -289,17 +288,36 @@ Obviously, you can't set repository or package file location with this method. <td>`--ignore-node-modules`<td> </tr> <tr> - <td>`depTypes`</td> - <td>Dependency types</td> - <td>list</td> - <td><pre>[ - {"depType": "dependencies", "semanticPrefix": "fix(deps): "}, - "devDependencies", - "optionalDependencies", - {"depType": "peerDependencies", "enabled": false} -]</pre></td> - <td>`RENOVATE_DEP_TYPES`</td> - <td>`--dep-types`<td> + <td>`dependencies`</td> + <td>Configuration specifically for `package.json`>`dependencies`</td> + <td>json</td> + <td><pre>{}</pre></td> + <td>`RENOVATE_DEPENDENCIES`</td> + <td><td> +</tr> +<tr> + <td>`devDependencies`</td> + <td>Configuration specifically for `package.json`>`devDependencies`</td> + <td>json</td> + <td><pre>{}</pre></td> + <td>`RENOVATE_DEV_DEPENDENCIES`</td> + <td><td> +</tr> +<tr> + <td>`optionalDependencies`</td> + <td>Configuration specifically for `package.json`>`optionalDependencies`</td> + <td>json</td> + <td><pre>{}</pre></td> + <td>`RENOVATE_OPTIONAL_DEPENDENCIES`</td> + <td><td> +</tr> +<tr> + <td>`peerDependencies`</td> + <td>Configuration specifically for `package.json`>`peerDependencies`</td> + <td>json</td> + <td><pre>{"enabled": false}</pre></td> + <td>`RENOVATE_PEER_DEPENDENCIES`</td> + <td><td> </tr> <tr> <td>`ignoreDeps`</td> diff --git a/lib/config/definitions.js b/lib/config/definitions.js index b62bb7f83ad6fa4f982d4022bd94dc2ce96ab83a..4db8770badac9a5e0d24ae599d71dfa1b054abb3 100644 --- a/lib/config/definitions.js +++ b/lib/config/definitions.js @@ -142,17 +142,43 @@ const options = [ stage: 'repository', }, { - name: 'depTypes', - description: 'Dependency types', + name: 'dependencies', + description: 'Configuration specifically for `package.json`>`dependencies`', stage: 'packageFile', - type: 'list', - default: [ - { depType: 'dependencies', semanticPrefix: 'fix(deps): ' }, - 'devDependencies', - 'optionalDependencies', - { depType: 'peerDependencies', enabled: false }, - ], + type: 'json', + default: {}, + mergeable: true, + cli: false, + }, + { + name: 'devDependencies', + description: + 'Configuration specifically for `package.json`>`devDependencies`', + stage: 'packageFile', + type: 'json', + default: {}, mergeable: true, + cli: false, + }, + { + name: 'optionalDependencies', + description: + 'Configuration specifically for `package.json`>`optionalDependencies`', + stage: 'packageFile', + type: 'json', + default: {}, + mergeable: true, + cli: false, + }, + { + name: 'peerDependencies', + description: + 'Configuration specifically for `package.json`>`peerDependencies`', + stage: 'packageFile', + type: 'json', + default: { enabled: false }, + mergeable: true, + cli: false, }, // depType { diff --git a/lib/config/index.js b/lib/config/index.js index b5439da3815944a2d8bca08bc830e058ca773b04..81bee9201e02e95e20bb34353f4acd016142bfc0 100644 --- a/lib/config/index.js +++ b/lib/config/index.js @@ -118,32 +118,13 @@ function mergeChildConfig(parentConfig, childConfig) { for (const option of definitions.getOptions()) { if (option.mergeable && childConfig[option.name]) { logger.debug(`mergeable option: ${option.name}`); - if (option.name === 'depTypes') { - const depTypes = []; - for (let parent of parentConfig.depTypes) { - if (typeof parent === 'string') { - parent = { depType: parent }; - } - for (let child of childConfig.depTypes) { - if (typeof child === 'string') { - child = { depType: child }; - } - if (parent.depType === child.depType) { - Object.assign(parent, child); - } - } - depTypes.push(parent); - } - config.depTypes = depTypes; - } else { - config[option.name] = Object.assign( - {}, - parentConfig[option.name], - childConfig[option.name] - ); - } - logger.debug({ option: config[option.name] }, `config.${option.name}`); + config[option.name] = Object.assign( + {}, + parentConfig[option.name], + childConfig[option.name] + ); } + logger.trace({ value: config[option.name] }, `config.${option.name}`); } return config; } diff --git a/lib/config/migration.js b/lib/config/migration.js index 13d98b66e337d2b5374e128efd9d552be8eb298d..9c017cf294b93320cd6997939face4f853480021 100644 --- a/lib/config/migration.js +++ b/lib/config/migration.js @@ -20,10 +20,26 @@ function migrateConfig(config) { let isMigrated = false; const migratedConfig = Object.assign({}, config); for (const key of Object.keys(config)) { + const val = config[key]; if (removedOptions.includes(key)) { isMigrated = true; delete migratedConfig[key]; + } else if (key === 'depTypes' && Array.isArray(val)) { + val.forEach(depType => { + if (isObject(depType)) { + const depTypeName = depType.depType; + if (depTypeName) { + migratedConfig[depTypeName] = Object.assign({}, depType); + delete migratedConfig[depTypeName].depType; + } + } + }); + delete migratedConfig.depTypes; } } return { isMigrated, migratedConfig }; } + +function isObject(obj) { + return Object.prototype.toString.call(obj) === '[object Object]'; +} diff --git a/lib/workers/package-file/index.js b/lib/workers/package-file/index.js index 7c31db63e4e758e9c2495d1028a7a27dbed64ac7..3ac26cf119ffaa1ab443fcd4634721a5bbf2f0aa 100644 --- a/lib/workers/package-file/index.js +++ b/lib/workers/package-file/index.js @@ -8,7 +8,6 @@ let logger = require('../../logger'); module.exports = { renovatePackageFile, - getDepTypeConfig, }; async function renovatePackageFile(packageFileConfig) { @@ -72,7 +71,7 @@ async function renovatePackageFile(packageFileConfig) { */ } // package.json>renovate config takes precedence over existing config - config = configParser.mergeChildConfig(config, packageContent.renovate); + config = configParser.mergeChildConfig(config, migratedConfig); } else { logger.debug('Package file has no renovate configuration'); } @@ -82,9 +81,26 @@ async function renovatePackageFile(packageFileConfig) { return upgrades; } - const depTypeConfigs = config.depTypes.map(depType => - module.exports.getDepTypeConfig(config, depType) - ); + const depTypes = [ + 'dependencies', + 'devDependencies', + 'optionalDependencies', + 'peerDependencies', + ]; + const depTypeConfigs = depTypes.map(depType => { + const depTypeConfig = configParser.mergeChildConfig( + packageFileConfig, + packageFileConfig[depType] + ); + depTypeConfig.depType = depType; + depTypeConfig.logger = logger.child({ + repository: depTypeConfig.repository, + packageFile: depTypeConfig.packageFile, + depType: depTypeConfig.depType, + }); + logger.debug({ config: depTypeConfig }, 'depTypeConfig'); + return configParser.filterConfig(depTypeConfig, 'depType'); + }); logger.trace({ config: depTypeConfigs }, `depTypeConfigs`); for (const depTypeConfig of depTypeConfigs) { upgrades = upgrades.concat( @@ -128,17 +144,3 @@ async function renovatePackageFile(packageFileConfig) { logger.info('Finished processing package file'); return upgrades; } - -function getDepTypeConfig(packageFileConfig, depType) { - let depTypeConfig = typeof depType === 'string' ? { depType } : depType; - depTypeConfig = configParser.mergeChildConfig( - packageFileConfig, - depTypeConfig - ); - depTypeConfig.logger = logger.child({ - repository: depTypeConfig.repository, - packageFile: depTypeConfig.packageFile, - depType: depTypeConfig.depType, - }); - return configParser.filterConfig(depTypeConfig, 'depType'); -} diff --git a/lib/workers/repository/apis.js b/lib/workers/repository/apis.js index b893f0e8f119e8d12545c1877d553e80fa389898..a95bf979bb53bd6a9c6342ac2493f71aa567699e 100644 --- a/lib/workers/repository/apis.js +++ b/lib/workers/repository/apis.js @@ -146,7 +146,7 @@ async function mergeRenovateJson(config, branchName) { ); }); */ } - returnConfig = configParser.mergeChildConfig(returnConfig, renovateJson); + returnConfig = configParser.mergeChildConfig(returnConfig, migratedConfig); returnConfig.renovateJsonPresent = true; } catch (err) { // Add to config.errors diff --git a/lib/workers/repository/onboarding.js b/lib/workers/repository/onboarding.js index 258a6908bf7243cd3950e8129ccb102c70690716..87190e29538820e30680f2e882893efc8e95cd01 100644 --- a/lib/workers/repository/onboarding.js +++ b/lib/workers/repository/onboarding.js @@ -49,12 +49,9 @@ async function createBranch(config) { config.logger.debug('Repo is private - pinning dependencies versions'); } else { config.logger.debug('Repo is not private - unpinning versions'); - onboardingConfig.depTypes = [ - { - depType: 'dependencies', - pinVersions: false, - }, - ]; + onboardingConfig.dependencies = { + pinVersions: false, + }; } if (config.foundNodeModules) { onboardingConfig.ignoreNodeModules = true; diff --git a/test/config/__snapshots__/index.spec.js.snap b/test/config/__snapshots__/index.spec.js.snap index 9b7d4174d2e91eb6029b93b256988e7bed300d6c..b0d69c50a6a2f3fa2bef7106f6eef213bf57f2f3 100644 --- a/test/config/__snapshots__/index.spec.js.snap +++ b/test/config/__snapshots__/index.spec.js.snap @@ -47,41 +47,4 @@ This {{#if isGitHub}}PR{{else}}MR{{/if}} has been generated by [Renovate Bot](ht } `; -exports[`config/index mergeChildConfig(parentConfig, childConfig) merges depTypes with meaningful child 1`] = ` -Array [ - Object { - "depType": "dependencies", - "semanticPrefix": "fix(deps): ", - }, - Object { - "depType": "devDependencies", - "foo": 1, - }, - Object { - "depType": "optionalDependencies", - }, - Object { - "depType": "peerDependencies", - "enabled": false, - }, -] -`; - -exports[`config/index mergeChildConfig(parentConfig, childConfig) merges depTypes with no child config 1`] = ` -Array [ - Object { - "depType": "dependencies", - "semanticPrefix": "fix(deps): ", - }, - Object { - "depType": "devDependencies", - }, - Object { - "depType": "optionalDependencies", - }, - Object { - "depType": "peerDependencies", - "enabled": false, - }, -] -`; +exports[`config/index mergeChildConfig(parentConfig, childConfig) merges depTypes 1`] = `undefined`; diff --git a/test/config/__snapshots__/migration.spec.js.snap b/test/config/__snapshots__/migration.spec.js.snap index 4367759db09122eaead5805737e036c2c66977d9..6ea6cee4fc195e1059a456412ee6be32e7a901e0 100644 --- a/test/config/__snapshots__/migration.spec.js.snap +++ b/test/config/__snapshots__/migration.spec.js.snap @@ -3,5 +3,8 @@ exports[`config/migration migrateConfig(config) it migrates config 1`] = ` Object { "enabled": true, + "optionalDependencies": Object { + "respectLatest": false, + }, } `; diff --git a/test/config/index.spec.js b/test/config/index.spec.js index 206789ed946d8aa681be7ef30fe639cd0f7b4428..5a23ceb0ea0d91797f313b030279dbd95e4fe1be 100644 --- a/test/config/index.spec.js +++ b/test/config/index.spec.js @@ -162,26 +162,12 @@ describe('config/index', () => { expect(config.lockFileMaintenance.schedule).toEqual('on monday'); expect(config.lockFileMaintenance).toMatchSnapshot(); }); - it('merges depTypes with no child config', () => { + it('merges depTypes', () => { const parentConfig = Object.assign({}, defaultConfig); const childConfig = { - depTypes: ['dependencies'], - }; - const configParser = require('../../lib/config/index.js'); - const config = configParser.mergeChildConfig(parentConfig, childConfig); - expect(config.depTypes).toMatchSnapshot(); - }); - it('merges depTypes with meaningful child', () => { - const parentConfig = Object.assign({}, defaultConfig); - const childConfig = { - depTypes: [ - 'dependencies', - { - depType: 'devDependencies', - foo: 1, - }, - 'peerDependencies', - ], + dependencies: {}, + devDependencies: { foo: 1 }, + peerDependencies: {}, }; const configParser = require('../../lib/config/index.js'); const config = configParser.mergeChildConfig(parentConfig, childConfig); diff --git a/test/config/migration.spec.js b/test/config/migration.spec.js index 120aab658c72cd7b1f3b54021236d593cbe82c5a..eebde0d06b8a47ff61ba3e935a30d4b73eb0c78b 100644 --- a/test/config/migration.spec.js +++ b/test/config/migration.spec.js @@ -6,11 +6,20 @@ describe('config/migration', () => { const config = { enabled: true, maintainYarnLock: true, + depTypes: [ + 'dependencies', + { + depType: 'optionalDependencies', + respectLatest: false, + }, + ], }; const { isMigrated, migratedConfig } = configMigration.migrateConfig( config ); expect(isMigrated).toBe(true); + expect(migratedConfig.depTypes).not.toBeDefined(); + expect(migratedConfig.optionalDependencies.respectLatest).toBe(false); expect(migratedConfig).toMatchSnapshot(); }); it('it does not migrate config', () => { diff --git a/test/workers/package-file/index.spec.js b/test/workers/package-file/index.spec.js index 4223c385872f550b37af771593ee9797b642e721..859b0b8452f5a2912be7809d66d3ccf4998f77a1 100644 --- a/test/workers/package-file/index.spec.js +++ b/test/workers/package-file/index.spec.js @@ -18,7 +18,6 @@ describe('packageFileWorker', () => { getFileContent: jest.fn(), getFileJson: jest.fn(), }, - depTypes: ['dependencies', 'devDependencies'], logger, }); }); @@ -66,6 +65,8 @@ describe('packageFileWorker', () => { config.api.getFileJson.mockReturnValueOnce({}); depTypeWorker.renovateDepType.mockReturnValueOnce([{}]); depTypeWorker.renovateDepType.mockReturnValueOnce([{}, {}]); + depTypeWorker.renovateDepType.mockReturnValueOnce([]); + depTypeWorker.renovateDepType.mockReturnValueOnce([]); const res = await packageFileWorker.renovatePackageFile(config); expect(res).toHaveLength(3); }); @@ -73,8 +74,7 @@ describe('packageFileWorker', () => { config.api.getFileJson.mockReturnValueOnce({}); config.api.getFileContent.mockReturnValueOnce('some-content-1'); config.api.getFileContent.mockReturnValueOnce('some-content-2'); - depTypeWorker.renovateDepType.mockReturnValueOnce([]); - depTypeWorker.renovateDepType.mockReturnValueOnce([]); + depTypeWorker.renovateDepType.mockReturnValue([]); const res = await packageFileWorker.renovatePackageFile(config); expect(res).toHaveLength(1); }); diff --git a/test/workers/repository/__snapshots__/onboarding.spec.js.snap b/test/workers/repository/__snapshots__/onboarding.spec.js.snap index d259073455fc7a4eb73e6a27e2a7597948539ae5..56e97505d5b7657a8bfbcd51799b3581b2da9a06 100644 --- a/test/workers/repository/__snapshots__/onboarding.spec.js.snap +++ b/test/workers/repository/__snapshots__/onboarding.spec.js.snap @@ -218,7 +218,7 @@ Array [ Object { "contents": "{ \\"pinVersions\\": true, - \\"depTypes\\": [{\\"depType\\": \\"dependencies\\", \\"pinVersions\\": false}], + \\"dependencies\\": {\\"pinVersions\\": false}, \\"ignoreNodeModules\\": true } ", @@ -236,7 +236,7 @@ Array [ Object { "contents": "{ \\"pinVersions\\": true, - \\"depTypes\\": [{\\"depType\\": \\"dependencies\\", \\"pinVersions\\": false}], + \\"dependencies\\": {\\"pinVersions\\": false}, \\"ignoreNodeModules\\": true } ", @@ -255,7 +255,7 @@ Array [ "contents": "{ \\"pinVersions\\": true, \\"semanticCommits\\": true, - \\"depTypes\\": [{\\"depType\\": \\"dependencies\\", \\"pinVersions\\": false}], + \\"dependencies\\": {\\"pinVersions\\": false}, \\"ignoreNodeModules\\": true } ", diff --git a/test/workers/repository/onboarding.spec.js b/test/workers/repository/onboarding.spec.js index 623748329c54d61419aba9b405dffbef3f9c8264..3e6cd815ecb0e1ee8ad6c22145ce9b52d22887f1 100644 --- a/test/workers/repository/onboarding.spec.js +++ b/test/workers/repository/onboarding.spec.js @@ -281,12 +281,8 @@ describe('lib/workers/repository/onboarding', () => { expect(config.api.commitFilesToBranch.mock.calls[0]).toMatchSnapshot(); }); it('skips commit files if existing content matches', async () => { - const existingContent = `{ - "pinVersions": true, - "depTypes": [{"depType": "dependencies", "pinVersions": false}], - "ignoreNodeModules": true -} -`; + const existingContent = + '{\n "pinVersions": true,\n "dependencies": {"pinVersions": false},\n "ignoreNodeModules": true\n}\n'; config.api.getFileContent.mockReturnValueOnce(existingContent); const res = await onboarding.getOnboardingStatus(config); expect(res).toEqual(false);