Skip to content

ci: keep the build caches alive between bursts of work - #61

Merged
radiosilence merged 1 commit into
mainfrom
60-make-sure-the-pipeline-uses-the-aggressive-cachi
Aug 8, 2026
Merged

ci: keep the build caches alive between bursts of work#61
radiosilence merged 1 commit into
mainfrom
60-make-sure-the-pipeline-uses-the-aggressive-cachi

Conversation

@radiosilence

Copy link
Copy Markdown
Owner

Closes #60.

The caching was already there

Worth saying up front, because it changes what this PR is: the pipeline
already does what jaritanet does. Swatinem/rust-cache is on every job that
compiles, keyed per target on the matrix legs, with save-if restricted to
main so a pull request restores the shared entry without evicting it. The
last run on main reports Cache hit ... full match: true and Cache up-to-date on both architectures.

The reason /actions/caches is empty is that GitHub deletes any cache nothing
has read for 7 days, and this repo goes quiet for longer than that between
bursts of work. The caches were not missing — they expired, and the next push
after a quiet fortnight compiles ~200 crates from cold on all four runners.
That cold run is the slow build in the issue.

What changes

A twice-weekly build on main (Mon/Thu 06:00 UTC), plus workflow_dispatch.
Reading a cache resets its clock and the job re-saves it against the current
Cargo.lock, so the entries never reach the eviction threshold and the cost of
a cold compile lands on a schedule instead of on whoever pushes next.

Nothing publishes on a schedule, and no new gate was needed for that: publish
and build-darwin were already conditioned on github.event_name == 'push'.
The binary uploads are skipped on schedule runs so a warm-up does not leave a
90-day artefact behind twice a week.

build-darwin now runs on the schedule too (!= 'pull_request' rather than
== 'push'). It is release-only, so its caches are wanted warm exactly when a
release goes out — which is rare enough that under the old condition they had
always expired by then. Public repo, so the macOS runners are free.

cargo build dropped from check. cargo test compiles the binary as
well, so it was a second pass over the same crates. Clippy moves to
--all-targets --locked, which lints the test code the bare invocation skipped;
it is clean under that today (verified locally). --verbose dropped from
cargo test — it only inflated the log.

What is deliberately not copied from jaritanet

The buildkit-blob-* / index-* entries in jaritanet's cache list are the GHA
layer cache from its reusable publish workflow. Adding those back here would be
a regression: since #54 nothing compiles inside the Dockerfile — it is a COPY
of a prebuilt binary onto distroless — and mode=max was stuffing Rust build
layers into the same repo-wide 10GB budget rust-cache uses, so the two evicted
each other. jaritanet's mise toolchain cache also has no counterpart; there is
no mise.toml here.

Verifying

  • check and both build-image legs must still pass on this PR, restoring
    from main and saving nothing (save-if is false off main).
  • The schedule only takes effect once this is on main — GitHub reads
    scheduled triggers from the default branch's copy of the workflow. First
    proof is either the Monday/Thursday run or a manual workflow_dispatch;
    after it, /actions/caches should list v0-rust-* entries for check,
    both linux-* legs and both *-apple-darwin targets.
  • No changelog entry: this ships no user-visible change, matching ci: publish from one job, release last, gate on the latest release #53 which
    was also CI-only and left it alone.

The pipeline already caches Rust builds the same way jaritanet does —
Swatinem/rust-cache on every compiling job, keyed per target, saving only
from main so a pull request cannot evict the entry it restores from. The
last run on main hit that cache on both architectures. What it does not
have is anything keeping the entries alive: GitHub drops a cache nothing
has read for 7 days, and this repo regularly goes quiet for longer, so
the caches are simply gone by the time work resumes and the next push
compiles ~200 crates from cold on every runner.

Builds on main twice a week so the entries stay warm and get re-saved
against the current Cargo.lock. Nothing publishes on a schedule — the
existing gates on publish and the release already require a push event —
and the binary uploads are skipped so a warm-up run leaves no 90-day
artefacts. build-darwin joins the schedule despite being release-only:
its caches are wanted warm exactly when a release goes out, which is rare
enough that they would otherwise always have expired.

Also drops `cargo build` from the check job, which only compiled a second
time what `cargo test` compiles anyway, and lints the tests by moving
clippy to --all-targets --locked. Clippy is clean under it today.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K5PUhckVayB6JLBywqgBP1
@radiosilence
radiosilence marked this pull request as ready for review August 8, 2026 12:12
@radiosilence
radiosilence merged commit ec9f5b6 into main Aug 8, 2026
5 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.

Make sure the pipeline uses the aggressive caching in jaritanet

1 participant