Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add package metadata to go_repositorys #1852

Merged
merged 6 commits into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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")
fmeum marked this conversation as resolved.
Show resolved Hide resolved
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,
fmeum marked this conversation as resolved.
Show resolved Hide resolved
)
ctx.file(build_file_name, build_file_content)
fmeum marked this conversation as resolved.
Show resolved Hide resolved

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")
fmeum marked this conversation as resolved.
Show resolved Hide resolved

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,
],
)