Release Go Projects with GoReleaser

GoReleaser automates building, packaging, and publishing releases for Go projects from a single config file.

Release on a tag push

This run definition releases on every Git tag push:

on:
  github:
    push:
      if: ${{ event.git.tag != '' }}
      init:
        commit-sha: ${{ event.git.sha }}

base:
  image: ubuntu:24.04
  config: rwx/base 1.0.2

tasks:
  - key: code
    call: git/clone 2.0.7
    with:
      repository: https://github.com/YOUR-ORG/YOUR-REPO.git
      ref: ${{ init.commit-sha }}
      github-token: ${{ github.token }}
      preserve-git-dir: true
      fetch-full-depth: true

  - key: go
    call: golang/install 1.2.1
    with:
      go-version: 1.26

  - key: goreleaser
    run: |
      arch="$(uname -m)"
      [ "$arch" = "aarch64" ] && arch="arm64"
      curl -fsSL "https://github.com/goreleaser/goreleaser/releases/download/${VERSION}/goreleaser_Linux_${arch}.tar.gz" \
        | sudo tar -xz -C /usr/local/bin goreleaser
    env:
      VERSION: v2.15.4

  - key: release
    use: [code, go, goreleaser]
    cache: false
    run: goreleaser release --clean
    env:
      GITHUB_TOKEN: ${{ github.token }}

A few things worth noting:

  • if: ${{ event.git.tag != '' }} filters the run to tag pushes. See GitHub Push Trigger for the full set of event fields.
  • preserve-git-dir: true and fetch-full-depth: true keep the .git directory and full history so GoReleaser can compute version metadata and changelogs.

Validate the config on pull requests

Run goreleaser release --snapshot --skip=publish on pull requests to catch config errors before they break a tag push:

on:
  github:
    pull_request:
      init:
        commit-sha: ${{ event.git.sha }}

# ... base, code, go, goreleaser tasks as above ...

tasks:
  - key: snapshot
    use: [code, go, goreleaser]
    run: goreleaser release --snapshot --clean --skip=publish

Building Docker images

If your .goreleaser.yaml declares dockers: or docker_manifests:, two things need to change in the release task:

  • Set docker: true so RWX runs a Docker daemon for the task. Without it, GoReleaser's calls to docker build and docker push will fail.
  • Add a docker login to the run script before goreleaser release. GoReleaser doesn't authenticate for you — it expects the daemon to already have credentials. Pull registry credentials from a secret and pass them as env with cache-key: excluded so the value isn't part of the cache key.

Reference