diff --git a/lib/config/index.js b/lib/config/index.js index 351fb6e129fbea55b0c0a65d1e354a4d97020c1b..50429d6e51d2f32b8b4084cb8100812536325a02 100644 --- a/lib/config/index.js +++ b/lib/config/index.js @@ -119,12 +119,8 @@ function mergeChildConfig(parentConfig, childConfig) { if (option.mergeable && childConfig[option.name]) { logger.debug(`mergeable option: ${option.name}`); if (option.type === 'list') { - if (parentConfig[option.name]) { - // Place parent values *after* child - config[option.name] = config[option.name].concat( - parentConfig[option.name] - ); - } + config[option.name] = (parentConfig[option.name] || []) + .concat(config[option.name] || []); } else { config[option.name] = { ...parentConfig[option.name], diff --git a/lib/workers/dep-type/index.js b/lib/workers/dep-type/index.js index a4c6d454500c7177d0a2981e85576de356d21be5..a089b8221545c4d2e8e133dd07f5f1ee95297619 100644 --- a/lib/workers/dep-type/index.js +++ b/lib/workers/dep-type/index.js @@ -55,45 +55,44 @@ async function renovateDepType(packageContent, config) { } function getDepConfig(depTypeConfig, dep) { - const depConfig = configParser.mergeChildConfig(depTypeConfig, dep); + let depConfig = configParser.mergeChildConfig(depTypeConfig, dep); // Apply any matching package rules if (depConfig.packageRules) { - let packageRuleApplied = false; depConfig.packageRules.forEach(packageRule => { - // Apply at most 1 package fule - if (!packageRuleApplied) { - 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; - } + let applyRule = false; + if ( + packageRule.packageNames && + packageRule.packageNames.includes(depConfig.depName) + ) { + applyRule = true; + } else if (packageRule.packagePatterns) { + for (const packagePattern of packageRule.packagePatterns) { + const packageRegex = new RegExp(packagePattern); + if (depConfig.depName.match(packageRegex)) { + applyRule = 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 ( + packageRule.excludePackageNames && + packageRule.excludePackageNames.includes(depConfig.depName) + ) { + applyRule = false; + } else if (packageRule.excludePackagePatterns) { + for (const packagePattern of packageRule.excludePackagePatterns) { + const packageRegex = new RegExp(packagePattern); + if (depConfig.depName.match(packageRegex)) { + applyRule = false; } } - if (packageRuleApplied) { - // Package rule config overrides any existing config - Object.assign(depConfig, packageRule); - delete depConfig.packageNames; - delete depConfig.packagePatterns; - } + } + if (applyRule) { + // Package rule config overrides any existing config + depConfig = configParser.mergeChildConfig(depConfig, packageRule); + delete depConfig.packageNames; + delete depConfig.packagePatterns; + delete depConfig.excludePackageNames; + delete depConfig.excludePackagePatterns; } }); } diff --git a/test/config/index.spec.js b/test/config/index.spec.js index 67f02e13f0d664d8d2120fd053363ed88e3d1b2d..d432a21b96bd14eb3129ef2481a110acbc660ee4 100644 --- a/test/config/index.spec.js +++ b/test/config/index.spec.js @@ -184,13 +184,13 @@ describe('config/index', () => { const configParser = require('../../lib/config/index.js'); const config = configParser.mergeChildConfig(parentConfig, childConfig); expect(config.packageRules.map(rule => rule.a)).toMatchObject([ - 3, - 4, 1, 2, + 3, + 4, ]); }); - it('skips null parent packageRules', () => { + it('handles null parent packageRules', () => { const parentConfig = { ...defaultConfig }; Object.assign(parentConfig, { packageRules: null, @@ -202,5 +202,12 @@ describe('config/index', () => { const config = configParser.mergeChildConfig(parentConfig, childConfig); expect(config.packageRules).toHaveLength(2); }); + it('handles null child packageRules', () => { + const parentConfig = { ...defaultConfig }; + parentConfig.packageRules = [{ a: 3 }, { a: 4 }]; + const configParser = require('../../lib/config/index.js'); + const config = configParser.mergeChildConfig(parentConfig, {}); + expect(config.packageRules).toHaveLength(2); + }); }); }); diff --git a/test/workers/dep-type/index.spec.js b/test/workers/dep-type/index.spec.js index 325f41ef10424086e2178c224a2e9cfb138b9c0e..d97e55e32897e410154ee2ceb2daf7cd744a4a0e 100644 --- a/test/workers/dep-type/index.spec.js +++ b/test/workers/dep-type/index.spec.js @@ -64,22 +64,22 @@ describe('lib/workers/dep-type/index', () => { }, ], }; - it('applies only one rule for a', () => { + it('applies both rules for a', () => { const dep = { depName: 'a', }; const res = depTypeWorker.getDepConfig(depTypeConfig, dep); expect(res.x).toBe(2); - expect(res.y).toBeUndefined(); + expect(res.y).toBe(2); expect(res.packageRules).toBeUndefined(); }); - it('applies only one rule for b', () => { + it('applies both rules for b', () => { const dep = { depName: 'b', }; const res = depTypeWorker.getDepConfig(depTypeConfig, dep); expect(res.x).toBe(2); - expect(res.y).toBeUndefined(); + expect(res.y).toBe(2); expect(res.packageRules).toBeUndefined(); }); it('applies the second rule', () => {