diff --git a/docs/configuration.md b/docs/configuration.md index 3fff9b9474bc37f1309a523db6c10faf65908241..c8d39f3f45d6e2f7c988645b53e6bf8d420866c1 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -328,26 +328,42 @@ Obviously, you can't set repository or package file location with this method. <td>`--ignore-deps`<td> </tr> <tr> - <td>`packages`</td> - <td>Package Rules</td> + <td>`packageRules`</td> + <td>Rules for matching package names</td> <td>list</td> <td><pre>[]</pre></td> <td></td> <td><td> </tr> <tr> - <td>`packageName`</td> - <td>A package name to match. Valid only within `packages` object</td> - <td>string</td> - <td><pre>null</pre></td> + <td>`packageNames`</td> + <td>Package names to match. Valid only within `packageRules` object</td> + <td>list</td> + <td><pre>[]</pre></td> <td></td> <td><td> </tr> <tr> - <td>`packagePattern`</td> - <td>A package name pattern to match. Valid only within `packages` object.</td> - <td>string</td> - <td><pre>null</pre></td> + <td>`excludePackageNames`</td> + <td>Package names to exclude. Valid only within `packageRules` object</td> + <td>list</td> + <td><pre>[]</pre></td> + <td></td> + <td><td> +</tr> +<tr> + <td>`packagePatterns`</td> + <td>Package name patterns to match. Valid only within `packageRules` object.</td> + <td>list</td> + <td><pre>[]</pre></td> + <td></td> + <td><td> +</tr> +<tr> + <td>`excludePackagePatterns`</td> + <td>Package name patterns to exclude. Valid only within `packageRules` object.</td> + <td>list</td> + <td><pre>[]</pre></td> <td></td> <td><td> </tr> diff --git a/docs/faq.md b/docs/faq.md index 80f2d3f862c2033d3e1d705f169ea74b587b8cc3..58533b9b58a3cb6ad1f37bf9c1c34156fa36be9d 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -73,7 +73,7 @@ To restrict `aws-sdk` to only weekly updates, you could add this package rule: ``` "packages": [ { - "packageName": "aws-sdk", + "packageNames": ["aws-sdk"], "schedule": ["after 9pm on sunday"] } ] @@ -128,7 +128,7 @@ Set the configuration option `labels` to an array of labels to use 1. Add a `packages` array to your configuration. 2. Create one object inside this array -3. Set field `packageName` to value `"abc"` +3. Set field `packageNames` to value `["abc"]` 4. Add the configuration option to the same object. e.g. @@ -136,7 +136,7 @@ e.g. ``` "packages": [ { - "packageName": "abc", + "packageNames": ["abc"], "assignees": ["importantreviewer"] } ] @@ -144,12 +144,12 @@ e.g. ### Apply a rule, but only for packages starting with `abc` -Do the same as above, but instead of using `packageName`, use `packagePattern` and a regex. e.g. +Do the same as above, but instead of using `packageNames`, use `packagePatterns` and a regex. e.g. ``` "packages": [ { - "packagePattern": "^abc", + "packagePatterns": "^abc", "assignees": ["importantreviewer"] } ] @@ -162,7 +162,7 @@ As above, but apply a `groupName`, e.g. ``` "packages": [ { - "packagePattern": "^abc", + "packagePatterns": "^abc", "groupName": ["abc packages"] } ] diff --git a/lib/config/definitions.js b/lib/config/definitions.js index 25bd51866ee4715e84806f5295f87dfcb51b5e15..3fdd14661fb5bc8deec575c152e24e17fc60d609 100644 --- a/lib/config/definitions.js +++ b/lib/config/definitions.js @@ -188,26 +188,45 @@ const options = [ stage: 'depType', }, { - name: 'packages', - description: 'Package Rules', + name: 'packageRules', + description: 'Rules for matching package names', type: 'list', stage: 'depType', cli: false, env: false, }, { - name: 'packageName', - description: 'A package name to match. Valid only within `packages` object', - type: 'string', + name: 'packageNames', + description: + 'Package names to match. Valid only within `packageRules` object', + type: 'list', stage: 'depType', cli: false, env: false, }, { - name: 'packagePattern', + name: 'excludePackageNames', description: - 'A package name pattern to match. Valid only within `packages` object.', - type: 'string', + 'Package names to exclude. Valid only within `packageRules` object', + type: 'list', + stage: 'depType', + cli: false, + env: false, + }, + { + name: 'packagePatterns', + description: + 'Package name patterns to match. Valid only within `packageRules` object.', + type: 'list', + stage: 'depType', + cli: false, + env: false, + }, + { + name: 'excludePackagePatterns', + description: + 'Package name patterns to exclude. Valid only within `packageRules` object.', + type: 'list', stage: 'depType', cli: false, env: false, diff --git a/lib/config/migration.js b/lib/config/migration.js index 473a0fe75eadf86e485d181c970e4f3aa585f8f4..7dec6805d7ec566b31a1f73ab4892509197549dd 100644 --- a/lib/config/migration.js +++ b/lib/config/migration.js @@ -27,6 +27,18 @@ function migrateConfig(config) { } else if (key === 'schedule' && typeof val === 'string') { isMigrated = true; migratedConfig.schedule = [val]; + } else if (key === 'packages') { + isMigrated = true; + migratedConfig.packageRules = migrateConfig(val); + delete migratedConfig.packages; + } else if (key === 'packageName') { + isMigrated = true; + migratedConfig.packageNames = [val]; + delete migratedConfig.packageName; + } else if (key === 'packagePattern') { + isMigrated = true; + migratedConfig.packagePatterns = [val]; + delete migratedConfig.packagePattern; } else if (key === 'depTypes' && Array.isArray(val)) { val.forEach(depType => { if (isObject(depType)) { diff --git a/lib/workers/dep-type/index.js b/lib/workers/dep-type/index.js index 746ba1c70e54ecaa2c2ba79789ee35d032b13e67..a4c6d454500c7177d0a2981e85576de356d21be5 100644 --- a/lib/workers/dep-type/index.js +++ b/lib/workers/dep-type/index.js @@ -57,20 +57,42 @@ async function renovateDepType(packageContent, config) { function getDepConfig(depTypeConfig, dep) { const depConfig = configParser.mergeChildConfig(depTypeConfig, dep); // Apply any matching package rules - if (depConfig.packages) { + if (depConfig.packageRules) { let packageRuleApplied = false; - depConfig.packages.forEach(packageConfig => { + depConfig.packageRules.forEach(packageRule => { // Apply at most 1 package fule if (!packageRuleApplied) { - const pattern = - packageConfig.packagePattern || `^${packageConfig.packageName}$`; - const packageRegex = new RegExp(pattern); - if (depConfig.depName.match(packageRegex)) { + if ( + packageRule.packageNames && + packageRule.packageNames.includes(depConfig.depName) + ) { packageRuleApplied = true; + } else if (packageRule.packagePatterns) { + for (const packagePattern of packageRule.packagePatterns) { + const packageRegex = new RegExp(packagePattern); + if (depConfig.depName.match(packageRegex)) { + packageRuleApplied = true; + } + } + } + if ( + packageRule.excludePackageNames && + packageRule.excludePackageNames.includes(depConfig.depName) + ) { + packageRuleApplied = false; + } else if (packageRule.excludePackagePatterns) { + for (const packagePattern of packageRule.excludePackagePatterns) { + const packageRegex = new RegExp(packagePattern); + if (depConfig.depName.match(packageRegex)) { + packageRuleApplied = false; + } + } + } + if (packageRuleApplied) { // Package rule config overrides any existing config - Object.assign(depConfig, packageConfig); - delete depConfig.packageName; - delete depConfig.packagePattern; + Object.assign(depConfig, packageRule); + delete depConfig.packageNames; + delete depConfig.packagePatterns; } } }); diff --git a/package.json b/package.json index 1e555165ccc8781ca23fc4f398e129899ae4962e..3d7b8db5c43d591bd80440efe7173486f9a508cc 100644 --- a/package.json +++ b/package.json @@ -118,7 +118,7 @@ "semanticCommits": true, "packages": [ { - "packagePattern": "jest", + "packagePatterns": "jest", "groupName": "jest" } ] diff --git a/test/config/__snapshots__/migration.spec.js.snap b/test/config/__snapshots__/migration.spec.js.snap index e7eebe819404fab8a5fa65bfaedc67afd61b20b6..8c7d0c1a2f15bff54d0db66e57011311395ebbed 100644 --- a/test/config/__snapshots__/migration.spec.js.snap +++ b/test/config/__snapshots__/migration.spec.js.snap @@ -6,6 +6,20 @@ Object { "optionalDependencies": Object { "respectLatest": false, }, + "packageRules": Object { + "isMigrated": true, + "migratedConfig": Object { + "0": Object { + "enabled": false, + "packageNames": Array [ + "angular", + ], + "packagePatterns": Array [ + "ang", + ], + }, + }, + }, "schedule": Array [ "after 5pm", ], diff --git a/test/config/migration.spec.js b/test/config/migration.spec.js index 5e3f8034f48b44ebf960d45a5a6cc2853cf85eaf..0632f6ce47140d504b648138795512348bf7f7d1 100644 --- a/test/config/migration.spec.js +++ b/test/config/migration.spec.js @@ -7,6 +7,13 @@ describe('config/migration', () => { enabled: true, maintainYarnLock: true, schedule: 'after 5pm', + packages: [ + { + packageName: 'angular', + packagePattern: 'ang', + enabled: false, + }, + ], depTypes: [ 'dependencies', { diff --git a/test/config/validation.spec.js b/test/config/validation.spec.js index a5ef8d43dbf163304a76be5f88e645ff88383cbc..8b51001ae4d31122daf307409200e6f0b00d3df9 100644 --- a/test/config/validation.spec.js +++ b/test/config/validation.spec.js @@ -23,7 +23,7 @@ describe('config/validation', () => { semanticPrefix: 7, githubAppId: 'none', lockFileMaintenance: false, - packages: [ + packageRules: [ { foo: 1, }, diff --git a/test/workers/dep-type/index.spec.js b/test/workers/dep-type/index.spec.js index cb04b3b5133a75ed630fd1d884faeff4c50b3c14..325f41ef10424086e2178c224a2e9cfb138b9c0e 100644 --- a/test/workers/dep-type/index.spec.js +++ b/test/workers/dep-type/index.spec.js @@ -51,25 +51,36 @@ describe('lib/workers/dep-type/index', () => { const depTypeConfig = { foo: 'bar', logger, - packages: [ + packageRules: [ { - packageName: 'a', + packageNames: ['a', 'b'], x: 2, }, { - packagePattern: 'a', + packagePatterns: ['a', 'b'], + excludePackageNames: ['aa'], + excludePackagePatterns: ['d'], y: 2, }, ], }; - it('applies only one rule', () => { + it('applies only one rule for a', () => { const dep = { depName: 'a', }; const res = depTypeWorker.getDepConfig(depTypeConfig, dep); expect(res.x).toBe(2); expect(res.y).toBeUndefined(); - expect(res.packages).toBeUndefined(); + expect(res.packageRules).toBeUndefined(); + }); + it('applies only one rule for b', () => { + const dep = { + depName: 'b', + }; + const res = depTypeWorker.getDepConfig(depTypeConfig, dep); + expect(res.x).toBe(2); + expect(res.y).toBeUndefined(); + expect(res.packageRules).toBeUndefined(); }); it('applies the second rule', () => { const dep = { @@ -78,7 +89,34 @@ describe('lib/workers/dep-type/index', () => { const res = depTypeWorker.getDepConfig(depTypeConfig, dep); expect(res.x).toBeUndefined(); expect(res.y).toBe(2); - expect(res.packages).toBeUndefined(); + expect(res.packageRules).toBeUndefined(); + }); + it('applies the second second rule', () => { + const dep = { + depName: 'bc', + }; + const res = depTypeWorker.getDepConfig(depTypeConfig, dep); + expect(res.x).toBeUndefined(); + expect(res.y).toBe(2); + expect(res.packageRules).toBeUndefined(); + }); + it('excludes package name', () => { + const dep = { + depName: 'aa', + }; + const res = depTypeWorker.getDepConfig(depTypeConfig, dep); + expect(res.x).toBeUndefined(); + expect(res.y).toBeUndefined(); + expect(res.packageRules).toBeUndefined(); + }); + it('excludes package pattern', () => { + const dep = { + depName: 'bcd', + }; + const res = depTypeWorker.getDepConfig(depTypeConfig, dep); + expect(res.x).toBeUndefined(); + expect(res.y).toBeUndefined(); + expect(res.packageRules).toBeUndefined(); }); }); });