diff --git a/docs/usage/bazel.md b/docs/usage/bazel.md index 4a95e19c55e2e1..3ef033f1685ecd 100644 --- a/docs/usage/bazel.md +++ b/docs/usage/bazel.md @@ -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//.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: @@ -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: diff --git a/lib/modules/manager/bazel-module/extract.spec.ts b/lib/modules/manager/bazel-module/extract.spec.ts index 336d6172a3ba13..53e5ca47845b30 100644 --- a/lib/modules/manager/bazel-module/extract.spec.ts +++ b/lib/modules/manager/bazel-module/extract.spec.ts @@ -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', + }, + ]), + ); + }); }); }); diff --git a/lib/modules/manager/bazel-module/extract.ts b/lib/modules/manager/bazel-module/extract.ts index b62bcbccdd983e..8774057c32833f 100644 --- a/lib/modules/manager/bazel-module/extract.ts +++ b/lib/modules/manager/bazel-module/extract.ts @@ -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( @@ -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); } @@ -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) diff --git a/lib/modules/manager/bazel-module/parser/index.spec.ts b/lib/modules/manager/bazel-module/parser/index.spec.ts index 26ce0ae5c45e37..f3783f87774f02 100644 --- a/lib/modules/manager/bazel-module/parser/index.spec.ts +++ b/lib/modules/manager/bazel-module/parser/index.spec.ts @@ -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, + ), + ]); + }); }); }); diff --git a/lib/modules/manager/bazel-module/parser/module.ts b/lib/modules/manager/bazel-module/parser/module.ts index 80371274c029e3..54371e9a7bd25d 100644 --- a/lib/modules/manager/bazel-module/parser/module.ts +++ b/lib/modules/manager/bazel-module/parser/module.ts @@ -9,6 +9,7 @@ const supportedRules = [ 'git_override', 'local_path_override', 'single_version_override', + 'git_repository', ]; const supportedRulesRegex = regEx(`^${supportedRules.join('|')}$`); diff --git a/lib/modules/manager/bazel-module/rules.spec.ts b/lib/modules/manager/bazel-module/rules.spec.ts index 048471c6504d39..c3a8b2a2207cef 100644 --- a/lib/modules/manager/bazel-module/rules.spec.ts +++ b/lib/modules/manager/bazel-module/rules.spec.ts @@ -10,6 +10,7 @@ import type { OverridePackageDep, } from './rules'; import { + GitRepositoryToPackageDep, RuleToBazelModulePackageDep, bazelModulePackageDepToPackageDependency, processModulePkgDeps, @@ -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', () => { @@ -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[] = [ diff --git a/lib/modules/manager/bazel-module/rules.ts b/lib/modules/manager/bazel-module/rules.ts index fda2cf253c0fd0..8f1bb2e626d77a 100644 --- a/lib/modules/manager/bazel-module/rules.ts +++ b/lib/modules/manager/bazel-module/rules.ts @@ -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; +});