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(packageRules): matchJsonata #31821

Closed
wants to merge 1 commit into from
Closed
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
11 changes: 11 additions & 0 deletions lib/config/options/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1513,6 +1513,17 @@ const options: RenovateOptions[] = [
cli: false,
env: false,
},
{
name: 'matchJsonata',
description:
'A JSONata expression to match against the full config object. Valid only within a `packageRules` object.',
type: 'string',
stage: 'package',
parents: ['packageRules'],
mergeable: true,
cli: false,
env: false,
},
// Version behavior
{
name: 'allowedVersions',
Expand Down
1 change: 1 addition & 0 deletions lib/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ export interface PackageRule
matchRepositories?: string[];
matchSourceUrls?: string[];
matchUpdateTypes?: UpdateType[];
matchJsonata?: string;
registryUrls?: string[] | null;
vulnerabilitySeverity?: string;
vulnerabilityFixVersion?: string;
Expand Down
69 changes: 69 additions & 0 deletions lib/util/package-rules/jsonata.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { JsonataMatcher } from './jsonata';

describe('JsonataMatcher', () => {

Check failure on line 3 in lib/util/package-rules/jsonata.spec.ts

View workflow job for this annotation

GitHub Actions / lint-eslint

Test must be described by this string: 'util/package-rules/jsonata'
const matcher = new JsonataMatcher();

it('should return true for a matching JSONata expression', () => {
const result = matcher.matches(
{ depName: 'lodash' },
{ matchJsonata: '$.depName = "lodash"' }
);
expect(result).toBeTrue();
});

it('should return false for a non-matching JSONata expression', () => {
const result = matcher.matches(
{ depName: 'lodash' },
{ matchJsonata: '$.depName = "react"' }
);
expect(result).toBeFalse();

Check failure on line 19 in lib/util/package-rules/jsonata.spec.ts

View workflow job for this annotation

GitHub Actions / test (1/2)

JsonataMatcher › should return false for a non-matching JSONata expression

expected true to be false or Boolean(false) at Object.<anonymous> (lib/util/package-rules/jsonata.spec.ts:19:20)
});

it('should return false for an invalid JSONata expression', () => {
const result = matcher.matches(
{ depName: 'lodash' },
{ matchJsonata: '$.depName = ' }
);
expect(result).toBeFalse();
});

it('should return null if matchJsonata is not defined', () => {
const result = matcher.matches(
{ depName: 'lodash' },
{}
);
expect(result).toBeNull();
});

it('should return true for a complex JSONata expression', () => {
const result = matcher.matches(
{ depName: 'lodash', version: '4.17.21' },
{ matchJsonata: '$.depName = "lodash" and $.version = "4.17.21"' }
);
expect(result).toBeTrue();
});

it('should return false for a complex JSONata expression with non-matching version', () => {
const result = matcher.matches(
{ depName: 'lodash', version: '4.17.20' },
{ matchJsonata: '$.depName = "lodash" and $.version = "4.17.21"' }
);
expect(result).toBeFalse();

Check failure on line 51 in lib/util/package-rules/jsonata.spec.ts

View workflow job for this annotation

GitHub Actions / test (1/2)

JsonataMatcher › should return false for a complex JSONata expression with non-matching version

expected true to be false or Boolean(false) at Object.<anonymous> (lib/util/package-rules/jsonata.spec.ts:51:20)
});

it('should return true for a JSONata expression with nested properties', () => {
const result = matcher.matches(
{ dep: { name: 'lodash', version: '4.17.21' } },
{ matchJsonata: '$.dep.name = "lodash" and $.dep.version = "4.17.21"' }
);
expect(result).toBeTrue();
});

it('should return false for a JSONata expression with nested properties and non-matching version', () => {
const result = matcher.matches(
{ dep: { name: 'lodash', version: '4.17.20' } },
{ matchJsonata: '$.dep.name = "lodash" and $.dep.version = "4.17.21"' }
);
expect(result).toBeFalse();

Check failure on line 67 in lib/util/package-rules/jsonata.spec.ts

View workflow job for this annotation

GitHub Actions / test (1/2)

JsonataMatcher › should return false for a JSONata expression with nested properties and non-matching version

expected true to be false or Boolean(false) at Object.<anonymous> (lib/util/package-rules/jsonata.spec.ts:67:20)
});
});
22 changes: 22 additions & 0 deletions lib/util/package-rules/jsonata.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import jsonata from 'jsonata';
import type { PackageRule, PackageRuleInputConfig } from '../../config/types';
import { Matcher } from './base';

export class JsonataMatcher extends Matcher {
override matches(
inputConfig: PackageRuleInputConfig,
{ matchJsonata }: PackageRule,
): boolean | null {
if (!matchJsonata) {
return null;
}

try {
const expression = jsonata(matchJsonata);
const result = expression.evaluate(inputConfig);
return Boolean(result);
} catch (error) {

Check failure on line 18 in lib/util/package-rules/jsonata.ts

View workflow job for this annotation

GitHub Actions / lint-eslint

'error' is defined but never used.
return false;
}
}
}
2 changes: 2 additions & 0 deletions lib/util/package-rules/matchers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import { PackageNameMatcher } from './package-names';
import { RepositoriesMatcher } from './repositories';
import { SourceUrlsMatcher } from './sourceurls';
import { JsonataMatcher } from './jsonata';

Check failure on line 16 in lib/util/package-rules/matchers.ts

View workflow job for this annotation

GitHub Actions / lint-eslint

`./jsonata` import should occur before import of `./managers`
import type { MatcherApi } from './types';
import { UpdateTypesMatcher } from './update-types';

Expand Down Expand Up @@ -40,3 +41,4 @@
matchers.push(new SourceUrlsMatcher());
matchers.push(new NewValueMatcher());
matchers.push(new CurrentAgeMatcher());
matchers.push(new JsonataMatcher());
Loading