Go build cache
Share Go's build cache entry by entry through GOCACHEPROG, served by Magic Cache from your own S3 bucket with GitHub's branch scopes. Go 1.24+.
Go 1.24 and later can hand the build cache to a program through GOCACHEPROG. Since v3.6.0, with remote_cache: go, runs-on/action ↗ points it at its own binary, which keeps the cache on local disk and shares it through the RunsOn agent, entry by entry, in your stack’s cache bucket:
- Each job uploads only the entries it compiled, instead of saving a new copy of the whole
GOCACHE. - GitHub’s cache scoping applies: a pull request reads its base branch’s entries and writes only its own. Cache isolation covers the entries.
- When the job starts, the action downloads in the background the entries the same job used in its previous run, so the go command finds them on local disk.
jobs: build: runs-on: runs-on=${{ github.run_id }}/runner=4cpu-linux-x64/extras=s3-cache steps: - uses: runs-on/action@v2 with: remote_cache: go - uses: actions/checkout@v5 - uses: actions/setup-go@v6 with: go-version: stable cache: false # the build cache is in the remote cache - uses: actions/cache@v5 with: path: ~/go/pkg/mod key: gomod-${{ runner.os }}-${{ hashFiles('**/go.sum') }} - run: go build ./... && go test ./...On a c7a.4xlarge, building Prometheus’s commands took 5.6–5.8 s with nothing changed, against 45 s without a cache. setup-go’s cache got the build to 4.7 s, but restoring its archive, which also holds the module cache, took about 15 s first. A job the action had no list for yet, such as a new matrix leg, fetched entries as the go command asked for them, in 24 s. The first, cold build took about 8 s longer than without a cache, while it uploaded every entry.
Compiled packages are shared between jobs; test results are not. Within a job, a test whose inputs did not change still reports (cached), but a new job runs its tests again, because a test can depend on things Go does not track, such as a database or the network.
To share test results too, use remote_cache: go,tests=true. A test that passed in another job with the same inputs then reports (cached). Go tracks the package, its dependencies, and the files and environment variables the test read through the standard library. It does not see a database, the network, or a file read by a child process: keep the default for such tests, or run them with go test -count=1. What a passing test printed is stored with its result and is then readable by any job that can read the cache, including pull requests from forks: do not use tests=true for tests that print secrets.
Requires Magic Cache (extras=s3-cache) and RunsOn v3.6.0 or later. Otherwise, the action warns and Go keeps its local build cache. Container jobs are supported. The runtime token that the action registers with the agent reaches no run step.
The Go guide covers the rest of a fast Go pipeline: runner sizes, the module cache and test flags.