From 3df00a601b8a2349341c3db93e2e398f5f78e890 Mon Sep 17 00:00:00 2001 From: Simon Stewart Date: Wed, 18 Sep 2024 11:16:14 +0100 Subject: [PATCH] Fix the `alias` generated when using `bzlmod` and the `maven` resolver (#1249) This always assumed that the repo with the default name was visible but what we actually need is the canonical repo name. --- BUILD | 1 + examples/bzlmod/BUILD | 11 +++ examples/bzlmod/MODULE.bazel | 22 ++++-- .../bzlmod/alternative_maven_install.json | 78 +++++++++++++++++++ private/extensions/maven.bzl | 4 +- private/rules/maven_bom.bzl | 23 ++---- repositories.bzl | 8 ++ setup.bzl | 3 + 8 files changed, 126 insertions(+), 24 deletions(-) create mode 100644 examples/bzlmod/alternative_maven_install.json diff --git a/BUILD b/BUILD index 9bb85b6bd..770e6d76e 100644 --- a/BUILD +++ b/BUILD @@ -12,6 +12,7 @@ bzl_library( srcs = [ ":defs.bzl", ":specs.bzl", + "@bazel_features//:bzl_files", "@rules_license//:docs_deps", ], visibility = [ diff --git a/examples/bzlmod/BUILD b/examples/bzlmod/BUILD index e69de29bb..5dee0eef4 100644 --- a/examples/bzlmod/BUILD +++ b/examples/bzlmod/BUILD @@ -0,0 +1,11 @@ +load("@rules_jvm_external//:defs.bzl", "artifact") + +# You can load artifacts from different `maven.install` tags by using the +# `repository_name` parameter of the `artifact` macro. +alias( + name = "junit-api", + actual = artifact( + "org.junit.jupiter:junit-jupiter-api", + repository_name = "alternative_resolver", + ), +) diff --git a/examples/bzlmod/MODULE.bazel b/examples/bzlmod/MODULE.bazel index 150ed0c60..258e0b9f1 100644 --- a/examples/bzlmod/MODULE.bazel +++ b/examples/bzlmod/MODULE.bazel @@ -3,7 +3,7 @@ module( version = "6.0", ) -bazel_dep(name = "rules_jvm_external", version = "6.0") +bazel_dep(name = "rules_jvm_external", version = "0.0") local_path_override( module_name = "rules_jvm_external", # matches the name of the `bazel_dep` path = "../..", @@ -23,8 +23,20 @@ maven.install( fetch_sources = True, lock_file = "//:maven_install.json", ) -use_repo( - maven, - "maven", - "unpinned_maven", + +# The default resolver cannot handle Maven BOMs, but the `maven` +# resolver can. Demonstrate how to use it. +maven.install( + name = "alternative_resolver", + artifacts = [ + "org.junit.jupiter:junit-jupiter-api", + ], + boms = [ + "org.junit:junit-bom:5.11.0", + ], + # Before the first pin, this file was completely empty. Running: + # `REPIN=1 bazel run @alternative_resolver//:pin` generated it. + lock_file = "//:alternative_maven_install.json", + resolver = "maven", ) +use_repo(maven, "alternative_resolver", "maven") diff --git a/examples/bzlmod/alternative_maven_install.json b/examples/bzlmod/alternative_maven_install.json new file mode 100644 index 000000000..8d3706540 --- /dev/null +++ b/examples/bzlmod/alternative_maven_install.json @@ -0,0 +1,78 @@ +{ + "__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": "THERE_IS_NO_DATA_ONLY_ZUUL", + "__INPUT_ARTIFACTS_HASH": 126045399, + "__RESOLVED_ARTIFACTS_HASH": 246607592, + "artifacts": { + "org.apiguardian:apiguardian-api": { + "shasums": { + "jar": "b509448ac506d607319f182537f0b35d71007582ec741832a1f111e5b5b70b38" + }, + "version": "1.1.2" + }, + "org.junit.jupiter:junit-jupiter-api": { + "shasums": { + "jar": "42aa202fc862f76cc5af65b47b1c0b1961cdd79cd2216405a6dfa2bd20b20974" + }, + "version": "5.11.0" + }, + "org.junit.platform:junit-platform-commons": { + "shasums": { + "jar": "609333a4545f9018eb0c59071efd30663a9e9fdce528121b65a04c27e5fc26a7" + }, + "version": "1.11.0" + }, + "org.opentest4j:opentest4j": { + "shasums": { + "jar": "48e2df636cab6563ced64dcdff8abb2355627cb236ef0bf37598682ddf742f1b" + }, + "version": "1.3.0" + } + }, + "dependencies": { + "org.junit.jupiter:junit-jupiter-api": [ + "org.apiguardian:apiguardian-api", + "org.junit.platform:junit-platform-commons", + "org.opentest4j:opentest4j" + ], + "org.junit.platform:junit-platform-commons": [ + "org.apiguardian:apiguardian-api" + ] + }, + "packages": { + "org.apiguardian:apiguardian-api": [ + "org.apiguardian.api" + ], + "org.junit.jupiter:junit-jupiter-api": [ + "org.junit.jupiter.api", + "org.junit.jupiter.api.condition", + "org.junit.jupiter.api.extension", + "org.junit.jupiter.api.extension.support", + "org.junit.jupiter.api.function", + "org.junit.jupiter.api.io", + "org.junit.jupiter.api.parallel" + ], + "org.junit.platform:junit-platform-commons": [ + "org.junit.platform.commons", + "org.junit.platform.commons.annotation", + "org.junit.platform.commons.function", + "org.junit.platform.commons.logging", + "org.junit.platform.commons.support", + "org.junit.platform.commons.support.conversion", + "org.junit.platform.commons.util" + ], + "org.opentest4j:opentest4j": [ + "org.opentest4j" + ] + }, + "repositories": { + "https://repo1.maven.org/maven2/": [ + "org.apiguardian:apiguardian-api", + "org.junit.jupiter:junit-jupiter-api", + "org.junit.platform:junit-platform-commons", + "org.opentest4j:opentest4j" + ] + }, + "services": {}, + "skipped": [], + "version": "2" +} diff --git a/private/extensions/maven.bzl b/private/extensions/maven.bzl index cbe638941..cbe406479 100644 --- a/private/extensions/maven.bzl +++ b/private/extensions/maven.bzl @@ -434,10 +434,12 @@ def maven_impl(mctx): additional_coursier_options = repo.get("additional_coursier_options"), ) else: + workspace_prefix = "@@" if bazel_features.external_deps.is_bzlmod_enabled else "@" + # Only the coursier resolver allows the lock file to be omitted. unpinned_maven_pin_command_alias( name = "unpinned_" + name, - alias = "@%s//:pin" % name, + alias = "%s%s//:pin" % (workspace_prefix, name), ) if repo.get("generate_compat_repositories") and not repo.get("lock_file"): diff --git a/private/rules/maven_bom.bzl b/private/rules/maven_bom.bzl index 906c68ccf..f391ab5c8 100644 --- a/private/rules/maven_bom.bzl +++ b/private/rules/maven_bom.bzl @@ -1,23 +1,14 @@ +load("@bazel_features//:features.bzl", "bazel_features") load("//private/lib:coordinates.bzl", "unpack_coordinates") load(":maven_bom_fragment.bzl", "MavenBomFragmentInfo") load(":maven_publish.bzl", "maven_publish") load(":maven_utils.bzl", "generate_pom") -_NON_EXISTENT_LABEL = Label("//:thisdoesnotexistinrulesjvmexternal") - -def _is_using_bzlmod(): - # There's no easy way in a macro to tell if you're using bzlmod. We can't - # depend on Bazel version number because `--noenable_bzlmod` may have been - # used. Instead, try and stringify a label we know doesn't exist. When - # bzlmod is in play, we'll get `[unknown repo` in the value. When it is not - # we get the label as we expect it to be. - return str(_NON_EXISTENT_LABEL).startswith("@@") - def _label(label_or_string): if type(label_or_string) == "Label": return label_or_string - workspace_prefix = "@@" if _is_using_bzlmod() else "@" + workspace_prefix = "@@" if bazel_features.external_deps.is_bzlmod_enabled else "@" if type(label_or_string) == "string": # We may have a target of the form: `@bar//foo`, `//foo`, `//foo:foo`, `:foo`, `foo` @@ -179,13 +170,9 @@ def maven_bom( # `same_package_label` doesn't exist in Bazel 5, but we still support it # so we check the version here to call a non-deprecated API in recent - # Bazel versions, or the older (deprecated) API in Bazel 5. Now, normally - # we'd use Skylib's `version` but that needs `native.bazel_version` to be - # present, and that's not available to macros. Instead, see whether what - # we need is present. Pulling in `bazel_features` for this check seems like - # overkill, especially since we'd need to land a patch in it before we - # could check this feature. Doing this the Not Invented Here way for now. - if "same_package_label" in dir(_NON_EXISTENT_LABEL): + # Bazel versions, or the older (deprecated) API in Bazel 5. + feature_check_label = Label("//:doesnotexistinrulesjvmexternal") + if hasattr(feature_check_label, "same_package_label"): fragments = [l.same_package_label("%s.bom-fragment" % l.name) for l in labels] else: # TODO: Drop this branch once we drop Bazel 5 support diff --git a/repositories.bzl b/repositories.bzl index 4aae636eb..a70725a1c 100644 --- a/repositories.bzl +++ b/repositories.bzl @@ -57,6 +57,14 @@ def rules_jvm_external_deps( sha256 = "26d4021f6898e23b82ef953078389dd49ac2b5618ac564ade4ef87cced147b38", ) + maybe( + http_archive, + name = "bazel_features", + sha256 = "bdc12fcbe6076180d835c9dd5b3685d509966191760a0eb10b276025fcb76158", + strip_prefix = "bazel_features-1.17.0", + url = "https://github.com/bazel-contrib/bazel_features/releases/download/v1.17.0/bazel_features-v1.17.0.tar.gz", + ) + maven_install( name = "rules_jvm_external_deps", artifacts = [ diff --git a/setup.bzl b/setup.bzl index 6996148e7..8942c58ce 100644 --- a/setup.bzl +++ b/setup.bzl @@ -1,3 +1,4 @@ +load("@bazel_features//:deps.bzl", "bazel_features_deps") load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") load("@rules_java//java:repositories.bzl", "rules_java_dependencies", "rules_java_toolchains") load("@rules_jvm_external_deps//:defs.bzl", "pinned_maven_install") @@ -5,6 +6,8 @@ load("@rules_jvm_external_deps//:defs.bzl", "pinned_maven_install") def rules_jvm_external_setup(): bazel_skylib_workspace() + bazel_features_deps() + # When using bazel 5, we have undefined toolchains from rules_js. This should be fine to skip, since we only need # it for the `JavaInfo` definition. major_version = native.bazel_version.partition(".")[0]