github-actions-golang icon indicating copy to clipboard operation
github-actions-golang copied to clipboard

GitHub Actions as CI for Go

GitHub Actions for Go

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
jobs:
  test:
    strategy:
      matrix:
        go-version: [1.18.x, 1.19.x]
        os: [ubuntu-latest, macos-latest, windows-latest]
    runs-on: ${{ matrix.os }}
    steps:
    - uses: actions/setup-go@v3
      with:
        go-version: ${{ matrix.go-version }}
    - uses: actions/checkout@v3
    - run: go test ./...

Summary

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.

Each job has a number of steps, such as installing Go, or checking out the repository's code.

Note that name fields are optional.

FAQs

How do I set environment variables?

They can be set up via env for an entire workflow, a job, or for each step:

env:
  GOPROXY: "https://proxy.company.com"
jobs:
  [...]

How do I set environment variables at run-time?

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_PATH

Note that these take effect for future steps in the job.

How do I set up caching between builds?

Use actions/cache. For example, to cache downloaded modules:

- uses: actions/cache@v3
  with:
    path: ~/go/pkg/mod
    key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
    restore-keys: |
      ${{ runner.os }}-go-

You can also include Go's build cache, to improve incremental builds:

- uses: actions/cache@v3
  with:
    # In order:
    # * Module download cache
    # * Build cache (Linux)
    # * Build cache (Mac)
    # * Build cache (Windows)
    path: |
      ~/go/pkg/mod
      ~/.cache/go-build
      ~/Library/Caches/go-build
      ~\AppData\Local\go-build
    key: ${{ runner.os }}-go-${{ matrix.go-version }}-${{ hashFiles('**/go.sum') }}
    restore-keys: |
      ${{ runner.os }}-go-${{ matrix.go-version }}-

This is demonstrated via the test-cache job in this very repository.

See this guide for more details.

How do I run a step conditionally?

You can use if conditionals, using their custom expression language:

- if: github.event_name == 'push' && matrix.os == 'ubuntu-latest'
  run: go run ./endtoend

How do I set up a custom build matrix?

You can include extra matrix jobs, and you can exclude specific matrix jobs.

How do I run multiline scripts?

- name: Series of commands
  run: |
    go test ./...
    go test -race ./...

Should I use two workflows, or two jobs on one workflow?

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.

How do I set up a secret environment variable?

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 }}

How do I install private modules?

It's possible to install modules from private GitHub repositories without using your own proxy. You'll need to add a personal access token as a secret environment variable, as well as configure GOPRIVATE.

- name: Configure git for private modules
  env:
    TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
  run: git config --global url."https://YOUR_GITHUB_USERNAME:${TOKEN}@github.com".insteadOf "https://github.com"
env:
  GOPRIVATE: "*.company.com"
jobs:
  [...]

How do I install Linux packages?

Use sudo apt, making sure to only run the step on Linux:

- if: matrix.os == 'ubuntu-latest'
  run: sudo apt update && sudo apt install -y --no-install-recommends mypackage

How do I set up a GOPATH build?

Declare GOPATH and clone inside of it:

jobs:
  test-gopath:
    env:
      GOPATH: ${{ github.workspace }}
      GO111MODULE: off
    defaults:
      run:
        working-directory: ${{ env.GOPATH }}/src/github.com/${{ github.repository }}
    steps:
    - uses: actions/checkout@v3
      with:
        path: ${{ env.GOPATH }}/src/github.com/${{ github.repository }}

Quick links

  • Concepts, rate limits, etc: https://docs.github.com/en/actions/learn-github-actions

  • Syntax and fields reference: https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions

  • Environment reference: https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners

  • To report bugs: https://github.community/c/code-to-cloud/github-actions/41

Caveats

  • https://github.com/actions/checkout/issues/135

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
  • https://github.com/actions/virtual-environments/issues/712

os.TempDir on Windows will contain a short name, since %TEMP% also contains it. Note that case sensitivity doesn't matter, and that os.Open should still work; but some programs not treating short names might break.

> echo %USERPROFILE%
C:\Users\runneradmin
> echo %TEMP%
C:\Users\RUNNER~1\AppData\Local\Temp