diff --git a/lib/modules/manager/npm/post-update/rules.spec.ts b/lib/modules/manager/npm/post-update/rules.spec.ts index 3d1ad4988ddef82d01824a92abd0a51ccc48e024..2b555996295fa22225e6c17d992a29d8349234c2 100644 --- a/lib/modules/manager/npm/post-update/rules.spec.ts +++ b/lib/modules/manager/npm/post-update/rules.spec.ts @@ -142,5 +142,50 @@ describe('modules/manager/npm/post-update/rules', () => { `, ); }); + + it('uses rules without host type', () => { + hostRules.add({ + matchHost: 'registry.company.com', + token: 'sometoken', + }); + const res = processHostRules(); + expect(res).toEqual({ + additionalNpmrcContent: [ + '//registry.company.com/:_authToken=sometoken', + ], + + additionalYarnRcYml: { + npmRegistries: { + '//registry.company.com/': { + npmAuthToken: 'sometoken', + }, + }, + }, + }); + }); + + it('deduplicates host rules while prefering npm type ones', () => { + hostRules.add({ + matchHost: 'registry.company.com', + token: 'donotuseme', + }); + hostRules.add({ + matchHost: 'registry.company.com', + token: 'useme', + hostType: 'npm', + }); + const res = processHostRules(); + expect(res).toEqual({ + additionalNpmrcContent: ['//registry.company.com/:_authToken=useme'], + + additionalYarnRcYml: { + npmRegistries: { + '//registry.company.com/': { + npmAuthToken: 'useme', + }, + }, + }, + }); + }); }); }); diff --git a/lib/modules/manager/npm/post-update/rules.ts b/lib/modules/manager/npm/post-update/rules.ts index 0814bfa334f43150a987caae5a98a02223ffb24d..5dfdfd4feb842a77fbee3c217eb05e810e569323 100644 --- a/lib/modules/manager/npm/post-update/rules.ts +++ b/lib/modules/manager/npm/post-update/rules.ts @@ -20,7 +20,27 @@ export function processHostRules(): HostRulesResult { hostType: 'npm', }); logger.debug(`Found ${npmHostRules.length} npm host rule(s)`); - for (const hostRule of npmHostRules) { + // Include host rules without specific type to mimic the behavior used when determining dependencies with updates. + const noTypeHostRules = hostRules + .getAll() + .filter((rule) => rule.hostType === null || rule.hostType === undefined); + logger.debug( + `Found ${noTypeHostRules.length} host rule(s) without host type`, + ); + // Drop duplicates for the same matchHost while prefering the more specific rules with hostType npm. + const noTypeHostRulesWithoutDuplicates = noTypeHostRules.filter( + (rule) => !npmHostRules.some((elem) => elem.matchHost === rule.matchHost), + ); + logger.debug( + `Found ${noTypeHostRulesWithoutDuplicates.length} host rule(s) without host type after dropping duplicates`, + ); + const effectiveHostRules = npmHostRules.concat( + noTypeHostRulesWithoutDuplicates, + ); + logger.trace( + `Found ${effectiveHostRules.length} effective npm host rule(s) after deduplication`, + ); + for (const hostRule of effectiveHostRules) { if (!hostRule.resolvedHost) { logger.debug('Skipping host rule without resolved host'); continue;