CI/CD for a Go Library with a Version Matrix in GitHub Actions
A published library has to work on every Go version your users run -- so test them all.
A Go library is consumed by projects on different Go versions, so CI should test across the versions you support, not just the latest. A build matrix runs the suite on each version in parallel, and the race detector catches concurrency bugs. This recipe tests a library across several Go releases.
What the pipeline does
- Runs the test suite across a matrix of Go versions.
- Runs go vet to catch suspicious constructs.
- Runs tests with the race detector enabled.
- Caches modules and build output per version.
The workflow
A matrix over go-version runs every supported release in parallel, each with module caching.
name: Go Library CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
go: ['1.21', '1.22', '1.23']
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: \${{ matrix.go }}
cache: true
- name: Vet
run: go vet ./...
- name: Test with race detector
run: go test -race ./...Notes for this platform
Set fail-fast: false so one failing Go version does not cancel the others -- you want to see exactly which versions break. The race detector is worth the slower run for a library, since concurrency bugs are the kind your consumers will hit. Every matrix leg runs on Linux, so use your cheapest, fastest runner class; with Latchkey Linux runners around 69% cheaper than GitHub-hosted Linux, a wide matrix stays affordable, and managed runners auto-retry transient module-download failures across all legs.
Key takeaways
- Test a library across every Go version your users run, not just the latest.
- Set fail-fast: false so one failing version does not hide the others.
- Run the race detector to catch concurrency bugs consumers would hit.