← Wed, Sep 16 digest

Scaling Golang CI by Replacing actions/setup-go

read article ↗ hn thread ↗

summary

The official GitHub actions/setup-go action slows down parallel CI workflows because its immutable cache keys are too generic, leading to stale data and race conditions between jobs. By implementing a more granular keying strategy that includes job identity and run IDs, CloudX reduced test runtimes by 69%. This approach ensures that every job saves its specific progress and that subsequent runs load the most recent cache state regardless of whether dependencies changed.

key points

  1. The default GitHub Go action uses a cache key based only on the OS, architecture, Go version, and go.mod file, meaning the cache only updates when these specific elements change.
  2. Parallel jobs like linting and testing often overwrite each other's cache entries because they share the same key, causing one job to repeatedly load a cache that lacks the necessary data for the other.
  3. The cloudx-io/setup-go replacement fixes this by incorporating the run ID and a custom prefix into the key, forcing a fresh cache save after every single job run.

who should read it

DevOps engineers and Go developers who manage complex CI pipelines on GitHub Actions and want to reduce build and test times.

discussion positive

consensus

Commenters generally agree that default CI caching, specifically via actions/setup-go, is often inefficient for larger projects and can be improved through custom caching strategies. While some advocate for custom-built Docker images to avoid installation overhead, others prefer optimized caching mechanisms like cache key prefixes and pruning. There is a shared sentiment that CI speed is critical for developer productivity, though implementing a general-purpose, high-performance cache for all users remains technically challenging.

top insight

The use of a pluggable GOCACHEPROG (introduced in Go 1.24) allows for shimming cache logic to measure performance or implement remote caching. This provides a way to avoid the monolithic loading of large tarballs, which often wastes time transferring and unpacking files that aren't actually needed for the current build. This approach shifts the focus from simple blob storage to more granular, efficient cache access.

Generated by an LLM from the article and thread. Check the sources before relying on it.