chore: only save the go build cache from dev and main

Restore is what makes CI fast; save is what got expensive. A same-era A/B
across the switch to this cache shows what restore buys: wall time went
6:50 to 3:52, Build Spinifex 63s to 10s, test-race 385s to 188s. Since
then the cache has grown to its steady state and the work has not moved,
so Build and Test now spends 75s restoring and 64s saving where it once
spent 13s and 8s.

A PR's save is read by nothing else. Splitting restore from save and
gating the save on dev and main keeps every branch reading a cache a dev
merge refreshes minutes later, and takes the upload off the 56% of runs
that are pull requests.
This commit is contained in:
Julian Sommer
2026-09-01 14:19:56 +10:00
parent bbd0ebebed
commit da92c7a083
+39 -6
View File
@@ -89,8 +89,11 @@ jobs:
# Build artifacts follow source, so the key rolls per run and falls back to
# this job's newest entry. Keyed per job because -race, -covermode=atomic
# and plain builds produce disjoint entries and would evict each other.
- name: Cache Go build
uses: actions/cache@v6
# Restore runs everywhere; the matching save is gated to dev and main, so
# a PR reads the base branch's entry without spending a minute uploading
# one only that PR would ever read.
- name: Restore Go build cache
uses: actions/cache/restore@v6
with:
path: ~/.cache/go-build
key: gobuild-${{ github.job }}-${{ github.run_id }}
@@ -131,6 +134,16 @@ jobs:
- name: Check Diff Coverage
run: cd spinifex && scripts/diff-coverage.sh coverage.out --base HEAD~1
# Compiled output stays valid whatever the tests said, and skipping the
# save on a red run would leave the next one rebuilding it, so this is
# gated on the branch rather than on success.
- name: Save Go build cache
if: ${{ !cancelled() && (github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/main') }}
uses: actions/cache/save@v6
with:
path: ~/.cache/go-build
key: gobuild-${{ github.job }}-${{ github.run_id }}
race_detection:
name: Race Detection
runs-on: ubuntu-26.04
@@ -198,8 +211,11 @@ jobs:
# Build artifacts follow source, so the key rolls per run and falls back to
# this job's newest entry. Keyed per job because -race, -covermode=atomic
# and plain builds produce disjoint entries and would evict each other.
- name: Cache Go build
uses: actions/cache@v6
# Restore runs everywhere; the matching save is gated to dev and main, so
# a PR reads the base branch's entry without spending a minute uploading
# one only that PR would ever read.
- name: Restore Go build cache
uses: actions/cache/restore@v6
with:
path: ~/.cache/go-build
key: gobuild-${{ github.job }}-${{ github.run_id }}
@@ -211,6 +227,13 @@ jobs:
- name: Run Tests with Race Detector
run: make -C spinifex test-race GOTESTFLAGS=-count=1
- name: Save Go build cache
if: ${{ !cancelled() && (github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/main') }}
uses: actions/cache/save@v6
with:
path: ~/.cache/go-build
key: gobuild-${{ github.job }}-${{ github.run_id }}
lint_and_security:
name: Lint + Security + Integration
runs-on: ubuntu-26.04
@@ -279,8 +302,11 @@ jobs:
# Build artifacts follow source, so the key rolls per run and falls back to
# this job's newest entry. Keyed per job because -race, -covermode=atomic
# and plain builds produce disjoint entries and would evict each other.
- name: Cache Go build
uses: actions/cache@v6
# Restore runs everywhere; the matching save is gated to dev and main, so
# a PR reads the base branch's entry without spending a minute uploading
# one only that PR would ever read.
- name: Restore Go build cache
uses: actions/cache/restore@v6
with:
path: ~/.cache/go-build
key: gobuild-${{ github.job }}-${{ github.run_id }}
@@ -301,3 +327,10 @@ jobs:
- name: Run Integration Tests
if: ${{ !cancelled() }}
run: make -C spinifex test-integration
- name: Save Go build cache
if: ${{ !cancelled() && (github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/main') }}
uses: actions/cache/save@v6
with:
path: ~/.cache/go-build
key: gobuild-${{ github.job }}-${{ github.run_id }}