Skip to content
Latchkey

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.

.github/workflows/go-cli.yml
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.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →