Skip to content

Commit 73c097e

Browse files
committed
Reapply "go_sdk: store SDK filenames and hashes in lockfile facts" (#4432)
This reverts commit 6d90ede. Includes the following fixes: * Adapted to the more limited facts API that actually got merged. * Prefetching of SDK hashes is now performed on a best-effort basis so that otherwise airgapped builds that provide SDK hashes do not result in failures.
1 parent 3ea65d8 commit 73c097e

File tree

5 files changed

+75
-36
lines changed

5 files changed

+75
-36
lines changed

.bazelversion

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
7.6.2rc1
1+
7.6.2

go/private/extensions.bzl

Lines changed: 58 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
load("@io_bazel_rules_go_bazel_features//:features.bzl", "bazel_features")
1616
load("//go/private:go_mod.bzl", "version_from_go_mod")
1717
load("//go/private:nogo.bzl", "DEFAULT_NOGO", "NOGO_DEFAULT_EXCLUDES", "NOGO_DEFAULT_INCLUDES", "go_register_nogo")
18-
load("//go/private:sdk.bzl", "detect_host_platform", "go_download_sdk_rule", "go_host_sdk_rule", "go_multiple_toolchains", "go_wrap_sdk_rule")
18+
load("//go/private:sdk.bzl", "detect_host_platform", "fetch_sdks_by_version", "go_download_sdk_rule", "go_host_sdk_rule", "go_multiple_toolchains", "go_wrap_sdk_rule")
1919

2020
def host_compatible_toolchain_impl(ctx):
2121
ctx.file("BUILD.bazel")
@@ -197,6 +197,10 @@ def _go_sdk_impl(ctx):
197197
first_host_compatible_toolchain = None
198198
host_detected_goos, host_detected_goarch = detect_host_platform(ctx)
199199
toolchains = []
200+
201+
sdks_by_version = getattr(ctx, "facts", None) or {}
202+
used_versions = {}
203+
200204
for module in ctx.modules:
201205
# Apply wrapped toolchains first to override specific platforms from the
202206
# default toolchain or any downloads.
@@ -261,18 +265,14 @@ def _go_sdk_impl(ctx):
261265
index = index,
262266
)
263267

264-
# Keep in sync with the other calls to `go_download_sdk_rule` above and below.
265-
go_download_sdk_rule(
268+
_download_sdk(
269+
module_ctx = ctx,
270+
sdks_by_version = sdks_by_version,
271+
used_versions = used_versions,
266272
name = name,
267273
goos = download_tag.goos,
268274
goarch = download_tag.goarch,
269-
sdks = download_tag.sdks,
270-
experiments = download_tag.experiments,
271-
patches = download_tag.patches,
272-
patch_strip = download_tag.patch_strip,
273-
urls = download_tag.urls,
274-
version = download_tag.version,
275-
strip_prefix = download_tag.strip_prefix,
275+
download_tag = download_tag,
276276
)
277277

278278
if (not download_tag.goos or download_tag.goos == host_detected_goos) and (not download_tag.goarch or download_tag.goarch == host_detected_goarch):
@@ -306,18 +306,14 @@ def _go_sdk_impl(ctx):
306306
suffix = "_{}_{}".format(goos, goarch),
307307
)
308308

309-
# Keep in sync with the other calls to `go_download_sdk_rule` above.
310-
go_download_sdk_rule(
309+
_download_sdk(
310+
module_ctx = ctx,
311+
sdks_by_version = sdks_by_version,
312+
used_versions = used_versions,
311313
name = default_name,
312314
goos = goos,
313315
goarch = goarch,
314-
sdks = download_tag.sdks,
315-
experiments = download_tag.experiments,
316-
patches = download_tag.patches,
317-
patch_strip = download_tag.patch_strip,
318-
urls = download_tag.urls,
319-
version = download_tag.version,
320-
strip_prefix = download_tag.strip_prefix,
316+
download_tag = download_tag,
321317
)
322318

323319
toolchains.append(struct(
@@ -379,7 +375,18 @@ def _go_sdk_impl(ctx):
379375
)
380376

381377
if bazel_features.external_deps.extension_metadata_has_reproducible:
382-
return ctx.extension_metadata(reproducible = True)
378+
kwargs = {
379+
"reproducible": True,
380+
}
381+
382+
# See _download_sdk below for details on these facts.
383+
if hasattr(ctx, "facts"):
384+
kwargs["facts"] = {
385+
version: sdk_info
386+
for version, sdk_info in sdks_by_version.items()
387+
if version in used_versions
388+
}
389+
return ctx.extension_metadata(**kwargs)
383390
else:
384391
return None
385392

@@ -409,6 +416,37 @@ def _left_pad_zero(index, length):
409416
fail("index must be non-negative")
410417
return ("0" * length + str(index))[-length:]
411418

419+
def _download_sdk(*, module_ctx, sdks_by_version, used_versions, name, goos, goarch, download_tag):
420+
version = download_tag.version
421+
sdks = download_tag.sdks
422+
if version and not sdks:
423+
# Avoid a download without a known digest in the SDK repo rule by fetching the SDKs filename
424+
# and digest here. When using a version of Bazel that supports module extension facts, this
425+
# info will be persisted in the lockfile, allowing for truly airgapped builds with an
426+
# up-to-date lockfile and download (formerly repository) cache.
427+
if version not in sdks_by_version:
428+
# Lazily fetch the information about all SDKs so that we avoid the download if the facts
429+
# already contain all the versions we care about.
430+
sdks_by_version.clear()
431+
sdks_by_version.update(fetch_sdks_by_version(module_ctx))
432+
if version not in sdks_by_version:
433+
fail("go_sdk: no SDKs found for version {} requested by".format(version), download_tag)
434+
used_versions[version] = True
435+
sdks = sdks_by_version[version]
436+
437+
go_download_sdk_rule(
438+
name = name,
439+
goos = goos,
440+
goarch = goarch,
441+
sdks = sdks,
442+
experiments = download_tag.experiments,
443+
patches = download_tag.patches,
444+
patch_strip = download_tag.patch_strip,
445+
urls = download_tag.urls,
446+
version = download_tag.version,
447+
strip_prefix = download_tag.strip_prefix,
448+
)
449+
412450
go_sdk_extra_kwargs = {
413451
# The choice of a host-compatible SDK is expressed in repository rule attribute values and
414452
# depends on host OS and architecture.

go/private/sdk.bzl

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -81,17 +81,7 @@ def _go_download_sdk_impl(ctx):
8181
ctx.report_progress("Finding latest Go version")
8282
else:
8383
ctx.report_progress("Finding Go SHA-256 sums")
84-
ctx.download(
85-
url = [
86-
"https://go.dev/dl/?mode=json&include=all",
87-
"https://golang.google.cn/dl/?mode=json&include=all",
88-
],
89-
output = "versions.json",
90-
)
91-
92-
data = ctx.read("versions.json")
93-
ctx.delete("versions.json")
94-
sdks_by_version = _parse_versions_json(data)
84+
sdks_by_version = fetch_sdks_by_version(ctx)
9585

9686
if not version:
9787
highest_version = None
@@ -580,6 +570,21 @@ def _parse_versions_json(data):
580570
for sdk in sdks
581571
}
582572

573+
def fetch_sdks_by_version(ctx):
574+
ctx.download(
575+
url = [
576+
"https://go.dev/dl/?mode=json&include=all",
577+
"https://golang.google.cn/dl/?mode=json&include=all",
578+
],
579+
output = "versions.json",
580+
)
581+
data = ctx.read("versions.json")
582+
583+
# module_ctx doesn't have delete, but its files are temporary anyway.
584+
if hasattr(ctx, "delete"):
585+
ctx.delete("versions.json")
586+
return _parse_versions_json(data)
587+
583588
def parse_version(version):
584589
"""Parses a version string like "1.15.5" and returns a tuple of numbers or None"""
585590
l, r = 0, 0

tests/bcr/WORKSPACE.bzlmod

Whitespace-only changes.

tests/bcr/other_module/MODULE.bazel

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,3 @@ module(name = "other_module")
33
bazel_dep(name = "rules_go", version = "")
44

55
go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
6-
7-
# Request an invalid SDK to verify that it isn't fetched since the test module registers a toolchain
8-
# that takes precedence.
9-
go_sdk.download(version = "3.0.0")

0 commit comments

Comments
 (0)