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.

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 19, 2024
1 parent 8433352 commit c327ff2
Show file tree
Hide file tree
Showing 8 changed files with 437 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,28 @@ class BazelModuleRegistryClientFunTest : WordSpec({
sourceInfo.integrity shouldBe "sha256-7t5x8oNxvzmqabRd4jsynTchQBbiBVJps7Xnz9QLWfU="
}
}

"CompositeBazelModuleRegistryService.kt.create" should {
"parse the 'registryFileHashes' property of the lock file (Bazel >= 7.2.0)" {
val expr1 = "https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/abseil-cpp/" +
"20230125.1/source.json"
val group1 = CompositeBazelModuleRegistryService.Companion.URL_REGEX.matchEntire(expr1)?.groups

group1?.get("server")
?.value shouldBe "https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/"
group1?.get("package")?.value shouldBe "abseil-cpp"

val expr2 = "https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/source.json"
val group2 = CompositeBazelModuleRegistryService.Companion.URL_REGEX.matchEntire(expr2)?.groups

group2?.get("server")?.value shouldBe "https://bcr.bazel.build/"
group2?.get("package")?.value shouldBe "rules_proto"

val expr3 = "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/source.json"
val group3 = CompositeBazelModuleRegistryService.Companion.URL_REGEX.matchEntire(expr3)?.groups

group3?.get("server")?.value shouldBe "https://bcr.bazel.build/"
group3?.get("package")?.value shouldBe "upb"
}
}
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* Copyright (C) 2024 The ORT Project Authors (see <https://github.com/oss-review-toolkit/ort/blob/main/NOTICE>)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
* License-Filename: LICENSE
*/

package org.ossreviewtoolkit.clients.bazelmoduleregistry

import java.io.File

import org.apache.logging.log4j.kotlin.logger

/**
* A composite Bazel module registry service that aggregates multiple [BazelModuleRegistryService] instances and
* delegates the package lookup to the corresponding registry. The first registry that contains the package is used.
* [packagesPerRegistry] is a map of [BazelModuleRegistryService] instances to the list of packages they are
* responsible for.
*/
class CompositeBazelModuleRegistryService(
private val packagesPerRegistry: Map<BazelModuleRegistryService, List<String>>
) : BazelModuleRegistryService {
companion object {
// A regular expression to extract the server and package parts of a registry URL.
internal val URL_REGEX = "^(?<server>.*/)modules/(?<package>[^/]+)/[^/]+/source\\.json$".toRegex()

/**
* Create a Composite Bazel Module Registry client instance.
*/
fun create(urls: Set<String>, projectDir: File): CompositeBazelModuleRegistryService {
val unknownKey = "UNKNOWN"

val packagesPerServer = urls.filter { it.endsWith("source.json") }.map {
val groups = URL_REGEX.matchEntire(it)?.groups

val key = groups?.get("server")?.value ?: unknownKey
val value = groups?.get("package")?.value ?: it

key to value
}.groupByTo(mutableMapOf(), { it.first }) { it.second }

packagesPerServer.remove(unknownKey)?.let {
logger.warn {
"The following URLs cannot be mapped to a server root:"
}

it.forEach { logger.warn { it } }
}

val packagesPerRegistry = packagesPerServer.mapKeys { entry ->
val url = entry.key

if (url.startsWith("file://")) {
val localRegistryURL = url.replace("%workspace%", projectDir.absolutePath)
logger.info {
"Using local Bazel module registry at '$localRegistryURL'."
}

LocalBazelModuleRegistryService(File(localRegistryURL))
} else {
RemoteBazelModuleRegistryService.create(url)
}
}

return CompositeBazelModuleRegistryService(packagesPerRegistry)
}
}

override suspend fun getModuleMetadata(name: String): ModuleMetadata {
val registry = packagesPerRegistry.entries.find { name in it.value }
?: throw IllegalArgumentException("No registry found for package '$name'.")
// TODO check if other registry entries contain the package

return registry.key.getModuleMetadata(name)
}

override suspend fun getModuleSourceInfo(name: String, version: String): ModuleSourceInfo {
val registry = packagesPerRegistry.entries.find { name in it.value }
?: throw IllegalArgumentException("No registry found for package '$name'.")
// TODO check if other registry entries contain the package

return registry.key.getModuleSourceInfo(name, version)
}
}
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)
Loading

0 comments on commit c327ff2

Please sign in to comment.