From 2ac103ac4323abfbe491f4ca43352a018567557d Mon Sep 17 00:00:00 2001 From: Nicolas Nobelis Date: Wed, 18 Sep 2024 13:44:37 +0200 Subject: [PATCH] fix(bazel): `MODULE.bazel` files from a local registry should be ignored `MODULE.bazel` files present in the local registry should not be considered as definition files. Fixes #9076. Signed-off-by: Nicolas Nobelis --- .../kotlin/LocalBazelModuleRegistryService.kt | 6 +- .../bazel-expected-output-local-registry2.yml | 110 ++++++++++++++++++ .../src/funTest/kotlin/BazelDetectionTest.kt | 23 ++-- .../bazel/src/main/kotlin/Bazel.kt | 17 +++ 4 files changed, 141 insertions(+), 15 deletions(-) create mode 100644 plugins/package-managers/bazel/src/funTest/assets/projects/synthetic/bazel-expected-output-local-registry2.yml diff --git a/clients/bazel-module-registry/src/main/kotlin/LocalBazelModuleRegistryService.kt b/clients/bazel-module-registry/src/main/kotlin/LocalBazelModuleRegistryService.kt index 3901c40ecc874..e7773c447df31 100644 --- a/clients/bazel-module-registry/src/main/kotlin/LocalBazelModuleRegistryService.kt +++ b/clients/bazel-module-registry/src/main/kotlin/LocalBazelModuleRegistryService.kt @@ -27,6 +27,8 @@ import kotlinx.serialization.json.decodeFromStream import org.apache.logging.log4j.kotlin.logger private const val BAZEL_MODULES_DIR = "modules" +const val METADATA_JSON = "metadata.json" +const val SOURCE_JSON = "source.json" /** * A Bazel registry which is located on the local file system. @@ -71,7 +73,7 @@ class LocalBazelModuleRegistryService(directory: File) : BazelModuleRegistryServ } override suspend fun getModuleMetadata(name: String): ModuleMetadata { - val metadataJson = moduleDirectory.resolve(name).resolve("metadata.json") + val metadataJson = moduleDirectory.resolve(name).resolve(METADATA_JSON) require(metadataJson.isFile) return metadataJson.inputStream().use { JSON.decodeFromStream(it) @@ -79,7 +81,7 @@ class LocalBazelModuleRegistryService(directory: File) : BazelModuleRegistryServ } override suspend fun getModuleSourceInfo(name: String, version: String): ModuleSourceInfo { - val sourceJson = moduleDirectory.resolve(name).resolve(version).resolve("source.json") + val sourceJson = moduleDirectory.resolve(name).resolve(version).resolve(SOURCE_JSON) require(sourceJson.isFile) return sourceJson.inputStream().use { JSON.decodeFromStream(it) diff --git a/plugins/package-managers/bazel/src/funTest/assets/projects/synthetic/bazel-expected-output-local-registry2.yml b/plugins/package-managers/bazel/src/funTest/assets/projects/synthetic/bazel-expected-output-local-registry2.yml new file mode 100644 index 0000000000000..06ec9f122821f --- /dev/null +++ b/plugins/package-managers/bazel/src/funTest/assets/projects/synthetic/bazel-expected-output-local-registry2.yml @@ -0,0 +1,110 @@ +--- +repository: + vcs: + type: "Git" + url: "" + revision: "" + path: "plugins/package-managers/bazel/src/funTest/assets/projects/synthetic/bazel-local-registry2" + vcs_processed: + type: "Git" + url: "" + revision: "" + path: "plugins/package-managers/bazel/src/funTest/assets/projects/synthetic/bazel-local-registry2" + config: {} +analyzer: + start_time: "1970-01-01T00:00:00Z" + end_time: "1970-01-01T00:00:00Z" + environment: + ort_version: "HEAD" + build_jdk: "" + java_version: "" + os: "" + processors: "" + max_memory: "" + variables: {} + tool_versions: {} + config: + allow_dynamic_versions: false + skip_excluded: false + result: + projects: + - id: "Bazel::plugins/package-managers/bazel/src/funTest/assets/projects/synthetic/bazel-local-registry2/MODULE.bazel:" + definition_file_path: "" + declared_licenses: [] + declared_licenses_processed: {} + vcs: + type: "Git" + url: "" + revision: "" + path: "" + vcs_processed: + type: "Git" + url: "" + revision: "" + path: "" + homepage_url: "" + scopes: + - name: "main" + dependencies: + - id: "Bazel::module_a:0.0.1" + linkage: "STATIC" + dependencies: + - id: "Bazel::module_b:0.0.1" + linkage: "STATIC" + packages: + - id: "Bazel::module_a:0.0.1" + purl: "pkg:generic/module_a@0.0.1" + declared_licenses: [] + declared_licenses_processed: {} + description: "" + homepage_url: "" + binary_artifact: + url: "" + hash: + value: "" + algorithm: "" + source_artifact: + url: "https://example.com/module_a-0.0.1.zip" + hash: + value: "562c4be7507dc6fb4997ecd648bf935d84efe17b54715fa5cfbddac05279f668" + algorithm: "SHA-256" + vcs: + type: "Git" + url: "" + revision: "" + path: "" + vcs_processed: + type: "Git" + url: "" + revision: "" + path: "" + - id: "Bazel::module_b:0.0.1" + purl: "pkg:generic/module_b@0.0.1" + declared_licenses: [] + declared_licenses_processed: {} + description: "" + homepage_url: "" + binary_artifact: + url: "" + hash: + value: "" + algorithm: "" + source_artifact: + url: "https://example.com/module_b-0.0.1.zip" + hash: + value: "562c4be7507dc6fb4997ecd648bf935d84efe17b54715fa5cfbddac05279f668" + algorithm: "SHA-256" + vcs: + type: "Git" + url: "" + revision: "" + path: "" + vcs_processed: + type: "Git" + url: "" + revision: "" + path: "" +scanner: null +advisor: null +evaluator: null +resolved_configuration: {} diff --git a/plugins/package-managers/bazel/src/funTest/kotlin/BazelDetectionTest.kt b/plugins/package-managers/bazel/src/funTest/kotlin/BazelDetectionTest.kt index fffc46eb9d860..968c651e537f4 100644 --- a/plugins/package-managers/bazel/src/funTest/kotlin/BazelDetectionTest.kt +++ b/plugins/package-managers/bazel/src/funTest/kotlin/BazelDetectionTest.kt @@ -19,28 +19,25 @@ package org.ossreviewtoolkit.plugins.packagemanagers.bazel -import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.nulls.shouldNotBeNull -import io.kotest.matchers.string.shouldContain +import io.kotest.matchers.should import org.ossreviewtoolkit.analyzer.analyze +import org.ossreviewtoolkit.model.toYaml import org.ossreviewtoolkit.utils.test.getAssetFile +import org.ossreviewtoolkit.utils.test.matchExpectedResult +import org.ossreviewtoolkit.utils.test.patchActualResult class BazelDetectionTest : StringSpec({ "MODULE.bazel files present in a local registry should not be considered as definition files" { val definitionFile = getAssetFile("projects/synthetic/bazel-local-registry2/MODULE.bazel") + val expectedResultFile = getAssetFile("projects/synthetic/bazel-expected-output-local-registry2.yml") - val exception = shouldThrow { - analyze(definitionFile.parentFile, packageManagers = listOf(Bazel.Factory())) - } + val result = analyze(definitionFile.parentFile, packageManagers = listOf(Bazel.Factory())) - exception.shouldNotBeNull { - // Running the Analyzer on a project depending on packages present in a local registry currently fails - // with this message (issue #9076). This is because the "MODULE.bazel" files present in the local - // registry should not be considered as definition files. - message shouldContain - "Unable to create the AnalyzerResult as it contains packages and projects with the same ids" - } + patchActualResult(result.toYaml(), patchStartAndEndTime = true) should matchExpectedResult( + expectedResultFile, + definitionFile + ) } }) diff --git a/plugins/package-managers/bazel/src/main/kotlin/Bazel.kt b/plugins/package-managers/bazel/src/main/kotlin/Bazel.kt index c2b7b0015e2a4..65e845267dc25 100644 --- a/plugins/package-managers/bazel/src/main/kotlin/Bazel.kt +++ b/plugins/package-managers/bazel/src/main/kotlin/Bazel.kt @@ -31,9 +31,11 @@ import org.ossreviewtoolkit.analyzer.PackageManager import org.ossreviewtoolkit.clients.bazelmoduleregistry.ArchiveOverride import org.ossreviewtoolkit.clients.bazelmoduleregistry.BazelModuleRegistryService import org.ossreviewtoolkit.clients.bazelmoduleregistry.LocalBazelModuleRegistryService +import org.ossreviewtoolkit.clients.bazelmoduleregistry.METADATA_JSON import org.ossreviewtoolkit.clients.bazelmoduleregistry.ModuleMetadata import org.ossreviewtoolkit.clients.bazelmoduleregistry.ModuleSourceInfo import org.ossreviewtoolkit.clients.bazelmoduleregistry.RemoteBazelModuleRegistryService +import org.ossreviewtoolkit.clients.bazelmoduleregistry.SOURCE_JSON import org.ossreviewtoolkit.downloader.VersionControlSystem import org.ossreviewtoolkit.model.Hash import org.ossreviewtoolkit.model.HashAlgorithm @@ -55,6 +57,7 @@ import org.ossreviewtoolkit.model.createAndLogIssue import org.ossreviewtoolkit.model.orEmpty import org.ossreviewtoolkit.utils.common.CommandLineTool import org.ossreviewtoolkit.utils.common.ProcessCapture +import org.ossreviewtoolkit.utils.common.alsoIfNull import org.ossreviewtoolkit.utils.common.collectMessages import org.ossreviewtoolkit.utils.common.withoutPrefix import org.ossreviewtoolkit.utils.ort.createOrtTempFile @@ -86,6 +89,20 @@ class Bazel( override fun command(workingDir: File?) = "bazel" + /** + * To avoid processing the module files in a local registry as definition files, ignore them if they are aside a + * source.json file and under a directory with a metadata.json file. This simple metric avoids parsing the .bazelrc + * in the top directory of the project to find out if a MODULE.bazel file is part of a local registry or not. + */ + override fun mapDefinitionFiles(definitionFiles: List): List = + definitionFiles.mapNotNull { file -> + file.takeUnless { + it.resolveSibling(SOURCE_JSON).isFile && it.parentFile.resolveSibling(METADATA_JSON).isFile + }.alsoIfNull { + logger.info { "Ignoring definition file '$file' as it is a module of a local registry." } + } + } + override fun run(vararg args: CharSequence, workingDir: File?, environment: Map): ProcessCapture = super.run( args = args,