GitHub Actions includes CI/CD for free for Open Source repositories. This document contains information on making it work well for Go. See them in action:
$ cat .github/workflows/test.yml
on: [push, pull_request]
name: Test
permissions:
contents: read
jobs:
test:
strategy:
matrix:
go-version: [1.26.x, 1.27.x]
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v7
- uses: actions/setup-go@v7
with:
go-version: ${{ matrix.go-version }}
- run: go test ./...Each workflow file has a number of jobs, which get run on specified events,
and run concurrently with each other. You can have workflow status badges.
Each job runs on a configuration matrix. For example, we can test two major
Go versions on three operating systems. actions/setup-go also accepts
stable and oldstable to always test the latest two Go versions.
Each job has a number of steps, such as installing Go, or checking out the
repository's code.
The permissions limit the workflow's token to read-only access, which is all it needs.
Note that name fields are optional.
They can be set up via env for an entire
workflow,
a job, or for each step:
env:
GOPROXY: "https://proxy.company.com"
jobs:
[...]You can use environment files
to set environment variables or add an element to $PATH. For example:
steps:
- name: Set env vars
run: |
echo "CGO_ENABLED=0" >> $GITHUB_ENV
echo "${HOME}/goroot/bin" >> $GITHUB_PATHNote that these take effect for future steps in the job.
The default shell on Windows is PowerShell, which needs $env:GITHUB_ENV
instead, or you can use shell: bash on the step.
actions/setup-go caches GOCACHE
and GOMODCACHE automatically, hashing go.mod into the cache key.
You can turn that off via cache: false, and then you may also use your own
custom caching, for example to only keep GOMODCACHE:
- uses: actions/cache@v6
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.mod') }}
restore-keys: |
${{ runner.os }}-go-See this guide for more details.
You can use if conditionals, using their custom expression
language:
- if: github.event_name == 'push' && matrix.os == 'ubuntu-latest'
run: go run ./endtoendYou can include extra matrix
jobs,
and you can exclude specific matrix
jobs.
By default, one failing job cancels the rest of the matrix; set
fail-fast
to false to let them all finish.
- name: Series of commands
run: |
go test ./...
go test -race ./...The biggest difference is the UI; workflow results are shown separately. Grouping jobs in workflows can also be useful if one wants to customize the workflow triggers, or to set up dependencies via needs.
Follow these steps
to set up the secret in the repo's settings. After adding a secret like
FOO_SECRET, use it on a step as follows:
- run: some-command
env:
FOO_SECRET: ${{ secrets.FOO_SECRET }}It's possible to install modules from private GitHub repositories without using your own proxy. You'll need to add a personal access token with read access to the repositories' contents as a secret environment variable, as well as configure GOPRIVATE. Note that the GITHUB_TOKEN provided to workflows can only access the repository running the workflow. You can define anything as username in the URL, it is not taken into account by GitHub.
- name: Configure git for private modules
env:
TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
run: git config --global url."https://user:${TOKEN}@github.com".insteadOf "https://github.com"env:
GOPRIVATE: "github.com/yourorg"
jobs:
[...]Use sudo apt-get, making sure to only run the step on Linux:
- if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y --no-install-recommends mypackage-
Usage limits: https://docs.github.com/en/actions/reference/limits
-
Syntax and fields reference: https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax
-
GitHub-hosted runners: https://docs.github.com/en/actions/concepts/runners/github-hosted-runners
git config core.autocrlf defaults to true, so be careful about CRLF endings in
your plaintext testdata files on Windows. To work around this, set up the
following .gitattributes:
* -text