Skip to content

Commit

Permalink
bzlmod: Add go_deps.from_file
Browse files Browse the repository at this point in the history
With go_deps.from_file, dependencies can be parsed from a go.mod/go.sum
pair directly by the go_deps module extension. Users only have to
declare visibility for their *direct* dependencies in their
MODULE.bazel.
  • Loading branch information
fmeum committed Jul 15, 2022
1 parent ca1bf80 commit 7a5f4eb
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 209 deletions.
207 changes: 1 addition & 206 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -22,212 +22,7 @@ use_repo(
)

go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
go_deps.module(
path = "honnef.co/go/tools",
sum = "h1:/hemPrYIhOhy8zYrNj+069zDB68us2sMGsfkFJO0iZs=",
version = "v0.0.0-20190523083050-ea95bdfd59fc",
)
go_deps.module(
path = "github.com/bazelbuild/buildtools",
sum = "h1:ox8T5nCkvLflRgKZ6uzzdvLDN3gbNZBgLBqA5Xgn7QA=",
version = "v0.0.0-20220323134444-a9f46b2bb3de",
build_naming_convention = "go_default_library",
)
go_deps.module(
path = "github.com/bazelbuild/rules_go",
sum = "h1:8/MDe6zCE7nYKXhlbamM1izUgJjw2ce7M5kd4QKF/3Y=",
version = "v0.31.0",
)
go_deps.module(
path = "github.com/bmatcuk/doublestar/v4",
sum = "h1:X0krlUVAVmtr2cRoTqR8aDMrDqnB36ht8wpWTiQ3jsA=",
version = "v4.0.2",
)
go_deps.module(
path = "github.com/BurntSushi/toml",
sum = "h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=",
version = "v0.3.1",
)
go_deps.module(
path = "github.com/census-instrumentation/opencensus-proto",
sum = "h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=",
version = "v0.2.1",
)
go_deps.module(
path = "github.com/chzyer/logex",
sum = "h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=",
version = "v1.1.10",
)
go_deps.module(
path = "github.com/chzyer/readline",
sum = "h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=",
version = "v0.0.0-20180603132655-2972be24d48e",
)
go_deps.module(
path = "github.com/chzyer/test",
sum = "h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=",
version = "v0.0.0-20180213035817-a1ea475d72b1",
)
go_deps.module(
path = "github.com/client9/misspell",
sum = "h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=",
version = "v0.3.4",
)
go_deps.module(
path = "github.com/davecgh/go-spew",
sum = "h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=",
version = "v1.1.1",
)
go_deps.module(
path = "github.com/envoyproxy/go-control-plane",
sum = "h1:4cmBvAEBNJaGARUEs3/suWRyfyBfhf7I60WBZq+bv2w=",
version = "v0.9.1-0.20191026205805-5f8ba28d4473",
)
go_deps.module(
path = "github.com/envoyproxy/protoc-gen-validate",
sum = "h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=",
version = "v0.1.0",
)
go_deps.module(
path = "github.com/fsnotify/fsnotify",
sum = "h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=",
version = "v1.5.1",
)
go_deps.module(
path = "github.com/golang/glog",
sum = "h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=",
version = "v0.0.0-20160126235308-23def4e6c14b",
)
go_deps.module(
path = "github.com/golang/mock",
sum = "h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8=",
version = "v1.1.1",
)
go_deps.module(
path = "github.com/golang/protobuf",
sum = "h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=",
version = "v1.4.3",
)
go_deps.module(
path = "github.com/google/go-cmp",
sum = "h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=",
version = "v0.5.7",
)
go_deps.module(
path = "github.com/pelletier/go-toml",
sum = "h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM=",
version = "v1.9.4",
)
go_deps.module(
path = "github.com/pmezard/go-difflib",
sum = "h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=",
version = "v1.0.0",
)
go_deps.module(
path = "github.com/prometheus/client_model",
sum = "h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=",
version = "v0.0.0-20190812154241-14fe0d1b01d4",
)
go_deps.module(
path = "github.com/yuin/goldmark",
sum = "h1:OtISOGfH6sOWa1/qXqqAiOIAO6Z5J3AEAE18WAq6BiQ=",
version = "v1.4.0",
)
go_deps.module(
path = "cloud.google.com/go",
sum = "h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ=",
version = "v0.26.0",
)
go_deps.module(
path = "gopkg.in/check.v1",
sum = "h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=",
version = "v0.0.0-20161208181325-20d25e280405",
)
go_deps.module(
path = "gopkg.in/yaml.v2",
sum = "h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=",
version = "v2.2.2",
)
go_deps.module(
path = "go.starlark.net",
sum = "h1:xwwDQW5We85NaTk2APgoN9202w/l0DVGp+GZMfsrh7s=",
version = "v0.0.0-20210223155950-e043a3d3c984",
)
go_deps.module(
path = "google.golang.org/appengine",
sum = "h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=",
version = "v1.4.0",
)
go_deps.module(
path = "google.golang.org/genproto",
sum = "h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=",
version = "v0.0.0-20200526211855-cb27e3aa2013",
)
go_deps.module(
path = "google.golang.org/grpc",
sum = "h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg=",
version = "v1.27.0",
)
go_deps.module(
path = "google.golang.org/protobuf",
sum = "h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=",
version = "v1.25.0",
)
go_deps.module(
path = "golang.org/x/crypto",
sum = "h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=",
version = "v0.0.0-20191011191535-87dc89f01550",
)
go_deps.module(
path = "golang.org/x/exp",
sum = "h1:c2HOrn5iMezYjSlGPncknSEr/8x5LELb/ilJbXi9DEA=",
version = "v0.0.0-20190121172915-509febef88a4",
)
go_deps.module(
path = "golang.org/x/lint",
sum = "h1:XQyxROzUlZH+WIQwySDgnISgOivlhjIEwaQaJEJrrN0=",
version = "v0.0.0-20190313153728-d0100b6bd8b3",
)
go_deps.module(
path = "golang.org/x/mod",
sum = "h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o=",
version = "v0.6.0-dev.0.20220106191415-9b9b3d81d5e3",
)
go_deps.module(
path = "golang.org/x/net",
sum = "h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI=",
version = "v0.0.0-20210805182204-aaa1db679c0d",
)
go_deps.module(
path = "golang.org/x/oauth2",
sum = "h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=",
version = "v0.0.0-20180821212333-d2e6202438be",
)
go_deps.module(
path = "golang.org/x/sync",
sum = "h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=",
version = "v0.0.0-20210220032951-036812b2e83c",
)
go_deps.module(
path = "golang.org/x/sys",
sum = "h1:OH54vjqzRWmbJ62fjuhxy7AxFFgoHN0/DPc/UrL8cAs=",
version = "v0.0.0-20220319134239-a9b59b0215f8",
)
go_deps.module(
path = "golang.org/x/text",
sum = "h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=",
version = "v0.3.6",
)
go_deps.module(
path = "golang.org/x/tools",
sum = "h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20=",
version = "v0.1.10",
)
go_deps.module(
path = "golang.org/x/xerrors",
sum = "h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=",
version = "v0.0.0-20200804184101-5ec99f83aff1",
)
go_deps.from_file(go_mod = "//:go.mod")
use_repo(
go_deps,
"com_github_bazelbuild_buildtools",
Expand Down
22 changes: 19 additions & 3 deletions internal/bzlmod/go_deps.bzl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
load("//internal:go_repository.bzl", "go_repository")
load(":go_mod.bzl", "deps_from_go_mod")
load(":semver.bzl", "semver")

def _repo_name(importpath):
Expand Down Expand Up @@ -47,6 +48,10 @@ def _go_deps_impl(module_ctx):
elif check_direct_deps == "error":
outdated_direct_dep_printer = fail

additional_module_tags = []
for from_file_tag in module.tags.from_file:
additional_module_tags += deps_from_go_mod(module_ctx, from_file_tag.go_mod)

# Parse the go_dep.module tags of all transitive dependencies and apply
# Minimum Version Selection to resolve importpaths to Go module versions
# and sums.
Expand All @@ -59,14 +64,19 @@ def _go_deps_impl(module_ctx):
# transitive dependencies have also been declared - we may end up
# resolving them to higher versions, but only compatible ones.
paths = {}
for module_tag in module.tags.module:
for module_tag in module.tags.module + additional_module_tags:
if module_tag.path in paths:
fail("Duplicate Go module path '{}' in module '{}'".format(module_tag.path, module.name))
paths[module_tag.path] = None
raw_version = module_tag.version
if raw_version.startswith("v"):
raw_version = raw_version[1:]
if getattr(module, "is_root", False):

# For modules imported from a go.sum, we know which ones are direct
# dependencies and can thus only report implicit version upgrades
# for direct dependencies. For manually specified go_deps.module
# tags, we always report version upgrades.
if getattr(module, "is_root", False) and getattr(module_tag, "direct", True):
root_versions[module_tag.path] = raw_version
version = semver.to_comparable(raw_version)
if module_tag.path not in module_resolutions or version > module_resolutions[module_tag.path].version:
Expand All @@ -78,7 +88,6 @@ def _go_deps_impl(module_ctx):
sum = module_tag.sum,
build_naming_convention = module_tag.build_naming_convention,
)
is_root_module = False

for path, root_version in root_versions.items():
if semver.to_comparable(root_version) < module_resolutions[path].version:
Expand Down Expand Up @@ -125,6 +134,12 @@ _config_tag = tag_class(
},
)

_from_file_tag = tag_class(
attrs = {
"go_mod": attr.label(mandatory = True),
}
)

_module_tag = tag_class(
attrs = {
"path": attr.string(mandatory = True),
Expand All @@ -138,6 +153,7 @@ go_deps = module_extension(
_go_deps_impl,
tag_classes = {
"config": _config_tag,
"from_file": _from_file_tag,
"module": _module_tag,
},
)
42 changes: 42 additions & 0 deletions internal/bzlmod/go_mod.bzl
Original file line number Diff line number Diff line change
@@ -1,3 +1,45 @@
def deps_from_go_mod(module_ctx, go_mod_label):
go_mod_path = module_ctx.path(go_mod_label)
go_mod_content = module_ctx.read(go_mod_path)
go_mod = parse_go_mod(go_mod_content, go_mod_path)

if go_mod.go[0] != 1 or go_mod.go[1] < 17:
# go.mod files only include entries for all transitive dependencies as
# of Go 1.17.
fail("go_deps.from_file requires a go.mod file generated by Go 1.17 or later. Fix {} with 'go mod tidy -go=1.17'.".format(go_mod_label))

# go.sum may not exist if go.mod does not contain any require directives,
# so we only resolve it conditionally.
if not go_mod.require:
return []

# We go through a Label so that the module extension is restarted if go.sum
# changes. We have to use a canonical label as we may not have visibility
# into the module that provides the go.sum.
go_sum_label = Label("@{}//{}:{}".format(
go_mod_label.workspace_name,
go_mod_label.package,
"go.sum",
))
go_sum_path = module_ctx.path(go_sum_label)
go_sum_content = module_ctx.read(go_sum_path)
go_sum = parse_go_sum(go_sum_content)

deps = []
for require in go_mod.require:
entry = (require.path, require.version)
if entry not in go_sum:
fail("No sum for {}@{} found in {}", require.path, require.version, go_sum_path)
deps.append(struct(
path = require.path,
version = require.version,
sum = go_sum[entry],
direct = require.direct,
build_naming_convention = "import_alias",
))

return deps

def parse_go_mod(content, path):
# See https://go.dev/ref/mod#go-mod-file.

Expand Down
5 changes: 5 additions & 0 deletions tests/bcr/MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ go_deps.module(
sum = "h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=",
version = "v3.0.1",
)
go_deps.module(
path = "github.com/davecgh/go-spew",
sum = "h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=",
version = "v1.1.1",
)
use_repo(
go_deps,
"com_github_pelletier_go_toml",
Expand Down

0 comments on commit 7a5f4eb

Please sign in to comment.