iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
💮

A Complete CI Workflow for Go Packages with GitHub Actions

に公開

In this article, I will introduce how to use GitHub Actions to automate the following tasks for Go package repositories.

  1. Vulnerability scanning for dependent packages (on push or pull request)
  2. Lint & test (on push or pull request)
  3. Build & deploy (when a version tag is added)

Vulnerability scanning for dependent packages

For scanning dependent packages, nancy seems like a good choice. An official GitHub Action is also provided.

https://github.com/sonatype-nexus-community/nancy
https://github.com/sonatype-nexus-community/nancy-github-action

To run nancy with GitHub Actions, place a YAML file with the following content in the .github/workflows/ directory.

vulns.yml
name: vulns
on:
  push:
    branches:
      - main
  pull_request:
jobs:
  vulns:
    name: Vulnerability scanner
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-go@v2
        with:
          go-version: ^1.19
      - name: WriteGoList
        run: go list -json -m all > go.list
      - name: Nancy
        uses: sonatype-nexus-community/nancy-github-action@main

With this, vulnerability scanning will run on pull requests and on pushes to the main branch[1].

I use my own tool depm to collect module information. It looks like this:

      - name: install depm
        run: go install github.com/goark/depm@latest
      - name: WriteGoList
        run: depm list --json > go.list

You can choose whichever method you prefer.

Lint & Test

For Go linters, golangci-lint is highly recommended. golangci-lint is an excellent tool that aggregates results from multiple linters, including go vet. An official GitHub Action is also available.

https://github.com/golangci/golangci-lint
https://github.com/golangci/golangci-lint-action

To run golangci-lint with GitHub Actions, place a YAML file with the following content in the .github/workflows/ directory.

lint.yml
name: lint
on:
  push:
    branches:
      - main
  pull_request:

permissions:
  contents: read
  # Optional: allow read access to pull request. Use with `only-new-issues` option.
  # pull-requests: read
jobs:
  golangci:
    name: lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/setup-go@v3
        with:
          go-version: ^1.19
      - uses: actions/checkout@v3
      - name: golangci-lint
        uses: golangci/golangci-lint-action@v3
        with:
          # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version
          version: latest

          # Optional: working directory, useful for monorepos
          # working-directory: somedir

          # Optional: golangci-lint command line arguments.
          # args: --issues-exit-code=0

          # Optional: show only new issues if it's a pull request. The default value is `false`.
          # only-new-issues: true

          # Optional: if set to true then the all caching functionality will be complete disabled,
          #           takes precedence over all other caching options.
          # skip-cache: true

          # Optional: if set to true then the action don't cache or restore ~/go/pkg.
          # skip-pkg-cache: true

          # Optional: if set to true then the action don't cache or restore ~/.cache/go-build.
          # skip-build-cache: true

      - name: testing
        run: go test -shuffle on ./...

With this, golangci-lint will run on pull requests and on pushes to the main branch[1:1]. By the way, the following part of the steps items:

      - name: testing
        run: go test -shuffle on ./...

is the section that executes Go tests. If you need more complex tests using the make command or similar instead of a simple go test, you will need to add a bit more detail.

Build & Deploy

If it is Pure Go, GoReleaser can handle everything from cross-compilation to deployment on the Release page automatically. Settings are written in .goreleaser.yml[2]. An official GitHub Action is also provided.

https://github.com/goreleaser/goreleaser/
https://github.com/goreleaser/goreleaser-action

To run GoReleaser with GitHub Actions, place a YAML file with the following content in the .github/workflows/ directory.

build.yml
name: build

on:
  push:
    tags:
      - v*
jobs:
  goreleaser:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          fetch-depth: 0
      - name: Set up Go
        uses: actions/setup-go@v3
        with:
          go-version: ^1.19
      - name: Run GoReleaser
        uses: goreleaser/goreleaser-action@v3
        with:
          # either 'goreleaser' (default) or 'goreleaser-pro'
          distribution: goreleaser
          version: latest
          args: release --rm-dist
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          # Your GoReleaser Pro key, if you are using the 'goreleaser-pro' distribution
          # GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}

With this, cross-compilation and deployment via GoReleaser will run when a version tag is added.

Adding GitHub Action Badges

You can add badges that display the status of your GitHub Actions to documents such as README.md. Use the following format to specify the badge:

[![Actions Status](https://github.com/{user}/{repo}/workflows/{action}/badge.svg)](https://github.com/{user}/{repo}/actions)

For example, for the repository https://github.com/goark/koyomi:

[![lint status](https://github.com/goark/koyomi/workflows/lint/badge.svg)](https://github.com/goark/koyomi/actions)

It will be displayed like this:

lint status

Note that the name for {action} corresponds to the name field on the first line of the YAML, not the file name.

Reference Pages

脚注
  1. Since October 2020, the default branch name for new GitHub repositories has become main. Please note that in older repositories, it remains as master. ↩︎ ↩︎

  2. I will omit details on how to use GoReleaser. You can probably find information in Japanese by searching for it. ↩︎

GitHubで編集を提案

Discussion