mirror of
https://github.com/renovatebot/renovate.git
synced 2025-01-13 15:36:25 +00:00
feat(bazel-modules): support single_version_override
(#22610)
Co-authored-by: Rhys Arkins <rhys@arkins.net>
This commit is contained in:
parent
0be6dba296
commit
ad61b6c875
5 changed files with 232 additions and 39 deletions
|
@ -180,5 +180,63 @@ describe('modules/manager/bazel-module/extract', () => {
|
|||
])
|
||||
);
|
||||
});
|
||||
|
||||
it('returns bazel_dep and single_version_override dependencies if a version is specified', async () => {
|
||||
const input = codeBlock`
|
||||
bazel_dep(name = "rules_foo", version = "1.2.3")
|
||||
single_version_override(
|
||||
module_name = "rules_foo",
|
||||
version = "1.2.3",
|
||||
registry = "https://example.com/custom_registry",
|
||||
)
|
||||
`;
|
||||
const result = await extractPackageFile(input, 'MODULE.bazel');
|
||||
if (!result) {
|
||||
throw new Error('Expected a result.');
|
||||
}
|
||||
expect(result.deps).toHaveLength(2);
|
||||
expect(result.deps).toEqual(
|
||||
expect.arrayContaining([
|
||||
{
|
||||
datasource: BazelDatasource.id,
|
||||
depType: 'bazel_dep',
|
||||
depName: 'rules_foo',
|
||||
currentValue: '1.2.3',
|
||||
skipReason: 'is-pinned',
|
||||
registryUrls: ['https://example.com/custom_registry'],
|
||||
},
|
||||
{
|
||||
depType: 'single_version_override',
|
||||
depName: 'rules_foo',
|
||||
currentValue: '1.2.3',
|
||||
skipReason: 'ignored',
|
||||
registryUrls: ['https://example.com/custom_registry'],
|
||||
},
|
||||
])
|
||||
);
|
||||
});
|
||||
|
||||
it('returns bazel_dep dependency if single_version_override does not have a version', async () => {
|
||||
const input = codeBlock`
|
||||
bazel_dep(name = "rules_foo", version = "1.2.3")
|
||||
single_version_override(
|
||||
module_name = "rules_foo",
|
||||
registry = "https://example.com/custom_registry",
|
||||
)
|
||||
`;
|
||||
const result = await extractPackageFile(input, 'MODULE.bazel');
|
||||
if (!result) {
|
||||
throw new Error('Expected a result.');
|
||||
}
|
||||
expect(result.deps).toEqual([
|
||||
{
|
||||
datasource: BazelDatasource.id,
|
||||
depType: 'bazel_dep',
|
||||
depName: 'rules_foo',
|
||||
currentValue: '1.2.3',
|
||||
registryUrls: ['https://example.com/custom_registry'],
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -136,5 +136,36 @@ describe('modules/manager/bazel-module/parser', () => {
|
|||
),
|
||||
]);
|
||||
});
|
||||
|
||||
it('finds single_version_override', () => {
|
||||
const input = codeBlock`
|
||||
bazel_dep(name = "rules_foo", version = "1.2.3")
|
||||
single_version_override(
|
||||
module_name = "rules_foo",
|
||||
version = "1.2.3",
|
||||
registry = "https://example.com/custom_registry",
|
||||
)
|
||||
`;
|
||||
const res = parse(input);
|
||||
expect(res).toEqual([
|
||||
fragments.record(
|
||||
{
|
||||
rule: fragments.string('bazel_dep'),
|
||||
name: fragments.string('rules_foo'),
|
||||
version: fragments.string('1.2.3'),
|
||||
},
|
||||
true
|
||||
),
|
||||
fragments.record(
|
||||
{
|
||||
rule: fragments.string('single_version_override'),
|
||||
module_name: fragments.string('rules_foo'),
|
||||
version: fragments.string('1.2.3'),
|
||||
registry: fragments.string('https://example.com/custom_registry'),
|
||||
},
|
||||
true
|
||||
),
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -10,6 +10,7 @@ const supportedRules = [
|
|||
'bazel_dep',
|
||||
'git_override',
|
||||
'local_path_override',
|
||||
'single_version_override',
|
||||
];
|
||||
const supportedRulesRegex = regEx(`^${supportedRules.join('|')}$`);
|
||||
|
||||
|
|
|
@ -6,13 +6,16 @@ import * as fragments from './fragments';
|
|||
import {
|
||||
BasePackageDep,
|
||||
BazelModulePackageDep,
|
||||
MergePackageDep,
|
||||
OverridePackageDep,
|
||||
RuleToBazelModulePackageDep,
|
||||
overrideToPackageDependency,
|
||||
bazelModulePackageDepToPackageDependency,
|
||||
processModulePkgDeps,
|
||||
toPackageDependencies,
|
||||
} from './rules';
|
||||
|
||||
const customRegistryUrl = 'https://example.com/custom_registry';
|
||||
|
||||
const bazelDepPkgDep: BasePackageDep = {
|
||||
datasource: BazelDatasource.id,
|
||||
depType: 'bazel_dep',
|
||||
|
@ -46,6 +49,27 @@ const localPathOverridePkgDep: OverridePackageDep = {
|
|||
skipReason: 'unsupported-datasource',
|
||||
bazelDepSkipReason: 'local-dependency',
|
||||
};
|
||||
const singleVersionOverridePkgDep: OverridePackageDep & MergePackageDep = {
|
||||
depType: 'single_version_override',
|
||||
depName: 'rules_foo',
|
||||
skipReason: 'ignored',
|
||||
bazelDepSkipReason: 'is-pinned',
|
||||
currentValue: '1.2.3',
|
||||
bazelDepMergeFields: ['registryUrls'],
|
||||
registryUrls: [customRegistryUrl],
|
||||
};
|
||||
const singleVersionOverrideWithRegistryPkgDep: MergePackageDep = {
|
||||
depType: 'single_version_override',
|
||||
depName: 'rules_foo',
|
||||
skipReason: 'ignored',
|
||||
bazelDepMergeFields: ['registryUrls'],
|
||||
registryUrls: [customRegistryUrl],
|
||||
};
|
||||
const singleVersionOverrideWithoutVersionAndRegistryPkgDep: BasePackageDep = {
|
||||
depType: 'single_version_override',
|
||||
depName: 'rules_foo',
|
||||
skipReason: 'ignored',
|
||||
};
|
||||
|
||||
describe('modules/manager/bazel-module/rules', () => {
|
||||
describe('RuleToBazelModulePackageDep', () => {
|
||||
|
@ -76,14 +100,27 @@ describe('modules/manager/bazel-module/rules', () => {
|
|||
module_name: fragments.string('rules_foo'),
|
||||
path: fragments.string('/path/to/module'),
|
||||
});
|
||||
const singleVersionOverride = fragments.record({
|
||||
rule: fragments.string('single_version_override'),
|
||||
module_name: fragments.string('rules_foo'),
|
||||
version: fragments.string('1.2.3'),
|
||||
registry: fragments.string(customRegistryUrl),
|
||||
});
|
||||
const singleVersionOverrideWithRegistry = fragments.record({
|
||||
rule: fragments.string('single_version_override'),
|
||||
module_name: fragments.string('rules_foo'),
|
||||
registry: fragments.string(customRegistryUrl),
|
||||
});
|
||||
|
||||
it.each`
|
||||
msg | a | exp
|
||||
${'bazel_dep'} | ${bazelDepWithoutDevDep} | ${bazelDepPkgDep}
|
||||
${'git_override, GitHub host'} | ${gitOverrideWithGihubHost} | ${gitOverrideForGithubPkgDep}
|
||||
${'git_override, unsupported host'} | ${gitOverrideWithUnsupportedHost} | ${gitOverrideForUnsupportedPkgDep}
|
||||
${'archive_override'} | ${archiveOverride} | ${archiveOverridePkgDep}
|
||||
${'local_path_override'} | ${localPathOverride} | ${localPathOverridePkgDep}
|
||||
msg | a | exp
|
||||
${'bazel_dep'} | ${bazelDepWithoutDevDep} | ${bazelDepPkgDep}
|
||||
${'git_override, GitHub host'} | ${gitOverrideWithGihubHost} | ${gitOverrideForGithubPkgDep}
|
||||
${'git_override, unsupported host'} | ${gitOverrideWithUnsupportedHost} | ${gitOverrideForUnsupportedPkgDep}
|
||||
${'archive_override'} | ${archiveOverride} | ${archiveOverridePkgDep}
|
||||
${'local_path_override'} | ${localPathOverride} | ${localPathOverridePkgDep}
|
||||
${'single_version_override with version and registry'} | ${singleVersionOverride} | ${singleVersionOverridePkgDep}
|
||||
${'single_version_override with registry'} | ${singleVersionOverrideWithRegistry} | ${singleVersionOverrideWithRegistryPkgDep}
|
||||
`('.parse() with $msg', ({ a, exp }) => {
|
||||
const pkgDep = RuleToBazelModulePackageDep.parse(a);
|
||||
expect(pkgDep).toEqual(exp);
|
||||
|
@ -94,43 +131,45 @@ describe('modules/manager/bazel-module/rules', () => {
|
|||
const expectedBazelDepNoOverrides: PackageDependency[] = [bazelDepPkgDep];
|
||||
const expectedBazelDepAndGitOverride: PackageDependency[] = [
|
||||
deepmerge(bazelDepPkgDep, { skipReason: 'git-dependency' }),
|
||||
overrideToPackageDependency(gitOverrideForGithubPkgDep),
|
||||
bazelModulePackageDepToPackageDependency(gitOverrideForGithubPkgDep),
|
||||
];
|
||||
const expectedBazelDepAndSingleVersionOverride: PackageDependency[] = [
|
||||
deepmerge(bazelDepPkgDep, {
|
||||
skipReason: 'is-pinned',
|
||||
registryUrls: [customRegistryUrl],
|
||||
}),
|
||||
bazelModulePackageDepToPackageDependency(singleVersionOverridePkgDep),
|
||||
];
|
||||
const expectedBazelDepAndArchiveOverride: PackageDependency[] = [
|
||||
deepmerge(bazelDepPkgDep, { skipReason: 'file-dependency' }),
|
||||
overrideToPackageDependency(archiveOverridePkgDep),
|
||||
bazelModulePackageDepToPackageDependency(archiveOverridePkgDep),
|
||||
];
|
||||
const expectedBazelDepAndLocalPathOverride: PackageDependency[] = [
|
||||
deepmerge(bazelDepPkgDep, { skipReason: 'local-dependency' }),
|
||||
overrideToPackageDependency(localPathOverridePkgDep),
|
||||
bazelModulePackageDepToPackageDependency(localPathOverridePkgDep),
|
||||
];
|
||||
// If a registry is specified and a version is not specified for a
|
||||
// single_version_override, it is merely providing a registry URL for the bazel_dep.
|
||||
const expectedBazelDepWithRegistry: PackageDependency[] = [
|
||||
deepmerge(bazelDepPkgDep, { registryUrls: [customRegistryUrl] }),
|
||||
];
|
||||
|
||||
it.each`
|
||||
msg | a | exp
|
||||
${'bazel_dep, no overrides'} | ${[bazelDepPkgDep]} | ${expectedBazelDepNoOverrides}
|
||||
${'bazel_dep & git_override'} | ${[bazelDepPkgDep, gitOverrideForGithubPkgDep]} | ${expectedBazelDepAndGitOverride}
|
||||
${'git_override, no bazel_dep'} | ${[gitOverrideForGithubPkgDep]} | ${[]}
|
||||
${'bazel_dep & archive_override'} | ${[bazelDepPkgDep, archiveOverridePkgDep]} | ${expectedBazelDepAndArchiveOverride}
|
||||
${'bazel_dep & local_path_override'} | ${[bazelDepPkgDep, localPathOverridePkgDep]} | ${expectedBazelDepAndLocalPathOverride}
|
||||
`('with $msg', ({ a, exp }) => {
|
||||
msg | a | exp
|
||||
${'bazel_dep, no overrides'} | ${[bazelDepPkgDep]} | ${expectedBazelDepNoOverrides}
|
||||
${'bazel_dep & git_override'} | ${[bazelDepPkgDep, gitOverrideForGithubPkgDep]} | ${expectedBazelDepAndGitOverride}
|
||||
${'git_override, no bazel_dep'} | ${[gitOverrideForGithubPkgDep]} | ${[]}
|
||||
${'bazel_dep & archive_override'} | ${[bazelDepPkgDep, archiveOverridePkgDep]} | ${expectedBazelDepAndArchiveOverride}
|
||||
${'bazel_dep & local_path_override'} | ${[bazelDepPkgDep, localPathOverridePkgDep]} | ${expectedBazelDepAndLocalPathOverride}
|
||||
${'single_version_override, with version and registry'} | ${[bazelDepPkgDep, singleVersionOverridePkgDep]} | ${expectedBazelDepAndSingleVersionOverride}
|
||||
${'single_version_override, with registry'} | ${[bazelDepPkgDep, singleVersionOverrideWithRegistryPkgDep]} | ${expectedBazelDepWithRegistry}
|
||||
${'single_version_override, without version and registry'} | ${[bazelDepPkgDep, singleVersionOverrideWithoutVersionAndRegistryPkgDep]} | ${[bazelDepPkgDep]}
|
||||
`('with $msg', ({ msg, a, exp }) => {
|
||||
const result = toPackageDependencies(a);
|
||||
expect(result).toEqual(exp);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.overrideToPackageDependency()', () => {
|
||||
it('removes the properties specific to OverridePackageDep', () => {
|
||||
const result = overrideToPackageDependency(gitOverrideForGithubPkgDep);
|
||||
expect(result).toEqual({
|
||||
datasource: GithubTagsDatasource.id,
|
||||
depType: 'git_override',
|
||||
depName: 'rules_foo',
|
||||
packageName: 'example/rules_foo',
|
||||
currentDigest: '850cb49c8649e463b80ef7984e7c744279746170',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('.processModulePkgDeps', () => {
|
||||
it('returns an empty array if the input is an empty array', () => {
|
||||
expect(processModulePkgDeps([])).toHaveLength(0);
|
||||
|
|
|
@ -16,27 +16,49 @@ export interface BasePackageDep extends PackageDependency {
|
|||
depName: string;
|
||||
}
|
||||
|
||||
type BasePackageDepMergeKeys = Extract<keyof BasePackageDep, 'registryUrls'>;
|
||||
|
||||
export interface MergePackageDep extends BasePackageDep {
|
||||
// The fields that should be copied from this struct to the bazel_dep
|
||||
// PackageDependency.
|
||||
bazelDepMergeFields: BasePackageDepMergeKeys[];
|
||||
}
|
||||
|
||||
export interface OverridePackageDep extends BasePackageDep {
|
||||
// This value is set as the skipReason on the bazel_dep PackageDependency.
|
||||
bazelDepSkipReason: SkipReason;
|
||||
}
|
||||
|
||||
export type BazelModulePackageDep = BasePackageDep | OverridePackageDep;
|
||||
export type BazelModulePackageDep =
|
||||
| BasePackageDep
|
||||
| OverridePackageDep
|
||||
| MergePackageDep;
|
||||
|
||||
function isOverride(value: BazelModulePackageDep): value is OverridePackageDep {
|
||||
return 'bazelDepSkipReason' in value;
|
||||
}
|
||||
|
||||
function isMerge(value: BazelModulePackageDep): value is MergePackageDep {
|
||||
return 'bazelDepMergeFields' in value;
|
||||
}
|
||||
|
||||
// This function exists to remove properties that are specific to
|
||||
// OverridePackageDep. In theory, there is no harm in leaving the properties
|
||||
// BazelModulePackageDep. In theory, there is no harm in leaving the properties
|
||||
// as it does not invalidate the PackageDependency interface. However, it might
|
||||
// be surprising to someone outside the bazel-module code to see the extra
|
||||
// properties.
|
||||
export function overrideToPackageDependency(
|
||||
override: OverridePackageDep
|
||||
export function bazelModulePackageDepToPackageDependency(
|
||||
bmpd: BazelModulePackageDep
|
||||
): PackageDependency {
|
||||
const copy: Partial<OverridePackageDep> = { ...override };
|
||||
delete copy.bazelDepSkipReason;
|
||||
const copy: BazelModulePackageDep = structuredClone(bmpd);
|
||||
if (isOverride(copy)) {
|
||||
const partial = copy as Partial<OverridePackageDep>;
|
||||
delete partial.bazelDepSkipReason;
|
||||
}
|
||||
if (isMerge(copy)) {
|
||||
const partial = copy as Partial<MergePackageDep>;
|
||||
delete partial.bazelDepMergeFields;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
|
@ -87,6 +109,40 @@ const GitOverrideToPackageDep = RecordFragmentSchema.extend({
|
|||
}
|
||||
);
|
||||
|
||||
const SingleVersionOverrideToPackageDep = RecordFragmentSchema.extend({
|
||||
children: z.object({
|
||||
rule: StringFragmentSchema.extend({
|
||||
value: z.literal('single_version_override'),
|
||||
}),
|
||||
module_name: StringFragmentSchema,
|
||||
version: StringFragmentSchema.optional(),
|
||||
registry: StringFragmentSchema.optional(),
|
||||
}),
|
||||
}).transform(
|
||||
({
|
||||
children: { rule, module_name: moduleName, version, registry },
|
||||
}): BasePackageDep => {
|
||||
const base: BasePackageDep = {
|
||||
depType: rule.value,
|
||||
depName: moduleName.value,
|
||||
skipReason: 'ignored',
|
||||
};
|
||||
// If a version is specified, then add a skipReason to bazel_dep
|
||||
if (version) {
|
||||
const override = base as OverridePackageDep;
|
||||
override.bazelDepSkipReason = 'is-pinned';
|
||||
override.currentValue = version.value;
|
||||
}
|
||||
// If a registry is specified, then merge it into the bazel_dep
|
||||
if (registry) {
|
||||
const merge = base as MergePackageDep;
|
||||
merge.bazelDepMergeFields = ['registryUrls'];
|
||||
merge.registryUrls = [registry.value];
|
||||
}
|
||||
return base;
|
||||
}
|
||||
);
|
||||
|
||||
const UnsupportedOverrideToPackageDep = RecordFragmentSchema.extend({
|
||||
children: z.object({
|
||||
rule: StringFragmentSchema.extend({
|
||||
|
@ -117,6 +173,7 @@ const UnsupportedOverrideToPackageDep = RecordFragmentSchema.extend({
|
|||
export const RuleToBazelModulePackageDep = z.union([
|
||||
BazelDepToPackageDep,
|
||||
GitOverrideToPackageDep,
|
||||
SingleVersionOverrideToPackageDep,
|
||||
UnsupportedOverrideToPackageDep,
|
||||
]);
|
||||
|
||||
|
@ -151,7 +208,14 @@ export function processModulePkgDeps(
|
|||
logger.debug(`A 'bazel_dep' was not found for '${moduleName}'.`);
|
||||
return [];
|
||||
}
|
||||
const deps: PackageDependency[] = [bazelDep];
|
||||
// Create a new bazelDep that will be modified. We do not want to change the
|
||||
// input.
|
||||
const bazelDepOut = { ...bazelDep };
|
||||
const deps: PackageDependency[] = [bazelDepOut];
|
||||
const merges = packageDeps.filter(isMerge);
|
||||
for (const merge of merges) {
|
||||
merge.bazelDepMergeFields.forEach((k) => (bazelDepOut[k] = merge[k]));
|
||||
}
|
||||
const overrides = packageDeps.filter(isOverride);
|
||||
// It is an error for more than one override to exist for a module. We will
|
||||
// ignore the overrides if there is more than one.
|
||||
|
@ -164,8 +228,8 @@ export function processModulePkgDeps(
|
|||
return deps;
|
||||
}
|
||||
const override = overrides[0];
|
||||
deps.push(overrideToPackageDependency(override));
|
||||
bazelDep.skipReason = override.bazelDepSkipReason;
|
||||
deps.push(bazelModulePackageDepToPackageDependency(override));
|
||||
bazelDepOut.skipReason = override.bazelDepSkipReason;
|
||||
return deps;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue