Skip to content

Commit

Permalink
Add package metadata to go_repositorys (#1852)
Browse files Browse the repository at this point in the history
**What type of PR is this?**

Feature

**What package or component does this PR mostly affect?**

go_repository

**What does this PR do? Why is it needed?**

All targets in a `go_repository` with generated build files are tagged
with a `package_info` automatically created by the repo rule.

This PR does not add any license information yet.

**Which issues(s) does this PR fix?**

Work towards #1314 

**Other notes for review**
  • Loading branch information
fmeum authored Aug 20, 2024
1 parent 4f4a7e1 commit d0a54d3
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 0 deletions.
1 change: 1 addition & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ bazel_dep(name = "bazel_features", version = "1.9.1")
bazel_dep(name = "bazel_skylib", version = "1.5.0")
bazel_dep(name = "protobuf", version = "3.19.6", repo_name = "com_google_protobuf")
bazel_dep(name = "rules_go", version = "0.47.0", repo_name = "io_bazel_rules_go")
bazel_dep(name = "rules_license", version = "0.0.8")
bazel_dep(name = "rules_proto", version = "4.0.0")

go_sdk = use_extension("@io_bazel_rules_go//go:extensions.bzl", "go_sdk")
Expand Down
10 changes: 10 additions & 0 deletions deps.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,16 @@ def gazelle_dependencies(
sha256 = "74d544d96f4a5bb630d465ca8bbcfe231e3594e5aae57e1edbf17a6eb3ca2506",
)

_maybe(
http_archive,
name = "rules_license",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/rules_license/releases/download/0.0.8/rules_license-0.0.8.tar.gz",
"https://github.com/bazelbuild/rules_license/releases/download/0.0.8/rules_license-0.0.8.tar.gz",
],
sha256 = "241b06f3097fd186ff468832150d6cc142247dc42a32aaefb56d0099895fd229",
)

if go_sdk:
go_repository_cache(
name = "bazel_gazelle_go_repository_cache",
Expand Down
44 changes: 44 additions & 0 deletions internal/go_repository.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,50 @@ def _go_repository_impl(ctx):
# Apply patches if necessary.
patch(ctx)

if generate:
# Do not override a REPO.bazel patched in by users. This also provides a
# way for users to opt out of Gazelle-generated package_info.
repo_file = ctx.path("REPO.bazel")
if not repo_file.exists:
ctx.file("REPO.bazel", """\
repo(default_package_metadata = ["//:gazelle_generated_package_info"])
""")

# Modify the top-level build file after patches have been applied as the
# patches may otherwise conflict with our generated content.
build_file = ctx.path(build_file_name)
if build_file.exists:
build_file_content = ctx.read(build_file)
else:
build_file_content = ""
build_file_content += _generate_package_info(
importpath = ctx.attr.importpath,
version = ctx.attr.version,
)
ctx.file(build_file_name, build_file_content)

def _generate_package_info(*, importpath, version):
package_name = importpath

# TODO: Consider adding support for custom remotes.
package_url = "https://" + importpath if version else None
package_version = version.removeprefix("v") if version else None
return """
load("@rules_license//rules:package_info.bzl", "package_info")
package_info(
name = "gazelle_generated_package_info",
package_name = {package_name},
package_url = {package_url},
package_version = {package_version},
visibility = ["//:__subpackages__"],
)
""".format(
package_name = repr(package_name),
package_url = repr(package_url),
package_version = repr(package_version),
)

go_repository = repository_rule(
implementation = _go_repository_impl,
doc = _DOC,
Expand Down
5 changes: 5 additions & 0 deletions tests/bcr/go_mod/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
load("@gazelle//:def.bzl", "gazelle", "gazelle_test")
load(":tests.bzl", "starlark_tests")

# gazelle:go_naming_convention import
# gazelle:go_naming_convention_external import
Expand All @@ -8,3 +9,7 @@ gazelle_test(
name = "gazelle_test",
workspace = "//:BUILD.bazel",
)

starlark_tests(
name = "starlark_tests",
)
3 changes: 3 additions & 0 deletions tests/bcr/go_mod/MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@ local_path_override(
path = "test_dep",
)

bazel_dep(name = "bazel_features", version = "1.14.0")
bazel_dep(name = "protobuf", version = "23.1", repo_name = "my_protobuf")
bazel_dep(name = "rules_go", version = "0.42.0", repo_name = "my_rules_go")
bazel_dep(name = "rules_license", version = "0.0.8")
bazel_dep(name = "rules_proto", version = "6.0.0-rc2", repo_name = "my_rules_proto")
bazel_dep(name = "rules_testing", version = "0.6.0")

go_sdk = use_extension("@my_rules_go//go:extensions.bzl", "go_sdk")

Expand Down
64 changes: 64 additions & 0 deletions tests/bcr/go_mod/tests.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
load("@bazel_features//:features.bzl", "bazel_features")
load("@rules_license//rules:providers.bzl", "PackageInfo")
load("@rules_testing//lib:analysis_test.bzl", "analysis_test", "test_suite")
load("@rules_testing//lib:truth.bzl", "subjects")

def _test_package_info(name):
analysis_test(
name = name,
impl = _test_package_info_impl,
target = "@com_github_fmeum_dep_on_gazelle//:go_default_library",
extra_target_under_test_aspects = [
_package_info_aspect,
],
provider_subject_factories = [_PackageInfoSubjectFactory],
)

def _test_package_info_impl(env, target):
# The package_info functionality requires REPO.bazel support, which is only
# available in Bazel 7 and higher. Use this unrelated feature launched in
# Bazel 7 as a hacky signal to skip the test if the feature is not
# available.
if not bazel_features.proto.starlark_proto_info:
return
env.expect.that_target(target).has_provider(PackageInfo)
subject = env.expect.that_target(target).provider(PackageInfo)
subject.package_name().equals("github.com/fmeum/dep_on_gazelle")
subject.package_version().equals("1.0.0")
subject.package_url().equals("https://github.com/fmeum/dep_on_gazelle")

def _package_info_aspect_impl(_, ctx):
if hasattr(ctx.rule.attr, "applicable_licenses"):
attr = ctx.rule.attr.applicable_licenses
elif hasattr(ctx.rule.attr, "package_metadata"):
attr = ctx.rule.attr.package_metadata
if attr and PackageInfo in attr[0]:
return [attr[0][PackageInfo]]
return []

_package_info_aspect = aspect(
implementation = _package_info_aspect_impl,
doc = "Forwards metadata annotations on the target via the PackageInfo provider.",
)

_PackageInfoSubjectFactory = struct(
type = PackageInfo,
name = "PackageInfo",
factory = lambda actual, *, meta: subjects.struct(
actual,
meta = meta,
attrs = {
"package_name": subjects.str,
"package_version": subjects.str,
"package_url": subjects.str,
},
),
)

def starlark_tests(name):
test_suite(
name = name,
tests = [
_test_package_info,
],
)

0 comments on commit d0a54d3

Please sign in to comment.