diff --git a/BUILD b/BUILD index 7c907e057..0378f054b 100644 --- a/BUILD +++ b/BUILD @@ -1,4 +1,6 @@ load("@bazel_skylib//:bzl_library.bzl", "bzl_library") +load("@package_metadata//licenses/rules:license.bzl", "license") +load("@package_metadata//rules:package_metadata.bzl", "package_metadata") exports_files([ "defs.bzl", @@ -8,12 +10,31 @@ exports_files([ licenses(["notice"]) # Apache 2.0 +package_metadata( + name = "package_metadata", + attributes = [ + ":license", + ], + purl = "pkg:bazel/{}@{}".format( + module_name(), + module_version(), + ) if module_version() else "pkg:bazel/{}".format(module_name()), + visibility = ["//visibility:public"], +) + +license( + name = "license", + kind = "@package_metadata//licenses/spdx:Apache-2.0", + text = "LICENSE", +) + bzl_library( name = "implementation", srcs = [ ":defs.bzl", ":specs.bzl", "@bazel_features//:bzl_files", + "@package_metadata//:srcs", "@rules_license//:docs_deps", ], visibility = [ diff --git a/MODULE.bazel b/MODULE.bazel index 299ee0cc8..9f54d8403 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -16,6 +16,10 @@ bazel_dep( name = "bazel_skylib", version = "1.7.1", ) +bazel_dep( + name = "package_metadata", + version = "0.0.3", +) bazel_dep( name = "platforms", version = "0.0.10", diff --git a/REPO.bazel b/REPO.bazel new file mode 100644 index 000000000..bbbb67313 --- /dev/null +++ b/REPO.bazel @@ -0,0 +1,7 @@ +"""File declaring metadata applying to all packages and targets in the Bazel module.""" + +repo( + default_package_metadata = [ + "//:package_metadata", + ], +) diff --git a/private/dependency_tree_parser.bzl b/private/dependency_tree_parser.bzl index e1660c601..9d5672155 100644 --- a/private/dependency_tree_parser.bzl +++ b/private/dependency_tree_parser.bzl @@ -29,7 +29,8 @@ load( "strip_packaging_and_classifier_and_version", "to_repository_name", ) -load("//private/lib:coordinates.bzl", "unpack_coordinates") +load("//private/lib:coordinates.bzl", "unpack_coordinates", "to_purl") +load("//private/lib:urls.bzl", "scheme_and_host") def _genrule_copy_artifact_from_http_file(artifact, visibilities): http_file_repository = to_repository_name(artifact["coordinates"]) @@ -244,12 +245,26 @@ copy_file( target_import_string.append("\tmaven_coordinates = \"%s\"," % coordinates) if len(artifact["urls"]): target_import_string.append("\tmaven_url = \"%s\"," % maven_url) + + package_metadata_name = "%s_package_metadata" % target_label + target_import_string.append("\tapplicable_licenses = [\":{}\"],".format(package_metadata_name)) + to_return.append(""" +package_metadata( + name = {package_metadata_name}, + purl = {purl}, + visibility = ["//visibility:public"], +) +""".format( + package_metadata_name = repr(package_metadata_name), + purl = repr(to_purl(coordinates, scheme_and_host(maven_url))), + )) else: unpacked = unpack_coordinates(coordinates) url = maven_url if len(artifact["urls"]) else None package_info_name = "%s_package_info" % target_label - target_import_string.append("\tapplicable_licenses = [\":%s\"]," % package_info_name) + package_metadata_name = "%s_package_metadata" % target_label + target_import_string.append("\tapplicable_licenses = [\n\t\t\":{}\",\n\t\t\":{}\",\n\t],".format(package_info_name, package_metadata_name)) to_return.append(""" package_info( name = {name}, @@ -257,9 +272,17 @@ package_info( package_url = {url}, package_version = {version}, ) + +package_metadata( + name = {package_metadata_name}, + purl = {purl}, + visibility = ["//visibility:public"], +) """.format( coordinates = repr(coordinates), name = repr(package_info_name), + package_metadata_name = repr(package_metadata_name), + purl = repr(to_purl(coordinates, scheme_and_host(url))), url = repr(url), version = repr(unpacked.version), )) diff --git a/private/rules/coursier.bzl b/private/rules/coursier.bzl index 09f39ed50..b40329287 100644 --- a/private/rules/coursier.bzl +++ b/private/rules/coursier.bzl @@ -38,6 +38,7 @@ _BUILD = """ load("@bazel_skylib//:bzl_library.bzl", "bzl_library") load("@bazel_skylib//rules:copy_file.bzl", "copy_file") +load("@package_metadata//rules:package_metadata.bzl", "package_metadata") load("@rules_license//rules:package_info.bzl", "package_info") load("@rules_java//java:defs.bzl", "java_binary", "java_library", "java_plugin") load("@rules_jvm_external//private/rules:pin_dependencies.bzl", "pin_dependencies") diff --git a/repositories.bzl b/repositories.bzl index cf4eb60c3..0e72eed69 100644 --- a/repositories.bzl +++ b/repositories.bzl @@ -93,6 +93,17 @@ def rules_jvm_external_deps( patch_args = ["-p1"], ) + maybe( + http_archive, + name = "package_metadata", + urls = [ + "https://mirror.bazel.build/github.com/bazel-contrib/supply-chain/releases/download/v0.0.3/supply-chain-v0.0.3.tar.gz", + "https://github.com/bazel-contrib/supply-chain/releases/download/v0.0.3/supply-chain-v0.0.3.tar.gz", + ], + sha256 = "0e89367f1cb6d93a5a1afea4b55b11ea6b28f63f653b47154153677ca7d4afea", + strip_prefix = "supply-chain-0.0.3/metadata", + ) + maybe( http_archive, name = "rules_license", diff --git a/tests/unit/jvm_import/jvm_import_test.bzl b/tests/unit/jvm_import/jvm_import_test.bzl index ccb7c14df..75a6293e9 100644 --- a/tests/unit/jvm_import/jvm_import_test.bzl +++ b/tests/unit/jvm_import/jvm_import_test.bzl @@ -17,6 +17,7 @@ This module contains a test suite for testing jvm_import """ load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") +load("@package_metadata//providers:package_metadata_info.bzl", "PackageMetadataInfo") load("@rules_license//rules:gather_metadata.bzl", "gather_metadata_info") load("@rules_license//rules:providers.bzl", "PackageInfo") load("@rules_license//rules_gathering:gathering_providers.bzl", "TransitiveMetadataInfo") @@ -28,6 +29,13 @@ TagsInfo = provider( }, ) +PackageMetadataInfoCollectionInfo = provider( + doc = "Provider to propagate jvm_import's applicable_licenses for testing purposes", + fields = { + "info": "A PackageMetadataInfo provider from jvm_import's applicable_licenses for testing purposes", + }, +) + def _tags_propagator_impl(target, ctx): tags = getattr(ctx.rule.attr, "tags") return TagsInfo(tags = tags) @@ -38,6 +46,30 @@ tags_propagator = aspect( implementation = _tags_propagator_impl, ) +def _package_metadata_info_propagator_impl(target, ctx): + direct = getattr(ctx.rule.attr, "package_metadata", None) + if not direct: + direct = getattr(ctx.rule.attr, "applicable_licenses") + + infos = [t[PackageMetadataInfo] for t in direct if PackageMetadataInfo in t] + for t in direct: + if PackageMetadataInfo not in t: + continue + + return [ + PackageMetadataInfoCollectionInfo( + info = t[PackageMetadataInfo], + ), + ] + + return [] + +package_metadata_info_propagator = aspect( + doc = "Aspect that propagates applicable_licenses to help with testing jvm_import", + attr_aspects = [], + implementation = _package_metadata_info_propagator_impl, +) + def _does_jvm_import_have_tags_impl(ctx): env = analysistest.begin(ctx) @@ -62,6 +94,26 @@ does_jvm_import_have_tags_test = analysistest.make( }, ) +def _does_jvm_import_have_applicable_licenses_impl(ctx): + env = analysistest.begin(ctx) + + asserts.true(env, PackageMetadataInfoCollectionInfo in ctx.attr.src) + info = ctx.attr.src[PackageMetadataInfoCollectionInfo] + asserts.true(env, info.info) + + return analysistest.end(env) + +does_jvm_import_have_applicable_licenses_test = analysistest.make( + _does_jvm_import_have_applicable_licenses_impl, + attrs = { + "src": attr.label( + doc = "Target to traverse for applicable_licenses", + aspects = [package_metadata_info_propagator], + mandatory = True, + ), + }, +) + def _does_jvm_import_export_a_package_provider_impl(ctx): env = analysistest.begin(ctx) @@ -116,6 +168,11 @@ def jvm_import_test_suite(name): target_under_test = "@jvm_import_test//:com_google_code_findbugs_jsr305_3_0_2", src = "@jvm_import_test//:com_google_code_findbugs_jsr305_3_0_2", ) + does_jvm_import_have_applicable_licenses_test( + name = "does_jvm_import_have_applicable_licenses_test", + target_under_test = "@jvm_import_test//:com_google_code_findbugs_jsr305_3_0_2", + src = "@jvm_import_test//:com_google_code_findbugs_jsr305_3_0_2", + ) does_jvm_import_export_a_package_provider_test( name = "does_jvm_import_export_a_package_provider", target_under_test = "@jvm_import_test//:com_google_code_findbugs_jsr305",