Skip to content

Commit

Permalink
Add support for isolated go_deps usages (#1584)
Browse files Browse the repository at this point in the history
Since isolated extension usages have their own sets of tags and repos,
overrides can be allowed for such usages even in non-root modules.
These usages also have to use their own dedicated repo config file.
  • Loading branch information
fmeum committed Aug 3, 2023
1 parent a872430 commit c4757e5
Show file tree
Hide file tree
Showing 15 changed files with 123 additions and 7 deletions.
1 change: 1 addition & 0 deletions .bazelci/presubmit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ tasks:
# Specify this target explicitly to verify that Gazelle generated it correctly.
- "//pkg:pkg_test"
- "//..."
- "@test_dep//..."
macos_arm64:
platform: macos_arm64
build_targets:
Expand Down
3 changes: 3 additions & 0 deletions .bcr/presubmit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ bcr_test_module:
run_test_module:
name: Run test module
platform: ${{ platform }}
build_flags:
- --experimental_isolated_extension_usages
shell_commands:
# Regenerate the BUILD file for the test module using Gazelle.
- rm pkg/BUILD.bazel
Expand All @@ -22,3 +24,4 @@ bcr_test_module:
# Specify this target explicitly to verify that Gazelle generated it correctly.
- "//pkg:pkg_test"
- "//..."
- "@test_dep//..."
2 changes: 1 addition & 1 deletion MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ use_repo(
"org_golang_x_mod",
"org_golang_x_sync",
"org_golang_x_tools",
# Read by go_repository rules.
# Referenced by `gazelle_binary`.
"bazel_gazelle_go_repository_config",
)

Expand Down
14 changes: 10 additions & 4 deletions internal/bzlmod/go_deps.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,16 @@ the required directives to the "default_gazelle_overrides.bzl" file at \
https://github.com/bazelbuild/bazel-gazelle/tree/master/internal/bzlmod/default_gazelle_overrides.bzl.
"""

def _fail_on_non_root_overrides(module, tag_class):
def _fail_on_non_root_overrides(module_ctx, module, tag_class):
if module.is_root:
return

# Isolated module extension usages only contain tags from a single module, so we can allow
# overrides. This is a new feature in Bazel 6.3.0, earlier versions do not allow module usages
# to be isolated.
if getattr(module_ctx, "is_isolated", False):
return

if getattr(module.tags, tag_class):
fail(_FORBIDDEN_OVERRIDE_TAG.format(
tag_class = tag_class,
Expand Down Expand Up @@ -151,7 +157,7 @@ def _go_deps_impl(module_ctx):
elif check_direct_deps == "error":
outdated_direct_dep_printer = fail

_fail_on_non_root_overrides(module, "gazelle_override")
_fail_on_non_root_overrides(module_ctx, module, "gazelle_override")
for gazelle_override_tag in module.tags.gazelle_override:
if gazelle_override_tag.path in gazelle_overrides:
fail("Multiple overrides defined for Go module path \"{}\" in module \"{}\".".format(gazelle_override_tag.path, module.name))
Expand All @@ -163,7 +169,7 @@ def _go_deps_impl(module_ctx):
build_file_generation = gazelle_override_tag.build_file_generation,
)

_fail_on_non_root_overrides(module, "module_override")
_fail_on_non_root_overrides(module_ctx, module, "module_override")
for module_override_tag in module.tags.module_override:
if module_override_tag.path in module_overrides:
fail("Multiple overrides defined for Go module path \"{}\" in module \"{}\".".format(module_override_tag.path, module.name))
Expand All @@ -188,7 +194,7 @@ def _go_deps_impl(module_ctx):
for tag in module_tags_from_go_mod
]

if module.is_root:
if module.is_root or getattr(module_ctx, "is_isolated", False):
replace_map.update(go_mod_replace_map)
else:
# Register this Bazel module as providing the specified Go module. It participates
Expand Down
16 changes: 15 additions & 1 deletion internal/go_repository.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,20 @@ def _go_repository_impl(ctx):
# Run Gazelle
if gazelle_path == None:
gazelle_path = ctx.path(Label(_gazelle))

# ctx.attr.name is the canonical name of this repository, which contains a '~' if and only
# if this repository is generated by a module extension rather than an invocation in
# WORKSPACE.
if "~" in ctx.attr.name:
# TODO: In Bazel 6.3.0 and earlier, there is no way to obtain a label referencing a repo
# generated by an extension from within that extension. We thus have to manually
# construct such a label pointing to the sibling `_go_repository_config` repo created by
# the `go_deps` extension. All extension-generated repos have names of the form
# `<prefix>~<name set by the extension>`.
extension_repo_prefix = ctx.attr.name.rpartition("~")[0] + "~"
repo_config = ctx.path(Label("@@" + extension_repo_prefix + "bazel_gazelle_go_repository_config//:WORKSPACE"))
else:
repo_config = ctx.path(ctx.attr.build_config)
cmd = [
gazelle_path,
"-go_repository_mode",
Expand All @@ -290,7 +304,7 @@ def _go_repository_impl(ctx):
"-repo_root",
ctx.path(""),
"-repo_config",
ctx.path(ctx.attr.build_config),
repo_config,
]
if ctx.attr.version:
cmd.append("-go_repository_module_mode")
Expand Down
1 change: 1 addition & 0 deletions tests/bcr/.bazelignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test_dep
1 change: 1 addition & 0 deletions tests/bcr/.bazelrc
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
common --enable_bzlmod
common --experimental_isolated_extension_usages
2 changes: 1 addition & 1 deletion tests/bcr/.bazelversion
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6.2.0
6.3.1
6 changes: 6 additions & 0 deletions tests/bcr/MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ local_path_override(
path = "../..",
)

bazel_dep(name = "test_dep", version = "1.0.0")
local_path_override(
module_name = "test_dep",
path = "test_dep",
)

bazel_dep(name = "rules_go", version = "0.39.1", repo_name = "my_rules_go")

# This bazel_dep provides the Go dependency github.com/cloudflare/circl, which requires custom
Expand Down
8 changes: 8 additions & 0 deletions tests/bcr/test_dep/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
load("@rules_go//go:def.bzl", "go_test")

go_test(
name = "test",
srcs = ["test.go"],
visibility = ["//visibility:public"],
deps = ["@com_github_stretchr_testify//require"],
)
50 changes: 50 additions & 0 deletions tests/bcr/test_dep/MODULE.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
module(
name = "test_dep",
version = "1.0.0",
)

bazel_dep(name = "rules_go", version = "0.41.0")
bazel_dep(name = "gazelle", version = "0.31.0")

# An isolated extension usage does not share any tags with any other usage and results in a
# completely separate set of repos. We explicitly use different directives and patches here to
# verify that they do not interfere with those of the root test module.
go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps", isolate = True)
go_deps.module(
path = "github.com/stretchr/testify",
sum = "h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=",
version = "v1.8.0",
)
go_deps.gazelle_override(
directives = [
"gazelle:go_naming_convention import",
],
path = "github.com/stretchr/testify",
)
go_deps.module_override(
patch_strip = 1,
patches = [
"//patches:testify.patch",
],
path = "github.com/stretchr/testify",
)

go_deps.module(
indirect = True,
path = "gopkg.in/yaml.v3",
sum = "h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=",
version = "v3.0.1",
)
go_deps.gazelle_override(
path = "gopkg.in/yaml.v3",
directives = [
"gazelle:go_naming_convention import",
],
)
go_deps.module(
indirect = True,
path = "github.com/davecgh/go-spew",
sum = "h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=",
version = "v1.1.1",
)
use_repo(go_deps, "com_github_stretchr_testify")
Empty file added tests/bcr/test_dep/WORKSPACE
Empty file.
Empty file.
13 changes: 13 additions & 0 deletions tests/bcr/test_dep/patches/testify.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
diff --git a/require/require.go b/require/require.go
index a6e1b7c..bc21879 100644
--- a/require/require.go
+++ b/require/require.go
@@ -12,6 +12,8 @@ import (
time "time"
)

+const Hello = "not_hello"
+
// Condition uses a Comparison to assert a complex condition.
func Condition(t TestingT, comp assert.Comparison, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
13 changes: 13 additions & 0 deletions tests/bcr/test_dep/test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package main

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestPatch(t *testing.T) {
// A patch is used to add this constant with a value that differs from that patched into the
// root module's version of this dep.
require.Equal(t, "not_hello", require.Hello)
}

0 comments on commit c4757e5

Please sign in to comment.