Skip to content

CI: main reuses its own build cache, with --prune and a nightly run from nothing - #2402

Merged
ashhart merged 2 commits into
mainfrom
lead/ci-main-reuse
Nov 7, 2026
Merged

ashhart merged 2 commits into
mainfrom
lead/ci-main-reuse

Conversation

@ashhart

@ashhart ashhart commented Nov 6, 2026

Copy link
Copy Markdown
Owner

Pull requests already restore main's newest build cache, but main itself built from nothing on every push. During a landing burst its saves fell several commits behind, and one shared-source commit in between undid most of a pull request's reuse.

What changes

  • Main reuses its cache. The zig and zig-windows jobs on main restore main's newest cache, like a pull request, and save it again. So each push compiles and runs only what changed since the last save.
  • zig_cache_restat --prune keeps the cache to about one build. It deletes the entries a checkout can't hit: an entry whose recorded file changed or can't be read, and any entry that uses a deleted entry's output folder. Without it, a cache that is restored and saved again keeps growing. All four restat steps pass --prune, including release-paths and macOS dev-tools, which already restored on main and were growing.
  • A nightly run builds from nothing (03:23 UTC). It skips every restore, so something a reused pass could hide fails within a day: for example, a test that reads a file the build doesn't know about (build: the portable-names test runs every time, since a reused pass can't see a name added since #2311 fixed the one case found so far). It saves under a -nightly key, so it doesn't collide with the push run for the same commit. On the nightly run, release-paths checks all three platforms, as on main's pushes. The lean check is skipped because a scheduled run has no base to compare against.

If restat fails, the job just rebuilds more than it needs to. It never skips a check.

Tests

  • tools/zig/zig_cache_restat_test.py with Zig 0.17.0: both tests pass. The new test_prune_keeps_one_build links a C object into the executable.
    • With nothing changed, pruning keeps every entry and all three steps stay cached.
    • After a change to the C file, all three steps miss and at least three entries are pruned along with their output folders. The number of output folders is the same after the rebuild, so the cache didn't grow.
  • zig fmt --check is clean, the lean check finds nothing new, and the workflow parses.

…m nothing

A pull request reuses main's newest cache, but main built from nothing, so during a landing burst its saves fell
several commits behind and one shared-source commit in between undid most of the reuse. Main now restores its newest
cache like a pull request and saves it again, and zig_cache_restat --prune deletes the entries a checkout can't hit
(a changed or missing file, or another dead entry's output), so the saved cache stays about one build. A nightly run
skips every restore, so a pass reuse could hide, such as a test reading a file the build doesn't know of, fails within
a day, and its cache starts the next day clean.
@ashhart
ashhart force-pushed the lead/ci-main-reuse branch from 734eefa to 78efd62 Compare November 7, 2026 01:40
@ashhart
ashhart merged commit 32a6946 into main Nov 7, 2026
5 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant