Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(package-rules): add DepNamePrefix matcher #28542

Merged
merged 9 commits into from
Apr 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/usage/configuration-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -2510,6 +2510,8 @@ Invalid if used outside of a `packageRule`.

### excludeDepPatterns

### excludeDepPrefixes

### excludePackageNames

**Important**: Do not mix this up with the option `ignoreDeps`.
Expand Down Expand Up @@ -2830,6 +2832,8 @@ It is recommended that you avoid using "negative" globs, like `**/!(package.json

### matchDepPatterns

### matchDepPrefixes

### matchNewValue

This option is matched against the `newValue` field of a dependency.
Expand Down
28 changes: 28 additions & 0 deletions lib/config/options/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1375,6 +1375,34 @@ const options: RenovateOptions[] = [
cli: 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',
description:
Expand Down
2 changes: 2 additions & 0 deletions lib/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ export interface PackageRule
description?: string | string[];
excludeDepNames?: string[];
excludeDepPatterns?: string[];
excludeDepPrefixes?: string[];
excludePackageNames?: string[];
excludePackagePatterns?: string[];
excludePackagePrefixes?: string[];
Expand All @@ -367,6 +368,7 @@ export interface PackageRule
matchDatasources?: string[];
matchDepNames?: string[];
matchDepPatterns?: string[];
matchDepPrefixes?: string[];
matchDepTypes?: string[];
matchFileNames?: string[];
matchManagers?: string[];
Expand Down
2 changes: 2 additions & 0 deletions lib/config/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -396,11 +396,13 @@ export async function validateConfig(
'matchDepTypes',
'matchDepNames',
'matchDepPatterns',
'matchDepPrefixes',
'matchPackageNames',
'matchPackagePatterns',
'matchPackagePrefixes',
'excludeDepNames',
'excludeDepPatterns',
'excludeDepPrefixes',
'excludePackageNames',
'excludePackagePatterns',
'excludePackagePrefixes',
Expand Down
105 changes: 105 additions & 0 deletions lib/util/package-rules/dep-prefixes.spec.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 35 additions & 0 deletions lib/util/package-rules/dep-prefixes.ts
Original file line number Diff line number Diff line change
@@ -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));
}
}
48 changes: 48 additions & 0 deletions lib/util/package-rules/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1230,4 +1230,52 @@ describe('util/package-rules/index', () => {
expect(res1.x).toBeUndefined();
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);
});
});
2 changes: 2 additions & 0 deletions lib/util/package-rules/matchers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { CurrentVersionMatcher } from './current-version';
import { DatasourcesMatcher } from './datasources';
import { DepNameMatcher } from './dep-names';
import { DepPatternsMatcher } from './dep-patterns';
import { DepPrefixesMatcher } from './dep-prefixes';
import { DepTypesMatcher } from './dep-types';
import { FileNamesMatcher } from './files';
import { ManagersMatcher } from './managers';
Expand All @@ -32,6 +33,7 @@ matchers.push([new MergeConfidenceMatcher()]);
matchers.push([
new DepNameMatcher(),
new DepPatternsMatcher(),
new DepPrefixesMatcher(),
new PackageNameMatcher(),
new PackagePatternsMatcher(),
new PackagePrefixesMatcher(),
Expand Down