Skip to content

Commit

Permalink
feat(Bazel): Support Bazel 7.2.0
Browse files Browse the repository at this point in the history
Bazel 7.2.0 has a new lock file format (see [1]): 'cmdRegistries' have been
replaced by a new property 'registryFileHashes'. This commit makes the
identification of the registry URLs dynamic based on the version of Bazel
used by the project to scan.
Newer versions of Bazel have to be supported as a fixed version can be
forced by the user in a .bazelversion file at the root of the repository.

Fixes #8796.

[1]: https://bazel.build/versions/7.2.0/external/lockfile

Signed-off-by: Nicolas Nobelis <[email protected]>
  • Loading branch information
nnobelis committed Jul 26, 2024
1 parent d9f073d commit 7f6549b
Show file tree
Hide file tree
Showing 8 changed files with 466 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
---
project:
id: "Bazel::plugins/package-managers/bazel/src/funTest/assets/projects/synthetic/bazel-7.2/MODULE.bazel:"
definition_file_path: "<REPLACE_DEFINITION_FILE_PATH>"
declared_licenses: []
declared_licenses_processed: {}
vcs:
type: "Git"
url: "<REPLACE_URL_PROCESSED>"
revision: "<REPLACE_REVISION>"
path: "<REPLACE_PATH>"
vcs_processed:
type: "Git"
url: "<REPLACE_URL_PROCESSED>"
revision: "<REPLACE_REVISION>"
path: "<REPLACE_PATH>"
homepage_url: ""
scopes:
- name: "dev"
dependencies:
- id: "Bazel::googletest:1.14.0"
linkage: "STATIC"
dependencies:
- id: "Bazel::abseil-cpp:20230125.1"
linkage: "STATIC"
dependencies:
- id: "Bazel::bazel_skylib:1.6.1"
linkage: "STATIC"
dependencies:
- id: "Bazel::platforms:0.0.9"
linkage: "STATIC"
- id: "Bazel::platforms:0.0.9"
linkage: "STATIC"
- id: "Bazel::rules_cc:0.0.9"
linkage: "STATIC"
- id: "Bazel::platforms:0.0.9"
linkage: "STATIC"
dependencies:
- id: "Bazel::rules_license:0.0.7"
linkage: "STATIC"
- id: "Bazel::rules_cc:0.0.9"
linkage: "STATIC"
dependencies:
- id: "Bazel::platforms:0.0.9"
linkage: "STATIC"
- name: "main"
dependencies:
- id: "Bazel::glog:0.5.0"
linkage: "STATIC"
dependencies:
- id: "Bazel::gflags:2.2.2"
linkage: "STATIC"
packages:
- id: "Bazel::abseil-cpp:20230125.1"
purl: "pkg:generic/[email protected]"
declared_licenses: []
declared_licenses_processed: {}
description: ""
homepage_url: "https://github.com/abseil/abseil-cpp"
binary_artifact:
url: ""
hash:
value: ""
algorithm: ""
source_artifact:
url: "https://github.com/abseil/abseil-cpp/archive/refs/tags/20230125.1.tar.gz"
hash:
value: "81311c17599b3712069ded20cca09a62ab0bf2a89dfa16993786c8782b7ed145"
algorithm: "SHA-256"
vcs:
type: "Git"
url: "https://github.com/abseil/abseil-cpp"
revision: ""
path: ""
vcs_processed:
type: "Git"
url: "https://github.com/abseil/abseil-cpp.git"
revision: ""
path: ""
- id: "Bazel::bazel_skylib:1.6.1"
purl: "pkg:generic/[email protected]"
declared_licenses: []
declared_licenses_processed: {}
description: ""
homepage_url: "https://github.com/bazelbuild/bazel-skylib"
binary_artifact:
url: ""
hash:
value: ""
algorithm: ""
source_artifact:
url: "https://github.com/bazelbuild/bazel-skylib/releases/download/1.6.1/bazel-skylib-1.6.1.tar.gz"
hash:
value: "9f38886a40548c6e96c106b752f242130ee11aaa068a56ba7e56f4511f33e4f2"
algorithm: "SHA-256"
vcs:
type: "Git"
url: "https://github.com/bazelbuild/bazel-skylib"
revision: ""
path: ""
vcs_processed:
type: "Git"
url: "https://github.com/bazelbuild/bazel-skylib.git"
revision: ""
path: ""
- id: "Bazel::gflags:2.2.2"
purl: "pkg:generic/[email protected]"
declared_licenses: []
declared_licenses_processed: {}
description: ""
homepage_url: "https://gflags.github.io/gflags/"
binary_artifact:
url: ""
hash:
value: ""
algorithm: ""
source_artifact:
url: "https://github.com/gflags/gflags/archive/refs/tags/v2.2.2.tar.gz"
hash:
value: "34af2f15cf7367513b352bdcd2493ab14ce43692d2dcd9dfc499492966c64dcf"
algorithm: "SHA-256"
vcs:
type: "Git"
url: "https://github.com/gflags/gflags"
revision: ""
path: ""
vcs_processed:
type: "Git"
url: "https://github.com/gflags/gflags.git"
revision: ""
path: ""
- id: "Bazel::glog:0.5.0"
purl: "pkg:generic/[email protected]"
declared_licenses: []
declared_licenses_processed: {}
description: ""
homepage_url: "https://github.com/google/glog"
binary_artifact:
url: ""
hash:
value: ""
algorithm: ""
source_artifact:
url: "https://github.com/google/glog/archive/refs/tags/v0.5.0.tar.gz"
hash:
value: "eede71f28371bf39aa69b45de23b329d37214016e2055269b3b5e7cfd40b59f5"
algorithm: "SHA-256"
vcs:
type: "Git"
url: "https://github.com/google/glog"
revision: ""
path: ""
vcs_processed:
type: "Git"
url: "https://github.com/google/glog.git"
revision: ""
path: ""
- id: "Bazel::googletest:1.14.0"
purl: "pkg:generic/[email protected]"
declared_licenses: []
declared_licenses_processed: {}
description: ""
homepage_url: "https://google.github.io/googletest/"
binary_artifact:
url: ""
hash:
value: ""
algorithm: ""
source_artifact:
url: "https://github.com/google/googletest/archive/refs/tags/v1.14.0.tar.gz"
hash:
value: "8ad598c73ad796e0d8280b082cebd82a630d73e73cd3c70057938a6501bba5d7"
algorithm: "SHA-256"
vcs:
type: "Git"
url: "https://github.com/google/googletest"
revision: ""
path: ""
vcs_processed:
type: "Git"
url: "https://github.com/google/googletest.git"
revision: ""
path: ""
- id: "Bazel::platforms:0.0.9"
purl: "pkg:generic/[email protected]"
declared_licenses: []
declared_licenses_processed: {}
description: ""
homepage_url: "https://github.com/bazelbuild/platforms"
binary_artifact:
url: ""
hash:
value: ""
algorithm: ""
source_artifact:
url: "https://github.com/bazelbuild/platforms/releases/download/0.0.9/platforms-0.0.9.tar.gz"
hash:
value: "5eda539c841265031c2f82d8ae7a3a6490bd62176e0c038fc469eabf91f6149b"
algorithm: "SHA-256"
vcs:
type: "Git"
url: "https://github.com/bazelbuild/platforms"
revision: ""
path: ""
vcs_processed:
type: "Git"
url: "https://github.com/bazelbuild/platforms.git"
revision: ""
path: ""
- id: "Bazel::rules_cc:0.0.9"
purl: "pkg:generic/[email protected]"
declared_licenses: []
declared_licenses_processed: {}
description: ""
homepage_url: "https://github.com/bazelbuild/rules_cc"
binary_artifact:
url: ""
hash:
value: ""
algorithm: ""
source_artifact:
url: "https://github.com/bazelbuild/rules_cc/releases/download/0.0.9/rules_cc-0.0.9.tar.gz"
hash:
value: "2037875b9a4456dce4a79d112a8ae885bbc4aad968e6587dca6e64f3a0900cdf"
algorithm: "SHA-256"
vcs:
type: "Git"
url: ""
revision: ""
path: ""
vcs_processed:
type: "Git"
url: ""
revision: ""
path: ""
- id: "Bazel::rules_license:0.0.7"
purl: "pkg:generic/[email protected]"
declared_licenses: []
declared_licenses_processed: {}
description: ""
homepage_url: "https://github.com/bazelbuild/rules_license"
binary_artifact:
url: ""
hash:
value: ""
algorithm: ""
source_artifact:
url: "https://github.com/bazelbuild/rules_license/releases/download/0.0.7/rules_license-0.0.7.tar.gz"
hash:
value: "4531deccb913639c30e5c7512a054d5d875698daeb75d8cf90f284375fe7c360"
algorithm: "SHA-256"
vcs:
type: "Git"
url: "https://github.com/bazelbuild/rules_license"
revision: ""
path: ""
vcs_processed:
type: "Git"
url: "https://github.com/bazelbuild/rules_license.git"
revision: ""
path: ""
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
7.2.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
bazel_dep(name = "glog", version = "0.5.0", repo_name = "com_github_google_glog")
bazel_dep(name = "googletest", version = "1.14.0", repo_name = "com_google_googletest", dev_dependency = True)
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,13 @@ class BazelFunTest : StringSpec({

result.toYaml() should matchExpectedResult(expectedResultFile, definitionFile)
}

"Dependencies are detected correctly with Bazel 7.2.0" {
val definitionFile = getAssetFile("projects/synthetic/bazel-7.2/MODULE.bazel")
val expectedResultFile = getAssetFile("projects/synthetic/bazel-7.2-expected-output.yml")

val result = create("Bazel").resolveSingleProject(definitionFile)

result.toYaml() should matchExpectedResult(expectedResultFile, definitionFile)
}
})
42 changes: 32 additions & 10 deletions plugins/package-managers/bazel/src/main/kotlin/Bazel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -109,16 +109,7 @@ class Bazel(
// If no lockfile is present, getDependencyGraph() runs "bazel mod graph", which creates a MODULE.bazel.lock
// file as a side effect. That file contains the URL of the Bazel module registry that was used for dependency
// resolution.
val registryUrl = parseLockfile(lockfile).registryUrl()

val registry = registryUrl.withoutPrefix("file://")?.let {
val localRegistryURL = it.replace("%workspace%", projectDir.absolutePath)
logger.info {
"Using local Bazel module registry at '$localRegistryURL'."
}

LocalBazelModuleRegistryService(File(localRegistryURL))
} ?: RemoteBazelModuleRegistryService.create(registryUrl)
val registry = determineRegistry(parseLockfile(lockfile), projectDir)

val packages = getPackages(scopes, registry)

Expand All @@ -143,6 +134,37 @@ class Bazel(
)
}

/**
* This function determines the Bazel module registry to use based on the given [lockfile]: If this is a lockfile
* generated by Bazel version >= 7.2.0, a [CompositeBazelModuleRegistryService] based on the "registryFileHashes"
* will be returned. Else, either a [LocalBazelModuleRegistryService] or a [RemoteBazelModuleRegistryService] based
* on the "cmdRegistries" will be returned.
*/
private fun determineRegistry(lockfile: Lockfile, projectDir: File): BazelModuleRegistryService {
// Bazel version < 7.2.0.
if (lockfile.flags != null) {
val registryUrl = lockfile.registryUrl()

return registryUrl.withoutPrefix("file://")?.let {
val localRegistryURL = it.replace("%workspace%", projectDir.absolutePath)
logger.info {
"Using local Bazel module registry at '$localRegistryURL'."
}

LocalBazelModuleRegistryService(File(localRegistryURL))
} ?: RemoteBazelModuleRegistryService.create(registryUrl)
}

// Bazel version >= 7.2.0.
if (lockfile.registryFileHashes != null) {
return CompositeBazelModuleRegistryService.create(lockfile.registryFileHashes.keys, projectDir)
}

val msg = "Bazel registry URL cannot be determined from the lockfile."
logger.error(msg)
error(msg)
}

private fun getPackages(scopes: Set<Scope>, registry: BazelModuleRegistryService): Set<Package> {
val ids = scopes.collectDependencies()
val moduleMetadataForId = ids.associateWith { getModuleMetadata(it, registry) }
Expand Down
12 changes: 11 additions & 1 deletion plugins/package-managers/bazel/src/main/kotlin/BazelModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,18 @@ private val json = Json { ignoreUnknownKeys = true }
*/
@Serializable
internal data class Lockfile(
val flags: Flags? = null
// The flags containing the registry URLs (Bazel < 7.2.0).
val flags: Flags? = null,

// The registry URLs of the project's dependencies packages (Bazel >= 7.2.0).
val registryFileHashes: Map<String, String>? = null
) {
init {
require((flags != null && registryFileHashes == null) || (flags == null && registryFileHashes != null)) {
"Exactly one of 'flags' and 'registryFileHashes' must be set."
}
}

// TODO Support multiple registries.
fun registryUrl(): String? = flags?.cmdRegistries?.getOrElse(0) { null }
}
Expand Down
Loading

0 comments on commit 7f6549b

Please sign in to comment.