Skip to content

feat(bazel-module): Support git_repository #33415

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

Merged
merged 1 commit into from
Jan 8, 2025
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
15 changes: 14 additions & 1 deletion docs/usage/bazel.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,19 @@ archive_override(
Renovate ignores [`multiple_version_override`](https://bazel.build/rules/lib/globals/module#multiple_version_override).
`multiple_version_override` does not affect the processing of version updates for a module.

### `git_repository`

If Renovate finds a [`git_repository`](https://bazel.build/rules/lib/repo/git#git_repository), it evaluates the `commit` value at the specified `remote`.
`remote` is limited to github repos: `https://github.com/<owner>/<repo>.git`

```python
git_repository(
name = "rules_foo",
remote = "https://github.com/fooexample/rules_foo.git",
commit = "8c94e11c2b05b6f25ced5f23cd07d0cfd36edc1a",
)
```

## Legacy `WORKSPACE` files

Renovate extracts dependencies from the following repository rules:
Expand All @@ -160,7 +173,7 @@ Renovate extracts dependencies from the following repository rules:
It also recognizes when these repository rule names are prefixed with an underscore.
For example, `_http_archive` is treated the same as `http_archive`.

### `git_repository`
### `git_repository` (legacy)

Renovate updates any `git_repository` declaration that has the following:

Expand Down
26 changes: 26 additions & 0 deletions lib/modules/manager/bazel-module/extract.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -392,5 +392,31 @@ describe('modules/manager/bazel-module/extract', () => {
},
]);
});

it('returns git_repository dependencies', async () => {
const input = codeBlock`
git_repository(
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(1);
expect(result.deps).toEqual(
expect.arrayContaining([
{
datasource: GithubTagsDatasource.id,
depType: 'git_repository',
depName: 'rules_foo',
currentDigest: '850cb49c8649e463b80ef7984e7c744279746170',
packageName: 'example/rules_foo',
},
]),
);
});
});
});
16 changes: 15 additions & 1 deletion lib/modules/manager/bazel-module/extract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import type { RecordFragment } from './fragments';
import { parse } from './parser';
import { RuleToMavenPackageDep, fillRegistryUrls } from './parser/maven';
import { RuleToDockerPackageDep } from './parser/oci';
import { RuleToBazelModulePackageDep } from './rules';
import {
GitRepositoryToPackageDep,
RuleToBazelModulePackageDep,
} from './rules';
import * as rules from './rules';

export async function extractPackageFile(
Expand All @@ -18,9 +21,14 @@ export async function extractPackageFile(
try {
const records = parse(content);
const pfc = await extractBazelPfc(records, packageFile);
const gitRepositoryDeps = extractGitRepositoryDeps(records);
const mavenDeps = extractMavenDeps(records);
const dockerDeps = LooseArray(RuleToDockerPackageDep).parse(records);

if (gitRepositoryDeps.length) {
pfc.deps.push(...gitRepositoryDeps);
}

if (mavenDeps.length) {
pfc.deps.push(...mavenDeps);
}
Expand Down Expand Up @@ -57,6 +65,12 @@ async function extractBazelPfc(
return pfc;
}

function extractGitRepositoryDeps(
records: RecordFragment[],
): PackageDependency[] {
return LooseArray(GitRepositoryToPackageDep).parse(records);
}

function extractMavenDeps(records: RecordFragment[]): PackageDependency[] {
return LooseArray(RuleToMavenPackageDep)
.transform(fillRegistryUrls)
Expand Down
32 changes: 32 additions & 0 deletions lib/modules/manager/bazel-module/parser/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -315,5 +315,37 @@ describe('modules/manager/bazel-module/parser/index', () => {
),
]);
});

it('finds the git_repository', () => {
const input = codeBlock`
git_repository(
name = "rules_foo",
remote = "https://github.com/example/rules_foo.git",
commit = "6a2c2e22849b3e6b33d5ea9aa72222d4803a986a",
patches = ["//:rules_foo.patch"],
patch_strip = 1,
)
`;
const res = parse(input);
expect(res).toEqual([
fragments.record(
{
rule: fragments.string('git_repository'),
name: fragments.string('rules_foo'),
patches: fragments.array(
[fragments.string('//:rules_foo.patch')],
true,
),
commit: fragments.string(
'6a2c2e22849b3e6b33d5ea9aa72222d4803a986a',
),
remote: fragments.string(
'https://github.com/example/rules_foo.git',
),
},
true,
),
]);
});
});
});
1 change: 1 addition & 0 deletions lib/modules/manager/bazel-module/parser/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const supportedRules = [
'git_override',
'local_path_override',
'single_version_override',
'git_repository',
];
const supportedRulesRegex = regEx(`^${supportedRules.join('|')}$`);

Expand Down
38 changes: 38 additions & 0 deletions lib/modules/manager/bazel-module/rules.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type {
OverridePackageDep,
} from './rules';
import {
GitRepositoryToPackageDep,
RuleToBazelModulePackageDep,
bazelModulePackageDepToPackageDependency,
processModulePkgDeps,
Expand Down Expand Up @@ -72,6 +73,19 @@ const singleVersionOverrideWithoutVersionAndRegistryPkgDep: BasePackageDep = {
depName: 'rules_foo',
skipReason: 'ignored',
};
const gitRepositoryForGithubPkgDep: BasePackageDep = {
datasource: GithubTagsDatasource.id,
depType: 'git_repository',
depName: 'rules_foo',
packageName: 'example/rules_foo',
currentDigest: '850cb49c8649e463b80ef7984e7c744279746170',
};
const gitRepositoryForUnsupportedPkgDep: BasePackageDep = {
depType: 'git_repository',
depName: 'rules_foo',
currentDigest: '850cb49c8649e463b80ef7984e7c744279746170',
skipReason: 'unsupported-datasource',
};

describe('modules/manager/bazel-module/rules', () => {
describe('RuleToBazelModulePackageDep', () => {
Expand Down Expand Up @@ -129,6 +143,30 @@ describe('modules/manager/bazel-module/rules', () => {
});
});

describe('GitRepositoryToPackageDep', () => {
const gitRepositoryWithGihubHost = fragments.record({
rule: fragments.string('git_repository'),
name: fragments.string('rules_foo'),
remote: fragments.string('https://github.com/example/rules_foo.git'),
commit: fragments.string('850cb49c8649e463b80ef7984e7c744279746170'),
});
const gitRepositoryWithUnsupportedHost = fragments.record({
rule: fragments.string('git_repository'),
name: fragments.string('rules_foo'),
remote: fragments.string('https://nobuenos.com/example/rules_foo.git'),
commit: fragments.string('850cb49c8649e463b80ef7984e7c744279746170'),
});

it.each`
msg | a | exp
${'git_repository, GitHub host'} | ${gitRepositoryWithGihubHost} | ${gitRepositoryForGithubPkgDep}
${'git_repository, unsupported host'} | ${gitRepositoryWithUnsupportedHost} | ${gitRepositoryForUnsupportedPkgDep}
`('.parse() with $msg', ({ a, exp }) => {
const pkgDep = GitRepositoryToPackageDep.parse(a);
expect(pkgDep).toEqual(exp);
});
});

describe('.toPackageDependencies()', () => {
const expectedBazelDepNoOverrides: PackageDependency[] = [bazelDepPkgDep];
const expectedBazelDepAndGitOverride: PackageDependency[] = [
Expand Down
25 changes: 25 additions & 0 deletions lib/modules/manager/bazel-module/rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,3 +242,28 @@ export function toPackageDependencies(
): PackageDependency[] {
return collectByModule(packageDeps).map(processModulePkgDeps).flat();
}

export const GitRepositoryToPackageDep = RecordFragmentSchema.extend({
children: z.object({
rule: StringFragmentSchema.extend({
value: z.literal('git_repository'),
}),
name: StringFragmentSchema,
remote: StringFragmentSchema,
commit: StringFragmentSchema,
}),
}).transform(({ children: { rule, name, remote, commit } }): BasePackageDep => {
const gitRepo: BasePackageDep = {
depType: rule.value,
depName: name.value,
currentDigest: commit.value,
};
const ghPackageName = githubPackageName(remote.value);
if (is.nonEmptyString(ghPackageName)) {
gitRepo.datasource = GithubTagsDatasource.id;
gitRepo.packageName = ghPackageName;
} else {
gitRepo.skipReason = 'unsupported-datasource';
}
return gitRepo;
});
Loading