mirror of
https://github.com/renovatebot/renovate.git
synced 2025-01-12 06:56:24 +00:00
feat(package-rules): add DepNamePrefix matcher (#28542)
Co-authored-by: Rhys Arkins <rhys@arkins.net>
This commit is contained in:
parent
99c99f01e0
commit
7b66b9f3c2
8 changed files with 226 additions and 0 deletions
|
@ -2510,6 +2510,8 @@ Invalid if used outside of a `packageRule`.
|
||||||
|
|
||||||
### excludeDepPatterns
|
### excludeDepPatterns
|
||||||
|
|
||||||
|
### excludeDepPrefixes
|
||||||
|
|
||||||
### excludePackageNames
|
### excludePackageNames
|
||||||
|
|
||||||
**Important**: Do not mix this up with the option `ignoreDeps`.
|
**Important**: Do not mix this up with the option `ignoreDeps`.
|
||||||
|
@ -2830,6 +2832,8 @@ It is recommended that you avoid using "negative" globs, like `**/!(package.json
|
||||||
|
|
||||||
### matchDepPatterns
|
### matchDepPatterns
|
||||||
|
|
||||||
|
### matchDepPrefixes
|
||||||
|
|
||||||
### matchNewValue
|
### matchNewValue
|
||||||
|
|
||||||
This option is matched against the `newValue` field of a dependency.
|
This option is matched against the `newValue` field of a dependency.
|
||||||
|
|
|
@ -1375,6 +1375,34 @@ const options: RenovateOptions[] = [
|
||||||
cli: false,
|
cli: false,
|
||||||
env: false,
|
env: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'matchDepPrefixes',
|
||||||
|
description:
|
||||||
|
'Dep names prefixes to match. Valid only within a `packageRules` object.',
|
||||||
|
type: 'array',
|
||||||
|
subType: 'string',
|
||||||
|
allowString: true,
|
||||||
|
stage: 'package',
|
||||||
|
parents: ['packageRules'],
|
||||||
|
mergeable: true,
|
||||||
|
cli: false,
|
||||||
|
env: false,
|
||||||
|
advancedUse: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'excludeDepPrefixes',
|
||||||
|
description:
|
||||||
|
'Dep names prefixes to exclude. Valid only within a `packageRules` object.',
|
||||||
|
type: 'array',
|
||||||
|
subType: 'string',
|
||||||
|
allowString: true,
|
||||||
|
stage: 'package',
|
||||||
|
parents: ['packageRules'],
|
||||||
|
mergeable: true,
|
||||||
|
cli: false,
|
||||||
|
env: false,
|
||||||
|
advancedUse: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'matchPackagePatterns',
|
name: 'matchPackagePatterns',
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -353,6 +353,7 @@ export interface PackageRule
|
||||||
description?: string | string[];
|
description?: string | string[];
|
||||||
excludeDepNames?: string[];
|
excludeDepNames?: string[];
|
||||||
excludeDepPatterns?: string[];
|
excludeDepPatterns?: string[];
|
||||||
|
excludeDepPrefixes?: string[];
|
||||||
excludePackageNames?: string[];
|
excludePackageNames?: string[];
|
||||||
excludePackagePatterns?: string[];
|
excludePackagePatterns?: string[];
|
||||||
excludePackagePrefixes?: string[];
|
excludePackagePrefixes?: string[];
|
||||||
|
@ -367,6 +368,7 @@ export interface PackageRule
|
||||||
matchDatasources?: string[];
|
matchDatasources?: string[];
|
||||||
matchDepNames?: string[];
|
matchDepNames?: string[];
|
||||||
matchDepPatterns?: string[];
|
matchDepPatterns?: string[];
|
||||||
|
matchDepPrefixes?: string[];
|
||||||
matchDepTypes?: string[];
|
matchDepTypes?: string[];
|
||||||
matchFileNames?: string[];
|
matchFileNames?: string[];
|
||||||
matchManagers?: string[];
|
matchManagers?: string[];
|
||||||
|
|
|
@ -396,11 +396,13 @@ export async function validateConfig(
|
||||||
'matchDepTypes',
|
'matchDepTypes',
|
||||||
'matchDepNames',
|
'matchDepNames',
|
||||||
'matchDepPatterns',
|
'matchDepPatterns',
|
||||||
|
'matchDepPrefixes',
|
||||||
'matchPackageNames',
|
'matchPackageNames',
|
||||||
'matchPackagePatterns',
|
'matchPackagePatterns',
|
||||||
'matchPackagePrefixes',
|
'matchPackagePrefixes',
|
||||||
'excludeDepNames',
|
'excludeDepNames',
|
||||||
'excludeDepPatterns',
|
'excludeDepPatterns',
|
||||||
|
'excludeDepPrefixes',
|
||||||
'excludePackageNames',
|
'excludePackageNames',
|
||||||
'excludePackagePatterns',
|
'excludePackagePatterns',
|
||||||
'excludePackagePrefixes',
|
'excludePackagePrefixes',
|
||||||
|
|
105
lib/util/package-rules/dep-prefixes.spec.ts
Normal file
105
lib/util/package-rules/dep-prefixes.spec.ts
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
import { DepPrefixesMatcher } from './dep-prefixes';
|
||||||
|
|
||||||
|
describe('util/package-rules/dep-prefixes', () => {
|
||||||
|
const depPrefixesMatcher = new DepPrefixesMatcher();
|
||||||
|
|
||||||
|
describe('match', () => {
|
||||||
|
it('should return null if matchDepPrefixes is not defined', () => {
|
||||||
|
const result = depPrefixesMatcher.matches(
|
||||||
|
{
|
||||||
|
depName: 'abc1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
matchDepPrefixes: undefined,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
expect(result).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false if depName is not defined', () => {
|
||||||
|
const result = depPrefixesMatcher.matches(
|
||||||
|
{
|
||||||
|
depName: undefined,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
matchDepPrefixes: ['@opentelemetry'],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
expect(result).toBeFalse();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true if depName matched', () => {
|
||||||
|
const result = depPrefixesMatcher.matches(
|
||||||
|
{
|
||||||
|
depName: 'abc1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
matchDepPrefixes: ['abc'],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
expect(result).toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false if depName does not match', () => {
|
||||||
|
const result = depPrefixesMatcher.matches(
|
||||||
|
{
|
||||||
|
depName: 'abc1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
matchDepPrefixes: ['def'],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
expect(result).toBeFalse();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('exclude', () => {
|
||||||
|
it('should return null if excludeDepPrefixes is not defined', () => {
|
||||||
|
const result = depPrefixesMatcher.excludes(
|
||||||
|
{
|
||||||
|
depName: 'abc1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
excludeDepPrefixes: undefined,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
expect(result).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false if depName is not defined', () => {
|
||||||
|
const result = depPrefixesMatcher.excludes(
|
||||||
|
{
|
||||||
|
depName: undefined,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
excludeDepPrefixes: ['@opentelemetry'],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
expect(result).toBeFalse();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true if depName matched', () => {
|
||||||
|
const result = depPrefixesMatcher.excludes(
|
||||||
|
{
|
||||||
|
depName: 'abc1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
excludeDepPrefixes: ['abc'],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
expect(result).toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false if depName does not match', () => {
|
||||||
|
const result = depPrefixesMatcher.excludes(
|
||||||
|
{
|
||||||
|
depName: 'abc1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
excludeDepPrefixes: ['def'],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
expect(result).toBeFalse();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
35
lib/util/package-rules/dep-prefixes.ts
Normal file
35
lib/util/package-rules/dep-prefixes.ts
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import is from '@sindresorhus/is';
|
||||||
|
import type { PackageRule, PackageRuleInputConfig } from '../../config/types';
|
||||||
|
import { Matcher } from './base';
|
||||||
|
|
||||||
|
export class DepPrefixesMatcher extends Matcher {
|
||||||
|
override matches(
|
||||||
|
{ depName }: PackageRuleInputConfig,
|
||||||
|
{ matchDepPrefixes }: PackageRule,
|
||||||
|
): boolean | null {
|
||||||
|
if (is.undefined(matchDepPrefixes)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is.undefined(depName)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return matchDepPrefixes.some((prefix) => depName.startsWith(prefix));
|
||||||
|
}
|
||||||
|
|
||||||
|
override excludes(
|
||||||
|
{ depName }: PackageRuleInputConfig,
|
||||||
|
{ excludeDepPrefixes }: PackageRule,
|
||||||
|
): boolean | null {
|
||||||
|
if (is.undefined(excludeDepPrefixes)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is.undefined(depName)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return excludeDepPrefixes.some((prefix) => depName.startsWith(prefix));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1230,4 +1230,52 @@ describe('util/package-rules/index', () => {
|
||||||
expect(res1.x).toBeUndefined();
|
expect(res1.x).toBeUndefined();
|
||||||
expect(res2.x).toBe(1);
|
expect(res2.x).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('matches matchDepPrefixes(depName)', () => {
|
||||||
|
const config: TestConfig = {
|
||||||
|
packageRules: [
|
||||||
|
{
|
||||||
|
matchDepPrefixes: ['abc'],
|
||||||
|
x: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const res1 = applyPackageRules({
|
||||||
|
...config,
|
||||||
|
depName: 'abc1',
|
||||||
|
});
|
||||||
|
const res2 = applyPackageRules({
|
||||||
|
...config,
|
||||||
|
depName: 'def1',
|
||||||
|
});
|
||||||
|
applyPackageRules(config); // coverage
|
||||||
|
|
||||||
|
expect(res1.x).toBe(1);
|
||||||
|
expect(res2.x).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('matches excludeDepPrefixes(depName)', () => {
|
||||||
|
const config: TestConfig = {
|
||||||
|
packageRules: [
|
||||||
|
{
|
||||||
|
excludeDepPrefixes: ['abc'],
|
||||||
|
x: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const res1 = applyPackageRules({
|
||||||
|
...config,
|
||||||
|
depName: 'abc1',
|
||||||
|
});
|
||||||
|
const res2 = applyPackageRules({
|
||||||
|
...config,
|
||||||
|
depName: 'def1',
|
||||||
|
});
|
||||||
|
applyPackageRules(config); // coverage
|
||||||
|
|
||||||
|
expect(res1.x).toBeUndefined();
|
||||||
|
expect(res2.x).toBe(1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { CurrentVersionMatcher } from './current-version';
|
||||||
import { DatasourcesMatcher } from './datasources';
|
import { DatasourcesMatcher } from './datasources';
|
||||||
import { DepNameMatcher } from './dep-names';
|
import { DepNameMatcher } from './dep-names';
|
||||||
import { DepPatternsMatcher } from './dep-patterns';
|
import { DepPatternsMatcher } from './dep-patterns';
|
||||||
|
import { DepPrefixesMatcher } from './dep-prefixes';
|
||||||
import { DepTypesMatcher } from './dep-types';
|
import { DepTypesMatcher } from './dep-types';
|
||||||
import { FileNamesMatcher } from './files';
|
import { FileNamesMatcher } from './files';
|
||||||
import { ManagersMatcher } from './managers';
|
import { ManagersMatcher } from './managers';
|
||||||
|
@ -32,6 +33,7 @@ matchers.push([new MergeConfidenceMatcher()]);
|
||||||
matchers.push([
|
matchers.push([
|
||||||
new DepNameMatcher(),
|
new DepNameMatcher(),
|
||||||
new DepPatternsMatcher(),
|
new DepPatternsMatcher(),
|
||||||
|
new DepPrefixesMatcher(),
|
||||||
new PackageNameMatcher(),
|
new PackageNameMatcher(),
|
||||||
new PackagePatternsMatcher(),
|
new PackagePatternsMatcher(),
|
||||||
new PackagePrefixesMatcher(),
|
new PackagePrefixesMatcher(),
|
||||||
|
|
Loading…
Reference in a new issue