build: optimized Bazel repository and toolchain caching for CI
- Pin Rust toolchain component checksums in MODULE.bazel to enable Bazel's repo contents cache. - Opt MSVC LLVM tools, XWin sysroot, and Zig repositories into reproducible repo metadata caching. - Extend GitHub Actions cache paths to include the Bazel repository download and contents cache.
This commit is contained in:
@@ -77,7 +77,14 @@ runs:
|
|||||||
if: steps.backend.outputs.remote != 'true'
|
if: steps.backend.outputs.remote != 'true'
|
||||||
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||||
with:
|
with:
|
||||||
path: ~/.cache/omp-bazel-disk
|
# Both caches ride one archive: the action cache AND the repository
|
||||||
|
# cache (downloads + extracted repo contents at repo/contents, which
|
||||||
|
# reproducible repo rules reuse across output bases). Without the
|
||||||
|
# repo half, every hosted job re-downloaded and re-extracted the
|
||||||
|
# rust/LLVM/zig toolchains. Save sites must list the same paths.
|
||||||
|
path: |
|
||||||
|
~/.cache/omp-bazel-disk
|
||||||
|
~/.cache/omp-bazel-repo
|
||||||
key: ${{ steps.backend.outputs.cache-key }}
|
key: ${{ steps.backend.outputs.cache-key }}
|
||||||
# Order matters: exact key, same-config prefix, then any archive for
|
# Order matters: exact key, same-config prefix, then any archive for
|
||||||
# this scope+os+arch. The bare fallback is what keeps release version
|
# this scope+os+arch. The bare fallback is what keeps release version
|
||||||
@@ -130,7 +137,10 @@ runs:
|
|||||||
# generations wrote would otherwise ride along forever; drop
|
# generations wrote would otherwise ride along forever; drop
|
||||||
# anything untouched for 14 days (tar preserves mtimes across
|
# anything untouched for 14 days (tar preserves mtimes across
|
||||||
# the actions/cache round trip, so age survives restores).
|
# the actions/cache round trip, so age survives restores).
|
||||||
find "$HOME/.cache/omp-bazel-disk" -type f -mtime +14 -delete 2>/dev/null || true
|
# Covers the repo download/contents cache too — bazel's own
|
||||||
|
# contents-cache GC only runs on idle servers, which short-lived
|
||||||
|
# CI invocations never have.
|
||||||
|
find "$HOME/.cache/omp-bazel-disk" "$HOME/.cache/omp-bazel-repo" -type f -mtime +14 -delete 2>/dev/null || true
|
||||||
{
|
{
|
||||||
echo "common --config=ci"
|
echo "common --config=ci"
|
||||||
echo "common --disk_cache=$HOME/.cache/omp-bazel-disk"
|
echo "common --disk_cache=$HOME/.cache/omp-bazel-disk"
|
||||||
|
|||||||
@@ -43,5 +43,8 @@ runs:
|
|||||||
if: steps.cache.outputs.save-needed == 'true'
|
if: steps.cache.outputs.save-needed == 'true'
|
||||||
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||||
with:
|
with:
|
||||||
path: ~/.cache/omp-bazel-disk
|
# Must mirror the restore path list in the bazel-cache action.
|
||||||
|
path: |
|
||||||
|
~/.cache/omp-bazel-disk
|
||||||
|
~/.cache/omp-bazel-repo
|
||||||
key: ${{ steps.cache.outputs.cache-key }}
|
key: ${{ steps.cache.outputs.cache-key }}
|
||||||
@@ -37,6 +37,45 @@ rust = use_extension("@rules_rust//rust:extensions.bzl", "rust")
|
|||||||
rust.toolchain(
|
rust.toolchain(
|
||||||
edition = "2024",
|
edition = "2024",
|
||||||
versions = ["nightly/2026-04-29"],
|
versions = ["nightly/2026-04-29"],
|
||||||
|
# Pinned archive checksums for every toolchain component. Not (only) a
|
||||||
|
# supply-chain nicety: rules_rust marks a toolchain-tools repo as
|
||||||
|
# reproducible — and therefore eligible for Bazel's repo contents cache —
|
||||||
|
# only when every sha256 it needs was predeclared here (repositories.bzl:
|
||||||
|
# `reproducible = sha256s == dict(ctx.attr.sha256s)`). Without these,
|
||||||
|
# every fresh output base (= every ephemeral CI pod) re-downloaded and
|
||||||
|
# re-extracted ~5 rustc toolchains (~20 s each). Regenerate after a
|
||||||
|
# version bump: for each `<tool>-nightly-<triple>` below, take the value
|
||||||
|
# from https://static.rust-lang.org/dist/<date>/<file>.tar.xz.sha256.
|
||||||
|
sha256s = {
|
||||||
|
"2026-04-29/cargo-nightly-aarch64-apple-darwin.tar.xz": "9165010618ad581a90bd3e74a36cab092e6f509c8e7ffdcfe00293257cafabb7",
|
||||||
|
"2026-04-29/cargo-nightly-aarch64-unknown-linux-gnu.tar.xz": "f9b463c3eadaf040b5028590c3d3072c8b0893f9863ed25138dfc54c254388e1",
|
||||||
|
"2026-04-29/cargo-nightly-x86_64-apple-darwin.tar.xz": "03cf3edb1d0b9564fd466553092ccec5c37be729c35df1d77f7c5a9206801638",
|
||||||
|
"2026-04-29/cargo-nightly-x86_64-unknown-linux-gnu.tar.xz": "0ae6ed5a9e262d082003d5804cd7fc6977057cfa3df721451e356347962f391f",
|
||||||
|
"2026-04-29/clippy-nightly-aarch64-apple-darwin.tar.xz": "84b933f8a2837c81adca3e3a44fed971ec0de27673e2c56f122f6d2b35ef9371",
|
||||||
|
"2026-04-29/clippy-nightly-aarch64-unknown-linux-gnu.tar.xz": "827c90b264a716475e85f51bd1999344af14648882cdd5a6d517a73c7e4c02c4",
|
||||||
|
"2026-04-29/clippy-nightly-x86_64-apple-darwin.tar.xz": "2c749f10bb18c752323b489e056c55f2e6e04ff3939d16444f4f0d960463d2d2",
|
||||||
|
"2026-04-29/clippy-nightly-x86_64-unknown-linux-gnu.tar.xz": "36a9409a58b3ac16ce9823d4e705055cad8144dd7f18464c028e3a06ae5d87c8",
|
||||||
|
"2026-04-29/llvm-tools-nightly-aarch64-apple-darwin.tar.xz": "c6a5cfd0c6133e1fae913a624bef2387a1b9c1e2e75316f9d9b6872a592a8b2c",
|
||||||
|
"2026-04-29/llvm-tools-nightly-aarch64-unknown-linux-gnu.tar.xz": "7e51dc58df2d0d9e263d629e6b149785bb61b716e267cc841556a4641ed52a50",
|
||||||
|
"2026-04-29/llvm-tools-nightly-x86_64-apple-darwin.tar.xz": "ab6cd3bae1c979fd807982b8c39e911227f9344dab5051d45f612b440dad13ff",
|
||||||
|
"2026-04-29/llvm-tools-nightly-x86_64-unknown-linux-gnu.tar.xz": "0fb4bed6714359d9505b870c8bd67c722266c5a3894f66523bc231b9c479db31",
|
||||||
|
"2026-04-29/rust-src-nightly.tar.xz": "2a9c5ae7696a808e30fc5169ddfea20d69571a11997f142944c022a0d30af48b",
|
||||||
|
"2026-04-29/rust-std-nightly-aarch64-apple-darwin.tar.xz": "cd9e231f3e343b4ed5cff5c384c813cecba13fca94ef767fa8dc4aa0ff58a171",
|
||||||
|
"2026-04-29/rust-std-nightly-aarch64-unknown-linux-gnu.tar.xz": "80dceec313e144e3cfc5d67326826d85c664e762a27b53fea018a96d537a2942",
|
||||||
|
"2026-04-29/rust-std-nightly-aarch64-unknown-linux-musl.tar.xz": "9d5cb99d5678b2310bd69b2b654e9dcbbc3c5a50f9b66d03a21745cff4444927",
|
||||||
|
"2026-04-29/rust-std-nightly-x86_64-apple-darwin.tar.xz": "4992887472dfdea66a7f96c85b81104b543974204f91722742bbe5453bce8ec1",
|
||||||
|
"2026-04-29/rust-std-nightly-x86_64-pc-windows-msvc.tar.xz": "890d91c1b86e482aaee32d793b366ee3889a9326143cd7f82a2b7507a4f4d592",
|
||||||
|
"2026-04-29/rust-std-nightly-x86_64-unknown-linux-gnu.tar.xz": "09774060c01c82005a2ae4e4b46a899c5e6157d6cc7188dfbb750c0a0f7c52cf",
|
||||||
|
"2026-04-29/rust-std-nightly-x86_64-unknown-linux-musl.tar.xz": "de5936933a2994ebff227b62fe41fca5707496d13da33563f2bfee3049e7b122",
|
||||||
|
"2026-04-29/rustc-nightly-aarch64-apple-darwin.tar.xz": "61fc2a3fd11637fbe9f961319aa16d84615d2a033de46909742000448290c687",
|
||||||
|
"2026-04-29/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz": "d8c9d9117a0499b6891e4622c55c7be9568e6b0cbed4f53540e51459ab514633",
|
||||||
|
"2026-04-29/rustc-nightly-x86_64-apple-darwin.tar.xz": "66efb8a2fb4155cd010bafda3382f643d87f337b646542f7830eda36cf1571a4",
|
||||||
|
"2026-04-29/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz": "b0db9dc4957c0f12ff8be0a30d22b411d4e2a7f434d747d767156be80d782f1d",
|
||||||
|
"2026-04-29/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "56dcf5ac72bcf663687273b0b9cdf953537081f38a4592d3577e9a6502707b4b",
|
||||||
|
"2026-04-29/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "b495726b0f311dcb53a8cf5325c61ef321f110a3739247536bc87109d428a3cc",
|
||||||
|
"2026-04-29/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "9c64403758b4b631b60057f6ed4a93b02f19286a59a60f8ea235b4f7d4e1ba4c",
|
||||||
|
"2026-04-29/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "397e4ead440f29a1fc10903388a377f5607a1d404c29dc3e3a979d2bc813a801",
|
||||||
|
},
|
||||||
extra_target_triples = [
|
extra_target_triples = [
|
||||||
"x86_64-unknown-linux-gnu",
|
"x86_64-unknown-linux-gnu",
|
||||||
"aarch64-unknown-linux-gnu",
|
"aarch64-unknown-linux-gnu",
|
||||||
|
|||||||
@@ -12,9 +12,18 @@ dir. Link steps keep the shared cache: they are the ones that benefit
|
|||||||
battle-tested path for concurrent artifact builds, and after first warm they
|
battle-tested path for concurrent artifact builds, and after first warm they
|
||||||
are pure readers.
|
are pure readers.
|
||||||
|
|
||||||
|
Also opt @zig_config into Bazel's repo contents cache (repo_metadata,
|
||||||
|
bazel >= 8.3): the fetch is deterministic given the pinned zig archive and
|
||||||
|
wrapper source, and re-running it cost ~20 s of wrapper compilation on every
|
||||||
|
fresh output base — every job on ephemeral CI pods.
|
||||||
|
|
||||||
|
Note: bazel's own patch parser (unlike GNU patch) requires the `diff --git`
|
||||||
|
separator line before each file section of a multi-file patch.
|
||||||
|
|
||||||
|
diff --git a/toolchain/zig-wrapper.zig b/toolchain/zig-wrapper.zig
|
||||||
--- a/toolchain/zig-wrapper.zig
|
--- a/toolchain/zig-wrapper.zig
|
||||||
+++ b/toolchain/zig-wrapper.zig
|
+++ b/toolchain/zig-wrapper.zig
|
||||||
@@ -252,6 +252,32 @@ fn parseArgs(
|
@@ -267,6 +267,32 @@
|
||||||
if (run_mode == RunMode.cc)
|
if (run_mode == RunMode.cc)
|
||||||
try resolveColonLibraries(arena, cwd, &args);
|
try resolveColonLibraries(arena, cwd, &args);
|
||||||
|
|
||||||
@@ -47,3 +56,19 @@ are pure readers.
|
|||||||
// Add -target as the last parameter. The wrapper should overwrite
|
// Add -target as the last parameter. The wrapper should overwrite
|
||||||
// the target specified by other tools calling the wrapper.
|
// the target specified by other tools calling the wrapper.
|
||||||
// Some tools might pass LLVM target triple, which are rejected by zig.
|
// Some tools might pass LLVM target triple, which are rejected by zig.
|
||||||
|
diff --git a/toolchain/defs.bzl b/toolchain/defs.bzl
|
||||||
|
--- a/toolchain/defs.bzl
|
||||||
|
+++ b/toolchain/defs.bzl
|
||||||
|
@@ -278,6 +278,12 @@
|
||||||
|
)
|
||||||
|
repository_ctx.symlink("tools/zig-wrapper{}".format(exe), tool_path)
|
||||||
|
|
||||||
|
+ # omp: opt into the repo contents cache — the fetch is deterministic
|
||||||
|
+ # given the pinned zig archive and the wrapper source above.
|
||||||
|
+ if hasattr(repository_ctx, "repo_metadata"):
|
||||||
|
+ return repository_ctx.repo_metadata(reproducible = True)
|
||||||
|
+ return None
|
||||||
|
+
|
||||||
|
zig_repository = repository_rule(
|
||||||
|
attrs = {
|
||||||
|
"version": attr.string(),
|
||||||
|
|||||||
@@ -120,6 +120,12 @@ def _llvm_msvc_tools_impl(rctx):
|
|||||||
|
|
||||||
rctx.file("BUILD.bazel", _BUILD.format(version = _LLVM_VERSION, host = key), executable = False)
|
rctx.file("BUILD.bazel", _BUILD.format(version = _LLVM_VERSION, host = key), executable = False)
|
||||||
|
|
||||||
|
# Opt into the repo contents cache: the fetch is a pure function of the
|
||||||
|
# pinned URL+sha256 and the deterministic prune above, and the ~172 s
|
||||||
|
# extraction of the 2 GiB archive was the single largest cost of every
|
||||||
|
# fresh output base on ephemeral CI pods (profiled: run 30510579596).
|
||||||
|
return rctx.repo_metadata(reproducible = True)
|
||||||
|
|
||||||
llvm_msvc_tools_repository = repository_rule(
|
llvm_msvc_tools_repository = repository_rule(
|
||||||
implementation = _llvm_msvc_tools_impl,
|
implementation = _llvm_msvc_tools_impl,
|
||||||
doc = "Pruned LLVM release binaries (clang-cl/lld-link/llvm-lib/llvm-rc) for the exec host.",
|
doc = "Pruned LLVM release binaries (clang-cl/lld-link/llvm-lib/llvm-rc) for the exec host.",
|
||||||
|
|||||||
@@ -161,6 +161,14 @@ def _xwin_sysroot_impl(rctx):
|
|||||||
executable = False,
|
executable = False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Opt into the repo contents cache. The splat is channel-stable, not
|
||||||
|
# bit-reproducible forever (see the module docstring) — caching freezes a
|
||||||
|
# known-good splat, which also keeps remote action keys stable across
|
||||||
|
# pods until this file changes or the cache entry ages out (14 d GC).
|
||||||
|
# OMP_XWIN_CACHE_DIR is a predeclared input (environ attr), so kata and
|
||||||
|
# dev fetches key separate entries.
|
||||||
|
return rctx.repo_metadata(reproducible = True)
|
||||||
|
|
||||||
xwin_sysroot_repository = repository_rule(
|
xwin_sysroot_repository = repository_rule(
|
||||||
implementation = _xwin_sysroot_impl,
|
implementation = _xwin_sysroot_impl,
|
||||||
doc = "MSVC CRT + Windows SDK sysroot splatted by a pinned xwin release.",
|
doc = "MSVC CRT + Windows SDK sysroot splatted by a pinned xwin release.",
|
||||||
|
|||||||
Reference in New Issue
Block a user