Skip to content

Commit 519d7cc

Browse files
authored
MODULE.bazel: load dependencies from go.work instead of go.mod (#2320)
**What type of PR is this?** > Bug fix **What package or component does this PR mostly affect?** > all **What does this PR do? Why is it needed?** This lets us drop the `replace` from go.mod, which is blocking `go install` in #2319. And it more accurately represents how Gazelle is managing dependencies: we'll need to do this anyway if `v2/go.mod` requires something that `go.mod` does not. This requires a substantial change in `go_deps`. I've renamed the `bazel_deps` list to `bazel_go_modules` to reflect the fact that with `go.work`, Bazel modules and Go modules are not one-to-one: a Bazel module like `gazelle` may contain multiple Go modules. We should not generate `go_repository` definitions for these, nor should we warn about selected version differences. Unfortunately, we can't ignore `go.work` files outside the main module. Gazelle's `deps` labels refer to `//v2/...` packages within the same module; clients cannot have a different view of the module boundaries. This change means that we don't need `ignore_local_replaced_modules`, so reverting that in #2321 since it's not released yet. **Which issues(s) does this PR fix?** Fixes #2319 **Other notes for review**
1 parent 7c54844 commit 519d7cc

6 files changed

Lines changed: 42 additions & 25 deletions

File tree

MODULE.bazel

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,7 @@ use_repo(
3131
)
3232

3333
go_deps = use_extension("//:extensions.bzl", "go_deps")
34-
go_deps.from_file(
35-
go_mod = "//:go.mod",
36-
ignore_local_replaced_modules = True,
37-
)
34+
go_deps.from_file(go_work = "//:go.work")
3835
use_repo(
3936
go_deps,
4037
"com_github_bazelbuild_buildtools",

go.mod

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,3 @@ require (
2929
google.golang.org/grpc v1.67.3 // indirect
3030
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 // indirect
3131
)
32-
33-
replace github.com/bazel-contrib/bazel-gazelle/v2 => ./v2

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
github.com/bazel-contrib/bazel-gazelle/v2 v2.0.0-1/go.mod h1:B76PjnaM2KyUG8ypV/ePHHDmGbyUNZ2PCEdEQIJISQM=
2+
github.com/bazel-contrib/bazel-gazelle/v2 v2.0.0-1 h1:Aney60tyjQn3ON+KPFQhEZ7saU1EtOhlCrGTKGkxiEI=
13
github.com/bazelbuild/buildtools v0.0.0-20250930140053-2eb4fccefb52 h1:njQAmjTv/YHRm/0Lfv9DXHFZ4MdT2IA/RKHTnqZkgDw=
24
github.com/bazelbuild/buildtools v0.0.0-20250930140053-2eb4fccefb52/go.mod h1:PLNUetjLa77TCCziPsz0EI8a6CUxgC+1jgmWv0H25tg=
35
github.com/bazelbuild/rules_go v0.53.0 h1:u160DT+RRb+Xb2aSO4piN8xhs4aZvWz2UDXCq48F4ao=

go.work.sum

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
github.com/bazel-contrib/bazel-gazelle/v2 v2.0.0-1/go.mod h1:B76PjnaM2KyUG8ypV/ePHHDmGbyUNZ2PCEdEQIJISQM=
12
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=

internal/bzlmod/go_deps.bzl

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ def _go_deps_impl(module_ctx):
341341
module_resolutions = {}
342342
sums = {}
343343
replace_map = {}
344-
bazel_deps = {}
344+
bazel_go_modules = {}
345345
all_tools = []
346346

347347
gazelle_default_attributes = _process_gazelle_default_attributes(module_ctx)
@@ -463,20 +463,36 @@ def _go_deps_impl(module_ctx):
463463
for mod_path, mod in go_mod_replace_map.items():
464464
if not mod_path in replace_map:
465465
replace_map[mod_path] = mod
466+
467+
# Register this Go module as being provided by the main Bazel
468+
# module. It does not have a version, and it overrides any
469+
# non-Bazel Go module with the same path. Note that a single
470+
# Bazel module may contain multiple Go modules via go.work.
471+
bazel_go_modules[module_path] = struct(
472+
module_name = module.name,
473+
repo_name = "@" + module.name,
474+
version = _HIGHEST_VERSION_SENTINEL,
475+
raw_version = "",
476+
is_root = True,
477+
go_mod_dir = from_file_tag.go_mod.package,
478+
)
466479
else:
467-
# Register this Bazel module as providing the specified Go module. It participates
468-
# in version resolution using its registry version, which uses a relaxed variant of
469-
# semver that can however still be compared to strict semvers.
470-
# An empty version string signals an override, which is assumed to be newer than any
471-
# other version.
480+
# Register this Go module as being provided by the specific
481+
# Bazel module. It participates in version resolution using its
482+
# registry version, which uses a relaxed variant of semver that
483+
# can however still be compared to strict semvers. An empty
484+
# version string signals an override, which is assumed to be
485+
# newer than any other version.
472486
raw_version = _canonicalize_raw_version(module.version)
473487
version = semver.to_comparable(raw_version, relaxed = True) if raw_version else _HIGHEST_VERSION_SENTINEL
474-
if module_path not in bazel_deps or version > bazel_deps[module_path].version:
475-
bazel_deps[module_path] = struct(
488+
if module_path not in bazel_go_modules or version > bazel_go_modules[module_path].version:
489+
bazel_go_modules[module_path] = struct(
476490
module_name = module.name,
477491
repo_name = "@" + from_file_tag.go_mod.repo_name,
478492
version = version,
479493
raw_version = raw_version,
494+
is_root = False,
495+
go_mod_dir = from_file_tag.go_mod.package,
480496
)
481497

482498
# Load all sums from transitively resolved `go.sum` files that have modules.
@@ -582,25 +598,26 @@ def _go_deps_impl(module_ctx):
582598
else:
583599
root_versions[path] = replace.version
584600

585-
for path, bazel_dep in bazel_deps.items():
601+
for path, bazel_go_module in bazel_go_modules.items():
586602
# We can't apply overrides to Bazel dependencies and thus fall back to using the Go module.
587603
if path in archive_overrides or path in gazelle_overrides or path in module_overrides or path in replace_map:
588604
# TODO: Consider adding a warning here. Users should patch the bazel_dep instead.
589605
continue
590606

591-
bazel_dep_is_older = path in module_resolutions and bazel_dep.version < module_resolutions[path].version
607+
bazel_dep_is_older = path in module_resolutions and bazel_go_module.version < module_resolutions[path].version
592608

593609
# Version mismatches between the Go module and the bazel_dep are problematic. For consistency always
594610
# prefer the bazel_dep version and report any mismatch to the user.
595611
#
596612
# The bazel_dep version can be relaxed semver (e.g. 1.2.3.bcr.1), which would always differ from valid Go
597613
# versions. We assume that the extra segments don't affect Go compatibility and thus ignore them.
598614
if (path in module_resolutions and
599-
semver.make_strict(bazel_dep.version) != module_resolutions[path].version and
600-
bazel_dep.version != _HIGHEST_VERSION_SENTINEL and
615+
not bazel_go_module.is_root and
616+
semver.make_strict(bazel_go_module.version) != module_resolutions[path].version and
617+
bazel_go_module.version != _HIGHEST_VERSION_SENTINEL and
601618
(bazel_dep_is_older or path in root_versions)):
602-
bazel_dep_name = bazel_dep.module_name
603-
bazel_dep_version = bazel_dep.raw_version
619+
bazel_dep_name = bazel_go_module.module_name
620+
bazel_dep_version = bazel_go_module.raw_version
604621
go_module_version = module_resolutions[path].raw_version
605622
if bazel_dep_is_older:
606623
remediation = [
@@ -646,9 +663,9 @@ Mismatch between versions requested for Go module {module}:
646663
go_module_version = go_module_version,
647664
), *remediation)
648665

649-
# TODO: We should update root_versions if the bazel_dep is a direct dependency of the root
666+
# TODO: We should update root_versions if the bazel_go_module is a direct dependency of the root
650667
# module. However, we currently don't have a way to determine that.
651-
module_resolutions[path] = bazel_dep
668+
module_resolutions[path] = bazel_go_module
652669

653670
recommended_updates = []
654671
for path, root_version in root_versions.items():
@@ -678,7 +695,7 @@ Mismatch between versions requested for Go module {module}:
678695
repos_processed = {}
679696
for path, module in module_resolutions.items():
680697
if hasattr(module, "module_name") or (getattr(module_ctx, "is_isolated", False) and path in _SHARED_REPOS):
681-
# Do not create a go_repository for a Go module provided by a bazel_dep or one shared with the non-isolated
698+
# Do not create a go_repository for a Go module provided by a bazel_go_module or one shared with the non-isolated
682699
# instance of go_deps.
683700
root_module_direct_deps.pop(_repo_name(path), None)
684701
root_module_direct_dev_deps.pop(_repo_name(path), None)
@@ -775,11 +792,13 @@ Mismatch between versions requested for Go module {module}:
775792
importpaths = {
776793
module.repo_name: path
777794
for path, module in module_resolutions.items()
795+
if not getattr(module, "go_mod_dir", None)
778796
},
779797
tool_targets = tool_targets,
780798
module_names = {
781799
info.repo_name: info.module_name
782-
for path, info in bazel_deps.items()
800+
for path, info in bazel_go_modules.items()
801+
if not getattr(info, "go_mod_dir", None)
783802
},
784803
build_naming_conventions = drop_nones({
785804
module.repo_name: get_directive_value(

vendor/modules.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
## workspace
2-
# github.com/bazel-contrib/bazel-gazelle/v2 v2.0.0-1 => ./v2
2+
# github.com/bazel-contrib/bazel-gazelle/v2 v2.0.0-1
33
## explicit; go 1.24.12
44
# github.com/bazelbuild/buildtools v0.0.0-20250930140053-2eb4fccefb52
55
## explicit; go 1.20

0 commit comments

Comments
 (0)