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:
can1357
2026-07-30 07:20:27 +02:00
parent 6b4efa896f
commit 52bd191b34
6 changed files with 95 additions and 4 deletions
+12 -2
View File
@@ -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"
+4 -1
View File
@@ -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 }}
+39
View File
@@ -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(),
+6
View File
@@ -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.",
+8
View File
@@ -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.",