Repository navigation
Conversation
mlugg/setup-zig@v2 restores its cache into $GITHUB_WORKSPACE/.zig-cache.
In all eight Zig jobs of brain-ci.yml it ran before actions/checkout,
which finds no clone in the workspace and empties it ("Deleting the
contents of '/home/runner/work/trinity-fpga/trinity-fpga'"). Every
restored cache was deleted before a build step used it.
Measured with `speed zigcache` over the last 25 completed brain-ci runs:
238 restores, 0 used. 237 were hits that checkout then deleted; 1 was a
miss. Each job still paid about 1-1.8 s to restore and 1-2.4 s to save
26-71 MB. On 2026-10-05 those saves were 157 of the 179 Actions cache
entries, 7.95 GB of 11.04 GB, where they evict the chipdb (#844).
Check out first, in every Zig job. No step, condition or input changes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
X Brain Health CheckScore: 100.0/100 X Brain is above merge threshold |
🧪 Brain Stress Test ResultsScore: not measured (no stress test prints a Score: line) X Stress test passed |
|
The CPU-pinning experiment mentioned under "A warm hit only helps on the same CPU model" has now been measured once. Results are in #844 (comment 5986656054). On branch This PR does not pin the CPU. Pinning changes what 🤖 Generated with Claude Code |
… cache mlugg/setup-zig restores into $GITHUB_WORKSPACE/.zig-cache, and an actions/checkout of the workspace after it deletes the restored cache. This is how brain-ci lost every hit (238 of 238 in 25 runs), and nothing stops the old order from coming back. tools/check_setup_zig_order.py reads every workflow with PyYAML and exits 1 for a caching setup-zig step followed by a checkout of the workspace. A checkout into a subdirectory and `use-cache: false` both pass. It exits 2, not 0, when no job uses setup-zig or a workflow does not parse. tools/test_check_setup_zig_order.py plants 17 cases. Four mutants of the checker are each caught. On this branch: 122 workflows, 16 setup-zig jobs, 0 findings. On main's brain-ci.yml: 8 of 8 jobs reported. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The five brain-unit matrix legs got one setup-zig key, so the first leg
to finish saved and the other four were refused ("Unable to reserve
cache"): 88 of 110 saves in 25 runs. Every leg then restored that one
region's build and compiled its own test binary from nothing. setup-zig
documents `cache-key` for exactly this: include the matrix variables.
Stacked on #890, which makes the restored cache survive checkout.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Three checks on this PR are red. None of them comes from this change.
#872 fixes the Follow-up: #891 gives each 🤖 Generated with Claude Code |
f75bbb9 to
966c838
Compare
The five brain-unit matrix legs got one setup-zig key, so the first leg
to finish saved and the other four were refused ("Unable to reserve
cache"): 88 of 110 saves in 25 runs. Every leg then restored that one
region's build and compiled its own test binary from nothing. setup-zig
documents `cache-key` for exactly this: include the matrix variables.
Stacked on #890, which makes the restored cache survive checkout.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Summary by t27-beesThis PR fixes a cache-thrashing bug in Worth a look
Read: 4 files, +304 -40, the whole diff. Head |
Part of #844 and #851 (W4b).
What
Moves
actions/checkoutahead ofmlugg/setup-zigin the eight Zig jobs ofbrain-ci.yml.Adds a gate so the old order cannot return:
.github/workflows/zig-cache-order.ymlrunstools/check_setup_zig_order.py. That check fails any job where a caching setup-zig step is followed by a checkout of the workspace. A checkout into a subdirectory passes, and so doesuse-cache: false. If no job uses setup-zig, or a workflow does not parse, it answers "cannot tell" (exit 2) rather than passing.tools/test_check_setup_zig_order.pyplants 17 cases and runs first. I wrote four mutants of the checker and the test catches each of them:path:counts as the workspace;On this branch the checker reads 123 workflows and finds 16 setup-zig jobs, none of them out of order. The commit message says 122 because I counted before adding the gate's own workflow, which has no setup-zig. Run on main's
brain-ci.yml, it reports 8 of 8 jobs.Why
setup-zig restores
.zig-cacheinto$GITHUB_WORKSPACE. When checkout runs after it, the workspace is not a clone yet, so checkout logsDeleting the contents of '<workspace>'and removes the cache that was just restored. Read from the job logs of the last 25 brain-ci runs withspeed zigcache --workflow brain-ci.yml: 238 restores, 238 hits, 0 used. Every hit was downloaded and then deleted before any step ran, and every job saved a new entry on the way out anyway.That is not free storage. Live list at 01:05Z: brain-ci's entries are 161 of 178 entries in this repo's Actions cache, 8.43 GB of 10.83 GB (78%). The chipdb entries the FPGA jobs need compete for the same 10 GB limit (#844).
Measured
One
workflow_dispatchrun of this branch, 37248624658, all green, against the median of 25 earlier runs.work= restore done until the post step's size check, i.e. everything the job did after setup-zig:This is close to a best case: the branch differs from
mainonly in this workflow, so the restored entries were built from the same sources.Behaviour change: an unchanged test binary is not run again
Integration's 0.6 s is not faster tests. The tests did not run. In Zig 0.16
std/Build/Step/Run.zig,hasSideEffects()is false for.zig_test, and line 926 skips the run on a cache hit (if (!has_side_effects and try step.cacheHitAndWatch(&man))). With a warm cache, a test binary whose inputs did not change keeps its earlier pass and is not executed.Two consequences:
tri_rand(integration, stress) no longer gets a fresh run, and a fresh--seed, on every CI run when its code is unchanged.If that matters for a job, the opt-outs are per step
has_side_effects = true(Run.zig line 89) or a file input (addFileInput, line 701), oruse-cache: falsefor the whole job. This PR does not choose for you.A warm hit only helps on the same CPU model
build.zigusesstandardTargetOptions, so the target is the native CPU, and the CPU model and features are part of every artifact's hash. GitHub'subuntu-latestrunners are not one machine: a single run of this workflow spread its jobs over AMD EPYC 7763, 9V45, 9V74 and Intel Xeon Platinum 8573C.Measured on the probe branch
exp/zig-cpu-probe(this PR's change plus a step that prints/proc/cpuinfo's model name), two dispatches, 37249467137 then 37249915131, each job restoring the entry the first run saved. Saver and restorer matched by setup-zig key, not by job name:.zig-cachedirectorylocus-coeruleus(9V45 → 9V74), Stress (9V45 → 7763)The other four Unit legs also grew (0.17 → 0.23 GB), but they are not counted: they restored the
locus-coeruleusleg's entry (shared key, below), so each built a test binary for its own region that was never in it.Negative control: every one of those pairs ran on the same runner image version (
20260927.320.1), and so did all 9 saver/restorer pairs found in 40ci.ymlruns, 7 of which rebuilt. The image is not what differs.So the Health growth in the run above (0.39 → 0.71 GB on identical sources) fits a runner with a different CPU from the saver's. That one is an inference: the saving run on
maindid not print its CPU.What this PR does not fix: a warm restore onto a different CPU model still recompiles. Pinning the target CPU (
-Dcpu=…on eachzig build) should make entries portable across runners. That is a separate experiment and an owner's call, becausevsa_simdbenefits from the native CPU's vector width.Not measured
Unit Testslegs get the same setup-zig key, so the first one saves and the rest are refused (4 of 5 in the run above). In the probe, all five legs restored what thelocus-coeruleusleg saved, so four of them started without their own region's test binary. Acache-key: ${{ matrix.region }}would fix it. That is a follow-up, not part of this PR.🤖 Generated with Claude Code