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(bazel-module): support bazel_dep dependencies without the version parameter #33496

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
27 changes: 26 additions & 1 deletion docs/usage/bazel.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ If Renovate finds a newer version, it updates `0.15.0` to match that version.

#### `git_override`

If Renovate finds a [`git_override`](https://bazel.build/rules/lib/globals/module#git_override), it ignores the related `bazel_dep` entry and instead evaluates the `commit` value at the specified `remote`.
If Renovate finds a [`git_override`](https://bazel.build/rules/lib/globals/module#git_override), it ignores the related `bazel_dep` entry and instead evaluates the `commit` value at the specified `remote`. When using `git_override`, the `version` parameter on the `bazel_dep` is optional.

```python
bazel_dep(name = "cgrindel_bazel_starlib", version = "0.15.0")
Expand All @@ -89,6 +89,13 @@ git_override(
commit = "fb47f0e9f7c376a7700fc9fe3319231ae57880df",
remote = "https://github.com/cgrindel/bazel-starlib.git",
)

bazel_dep(name = "rules_foo")
git_override(
module_name = "rules_foo",
remote = "https://github.com/foo/rules_foo.git",
commit = "8a1e9abe415eda7cd7f2a744fdac7499ce42cdca",
)
```

If the primary branch has a newer commit than in the list, Renovate updates the `commit` value.
Expand All @@ -101,6 +108,7 @@ Renovate only evaluates _two_ attributes from this declaration: `version` and `r
If a `version` is specified, it overrides the version in the `bazel_dep`.
In the following example, Renovate notices that the version is pinned to `1.2.3`.
This results in `rules_foo` being ignored for update evaluation.
When using `single_version_override`, the `version` parameter on the `bazel_dep` is optional.

```python
bazel_dep(name = "rules_foo", version = "1.2.4")
Expand All @@ -109,6 +117,13 @@ single_version_override(
module_name = "rules_foo",
version = "1.2.3",
)

bazel_dep(name = "rules_bar")

single_version_override(
module_name = "rules_bar",
version = "1.2.3",
)
```

If a `registry` is specified, Renovate uses the specified registry URL to check for a new version.
Expand All @@ -128,6 +143,7 @@ single_version_override(

If Renovate finds an [`archive_override`](https://bazel.build/rules/lib/globals/module#archive_override) or a [`local_path_override`](https://bazel.build/rules/lib/globals/module#local_path_override), it ignores the related `bazel_dep`.
Because these declarations lack versionable attributes, Renovate does not update them.
When using `archive_override` and `local_path_override`, the `version` parameter on the `bazel_dep` is optional.

```python
bazel_dep(name = "rules_foo", version = "1.2.3")
Expand All @@ -138,6 +154,15 @@ archive_override(
"https://example.com/archive.tar.gz",
],
)

bazel_dep(name = "rules_bar")

archive_override(
module_name = "rules_bar",
urls = [
"https://example.com/archive.tar.gz",
],
)
```

#### `multiple_version_override`
Expand Down
18 changes: 18 additions & 0 deletions lib/modules/manager/bazel-module/context.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,24 @@ describe('modules/manager/bazel-module/context', () => {
]);
});

it('construct simple bazel_dep with no version', () => {
const ctx = new Ctx()
.startRule('bazel_dep')
.startAttribute('name')
.addString('rules_foo')
.endRule();

expect(ctx.results).toEqual([
fragments.record(
{
rule: fragments.string('bazel_dep'),
name: fragments.string('rules_foo'),
},
true,
),
]);
});

it('construct a rule with array arg', () => {
const ctx = new Ctx()
.startRule('foo_library')
Expand Down
123 changes: 120 additions & 3 deletions lib/modules/manager/bazel-module/extract.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,39 @@ describe('modules/manager/bazel-module/extract', () => {
);
});

it('returns bazel_dep with no version and git_override', async () => {
const input = codeBlock`
bazel_dep(name = "rules_foo")
git_override(
module_name = "rules_foo",
commit = "850cb49c8649e463b80ef7984e7c744279746170",
remote = "https://github.com/example/rules_foo.git",
)
`;
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',
skipReason: 'git-dependency',
},
{
datasource: GithubTagsDatasource.id,
depType: 'git_override',
depName: 'rules_foo',
currentDigest: '850cb49c8649e463b80ef7984e7c744279746170',
packageName: 'example/rules_foo',
},
]),
);
});

it('returns dependencies and custom registry URLs when specified in a bazelrc', async () => {
const packageFile = 'extract/multiple-bazelrcs/MODULE.bazel';
const input = Fixtures.get(packageFile);
Expand Down Expand Up @@ -149,6 +182,38 @@ describe('modules/manager/bazel-module/extract', () => {
);
});

it('returns bazel_dep with no version and archive_override dependencies', async () => {
const input = codeBlock`
bazel_dep(name = "rules_foo")
archive_override(
module_name = "rules_foo",
urls = [
"https://example.com/archive.tar.gz",
],
)
`;
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',
skipReason: 'file-dependency',
},
{
depType: 'archive_override',
depName: 'rules_foo',
skipReason: 'unsupported-datasource',
},
]),
);
});

it('returns bazel_dep and local_path_override dependencies', async () => {
const input = codeBlock`
bazel_dep(name = "rules_foo", version = "1.2.3")
Expand Down Expand Up @@ -180,9 +245,39 @@ describe('modules/manager/bazel-module/extract', () => {
);
});

it('returns bazel_dep and single_version_override dependencies if a version is specified', async () => {
it('returns bazel_dep with no version and local_path_override dependencies', async () => {
const input = codeBlock`
bazel_dep(name = "rules_foo", version = "1.2.3")
bazel_dep(name = "rules_foo")
local_path_override(
module_name = "rules_foo",
urls = "/path/to/repo",
)
`;
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',
skipReason: 'local-dependency',
},
{
depType: 'local_path_override',
depName: 'rules_foo',
skipReason: 'unsupported-datasource',
},
]),
);
});

it('returns bazel_dep with no version and single_version_override dependencies if a version is specified', async () => {
const input = codeBlock`
bazel_dep(name = "rules_foo")
single_version_override(
module_name = "rules_foo",
version = "1.2.3",
Expand All @@ -200,7 +295,6 @@ describe('modules/manager/bazel-module/extract', () => {
datasource: BazelDatasource.id,
depType: 'bazel_dep',
depName: 'rules_foo',
currentValue: '1.2.3',
skipReason: 'is-pinned',
registryUrls: ['https://example.com/custom_registry'],
},
Expand Down Expand Up @@ -238,6 +332,29 @@ describe('modules/manager/bazel-module/extract', () => {
]);
});

it('returns bazel_dep with no version dependency if single_version_override does not have a version', async () => {
const input = codeBlock`
bazel_dep(name = "rules_foo")
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',
skipReason: 'unspecified-version',
registryUrls: ['https://example.com/custom_registry'],
},
]);
});

it('returns maven.install and maven.artifact dependencies', async () => {
const input = codeBlock`
maven.artifact(
Expand Down
63 changes: 54 additions & 9 deletions lib/modules/manager/bazel-module/rules.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ const bazelDepPkgDep: BasePackageDep = {
depName: 'rules_foo',
currentValue: '1.2.3',
};
const bazelDepPkgDepNoVersion: BasePackageDep = {
datasource: BazelDatasource.id,
depType: 'bazel_dep',
depName: 'rules_foo',
currentValue: undefined,
skipReason: 'unspecified-version',
};
const gitOverrideForGithubPkgDep: OverridePackageDep = {
datasource: GithubTagsDatasource.id,
depType: 'git_override',
Expand Down Expand Up @@ -94,6 +101,10 @@ describe('modules/manager/bazel-module/rules', () => {
name: fragments.string('rules_foo'),
version: fragments.string('1.2.3'),
});
const bazelDepWithoutDevDepNoVersion = fragments.record({
rule: fragments.string('bazel_dep'),
name: fragments.string('rules_foo'),
});
const gitOverrideWithGihubHost = fragments.record({
rule: fragments.string('git_override'),
module_name: fragments.string('rules_foo'),
Expand Down Expand Up @@ -131,6 +142,7 @@ describe('modules/manager/bazel-module/rules', () => {
it.each`
msg | a | exp
${'bazel_dep'} | ${bazelDepWithoutDevDep} | ${bazelDepPkgDep}
${'bazel_dep, no version'} | ${bazelDepWithoutDevDepNoVersion} | ${bazelDepPkgDepNoVersion}
${'git_override, GitHub host'} | ${gitOverrideWithGihubHost} | ${gitOverrideForGithubPkgDep}
${'git_override, unsupported host'} | ${gitOverrideWithUnsupportedHost} | ${gitOverrideForUnsupportedPkgDep}
${'archive_override'} | ${archiveOverride} | ${archiveOverridePkgDep}
Expand Down Expand Up @@ -169,41 +181,74 @@ describe('modules/manager/bazel-module/rules', () => {

describe('.toPackageDependencies()', () => {
const expectedBazelDepNoOverrides: PackageDependency[] = [bazelDepPkgDep];
const expectedBazelDepNoOverridesNoVersion: PackageDependency[] = [
bazelDepPkgDepNoVersion,
];
const expectedBazelDepAndGitOverride: PackageDependency[] = [
deepmerge(bazelDepPkgDep, { skipReason: 'git-dependency' }),
bazelModulePackageDepToPackageDependency(gitOverrideForGithubPkgDep),
];
const expectedBazelDepNoVersionAndGitOverride: PackageDependency[] = [
deepmerge(bazelDepPkgDepNoVersion, { skipReason: 'git-dependency' }),
bazelModulePackageDepToPackageDependency(gitOverrideForGithubPkgDep),
];
const expectedBazelDepAndSingleVersionOverride: PackageDependency[] = [
deepmerge(bazelDepPkgDep, {
skipReason: 'is-pinned',
registryUrls: [customRegistryUrl],
}),
bazelModulePackageDepToPackageDependency(singleVersionOverridePkgDep),
];
const expectedBazelDepNoVersionAndSingleVersionOverride: PackageDependency[] =
[
deepmerge(bazelDepPkgDepNoVersion, {
skipReason: 'is-pinned',
registryUrls: [customRegistryUrl],
}),
bazelModulePackageDepToPackageDependency(singleVersionOverridePkgDep),
];
const expectedBazelDepAndArchiveOverride: PackageDependency[] = [
deepmerge(bazelDepPkgDep, { skipReason: 'file-dependency' }),
bazelModulePackageDepToPackageDependency(archiveOverridePkgDep),
];
const expectedBazelDepNoVersionAndArchiveOverride: PackageDependency[] = [
deepmerge(bazelDepPkgDepNoVersion, { skipReason: 'file-dependency' }),
bazelModulePackageDepToPackageDependency(archiveOverridePkgDep),
];
const expectedBazelDepAndLocalPathOverride: PackageDependency[] = [
deepmerge(bazelDepPkgDep, { skipReason: 'local-dependency' }),
bazelModulePackageDepToPackageDependency(localPathOverridePkgDep),
];
const expectedBazelDepNoVersionAndLocalPathOverride: PackageDependency[] = [
deepmerge(bazelDepPkgDepNoVersion, { skipReason: 'local-dependency' }),
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] }),
];
const expectedBazelDepNoVersionWithRegistry: PackageDependency[] = [
deepmerge(bazelDepPkgDepNoVersion, { 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}
${'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]}
msg | a | exp
${'bazel_dep, no overrides'} | ${[bazelDepPkgDep]} | ${expectedBazelDepNoOverrides}
${'bazel_dep, no overrides, no version'} | ${[bazelDepPkgDepNoVersion]} | ${expectedBazelDepNoOverridesNoVersion}
${'bazel_dep & git_override'} | ${[bazelDepPkgDep, gitOverrideForGithubPkgDep]} | ${expectedBazelDepAndGitOverride}
${'bazel_dep, no version & git_override'} | ${[bazelDepPkgDepNoVersion, gitOverrideForGithubPkgDep]} | ${expectedBazelDepNoVersionAndGitOverride}
${'git_override, no bazel_dep'} | ${[gitOverrideForGithubPkgDep]} | ${[]}
${'bazel_dep & archive_override'} | ${[bazelDepPkgDep, archiveOverridePkgDep]} | ${expectedBazelDepAndArchiveOverride}
${'bazel_dep, no version & archive_override'} | ${[bazelDepPkgDepNoVersion, archiveOverridePkgDep]} | ${expectedBazelDepNoVersionAndArchiveOverride}
${'bazel_dep & local_path_override'} | ${[bazelDepPkgDep, localPathOverridePkgDep]} | ${expectedBazelDepAndLocalPathOverride}
${'bazel_dep, no version & local_path_override'} | ${[bazelDepPkgDepNoVersion, localPathOverridePkgDep]} | ${expectedBazelDepNoVersionAndLocalPathOverride}
${'single_version_override, with version and registry'} | ${[bazelDepPkgDep, singleVersionOverridePkgDep]} | ${expectedBazelDepAndSingleVersionOverride}
${'bazel_dep, no version & single_version_override, with version and registry'} | ${[bazelDepPkgDepNoVersion, singleVersionOverridePkgDep]} | ${expectedBazelDepNoVersionAndSingleVersionOverride}
${'single_version_override, with registry'} | ${[bazelDepPkgDep, singleVersionOverrideWithRegistryPkgDep]} | ${expectedBazelDepWithRegistry}
${'bazel_dep, no version & single_version_override, with registry'} | ${[bazelDepPkgDepNoVersion, singleVersionOverrideWithRegistryPkgDep]} | ${expectedBazelDepNoVersionWithRegistry}
${'single_version_override, without version and registry'} | ${[bazelDepPkgDep, singleVersionOverrideWithoutVersionAndRegistryPkgDep]} | ${[bazelDepPkgDep]}
${'bazel_dep, no version & single_version_override, without version and registry'} | ${[bazelDepPkgDepNoVersion, singleVersionOverrideWithoutVersionAndRegistryPkgDep]} | ${[bazelDepPkgDepNoVersion]}
`('with $msg', ({ msg, a, exp }) => {
const result = toPackageDependencies(a);
expect(result).toEqual(exp);
Expand Down
5 changes: 3 additions & 2 deletions lib/modules/manager/bazel-module/rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,15 @@ const BazelDepToPackageDep = RecordFragmentSchema.extend({
value: z.literal('bazel_dep'),
}),
name: StringFragmentSchema,
version: StringFragmentSchema,
version: StringFragmentSchema.optional(),
}),
}).transform(
({ children: { rule, name, version } }): BasePackageDep => ({
datasource: BazelDatasource.id,
depType: rule.value,
depName: name.value,
currentValue: version.value,
currentValue: version?.value,
skipReason: version ? undefined : 'unspecified-version',
}),
);

Expand Down
Loading