CI/CD for a Go CLI Binary with GitHub Actions
Build one Go binary for every OS and ship them all on a tag.
Go cross-compiles to almost any OS and architecture from a single Linux runner just by setting GOOS and GOARCH -- no emulation, no extra toolchains. This recipe tests the CLI, builds binaries for several targets with a matrix, and attaches them to a GitHub Release when you push a tag.
What the pipeline does
- Runs go test on every push and pull request.
- Cross-compiles binaries for several OS/arch targets via a matrix.
- Builds release binaries only on tag pushes.
- Attaches the binaries to a GitHub Release.
The workflow
A build matrix over GOOS and GOARCH produces all targets from one Linux runner; the release job runs only on tags.
name: Go CLI
on:
push:
branches: [main]
tags: ['v*']
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.22'
cache: true
- run: go test ./...
release:
needs: test
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
strategy:
matrix:
include:
- { goos: linux, goarch: amd64 }
- { goos: darwin, goarch: arm64 }
- { goos: windows, goarch: amd64 }
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.22'
- name: Build
env:
GOOS: \${{ matrix.goos }}
GOARCH: \${{ matrix.goarch }}
run: go build -o dist/mycli-\${{ matrix.goos }}-\${{ matrix.goarch }} ./cmd/mycli
- uses: softprops/action-gh-release@v2
with:
files: dist/*Notes for this platform
Go cross-compilation needs no emulator -- one Linux runner builds Linux, macOS, and Windows binaries by setting GOOS/GOARCH, so you never pay for macOS or Windows runners just to ship those targets. Enable Go module/build caching via setup-go for faster runs. Managed Linux runners run roughly 69% cheaper than GitHub-hosted Linux and auto-retry transient module-download failures, so a flaky proxy.golang.org fetch will not break a release.
Key takeaways
- Go cross-compiles to every OS from one Linux runner via GOOS/GOARCH.
- Use a matrix to build all targets in parallel and attach them on tag.
- No macOS or Windows runners needed -- everything builds on cheap Linux.