ci: cache Go build cache via reusable go-cache action#1048
Conversation
CI disabled setup-go's cache and manually cached only the module cache (~/go/pkg/mod). The Go build cache (~/.cache/go-build) — the dominant cost for our -race test/compile workload — was never cached, so every job recompiled from scratch. Add a reusable composite action (.github/actions/go-cache) that restores the module + build cache, with the single main-branch unit-test job saving them. GitHub scopes caches by branch, so only the default branch's cache is readable by all PRs: one authoritative saver on main, everyone else restore-only. The build-cache key rotates daily so it never goes stale, and a trim step keeps the saved tarball under the 10 GB repo cache cap. Wire it into every Go-compiling workflow. -race jobs (pr/main tests, smoketests, long tests) get module + build cache; non-race jobs (golangci, sonar, nightly, chainintegrity builds, benchmarks) get module cache only — the build cache is flag-keyed by Go, so non-race jobs would only waste bandwidth on a tarball they cannot hit. Also align benchmark-compare to Go 1.26.0 (was 1.25.2, the only version drift).
|
🤖 Claude Code Review Status: Complete Current Review: No issues found. The cache implementation is well-designed:
|
Benchmark Comparison ReportBaseline: Current: Summary
All benchmark results (sec/op)
Threshold: >10% with p < 0.05 | Generated: 2026-06-07 08:29 UTC |
|
ordishs
left a comment
There was a problem hiding this comment.
Approved. CI-only change with a sound caching model — single authoritative saver on main (correct given GitHub's branch-scoped caches) and the -race vs non-race build_cache split is a sharp call.
Verified: checkout precedes the local composite action in every touched job; the boolean save input flows correctly through the string guards; restore-vs-save variants are wired right (PR jobs never write); SHA-pinned actions/cache.
Minor non-blocking notes for follow-up:
Trim Go build cachelacks a branch guard — runs on non-maingo-testinvocations where nothing is ever saved (harmless, just wasted work).-mmin +90deletes by mtime (≈ creation time for write-once build objects), so onmake testruns exceeding 90 min it may drop still-useful objects before the post-job save.- Worth watching the repo cache usage page for a few days — daily-rotating build-cache tarballs accumulating against the 10 GB budget could evict the module cache.



What
CI never cached the Go build cache (
~/.cache/go-build).setup-go's cache was disabled and we manually cached only the module cache (~/go/pkg/mod). For our workload —go test -raceacross the whole tree — the-racecompile is the dominant cost, and it was rebuilt from scratch on every job.This adds a reusable composite action
.github/actions/go-cacheand wires it into every Go-compiling workflow.How
main. GitHub scopes caches by branch — only the default branch's cache is readable by all PRs. So the main-branch unit-test job (teranode_main_tests→go-test) is the only writer (savegated torefs/heads/main); every other job is restore-only. staging/release/tag builds restore but don't write, leaving the 10 GB repo budget to main.gobuild-${os}-${hash(go.mod)}-${date}) with prefix restore-key fallback, so the build cache never pins stale for weeks. Module cache keeps the existinggomod-${os}-${hash(go.sum)}scheme.find ~/.cache/go-build -mmin +90 -delete) keeps the uploaded tarball under the 10 GB cap.-racevs not. Go keys the build cache by build flags, so a non-race job restoring the-racesaver's multi-GB tarball gets ~zero hits — pure wasted bandwidth. The composite exposesbuild_cache(defaulttrue); non-race jobs set itfalseand restore the module cache only.-raceAlso
benchmark-comparewas on Go 1.25.2 while everything else is 1.26.0 — aligned it (added a workflowenv: GO_VERSIONso it can't drift again). Benches now compile/run under 1.26.0.Notes
main'sgo-testruns post-merge. Merge first, then watch a follow-up PR for the build-cache hit.actionlinton all touched workflows (clean; remaining notes are pre-existing shellcheck warnings in unrelated docker-log loops and the known custom-runner-label notes). Cache hit/timing can only be confirmed by a live run.