goreleaser: Deliver Go binaries as fast and easily as possible

To update or switch versions, run webi goreleaser@stable (or @v0.174, @beta, etc).

Cheat Sheet

goreleaser makes it easy to build versioned Go binaries for Mac, Linux, Windows, and Raspberry Pi, and to publish the ChangeLog and binaries to common release platforms including GitHub, Gitea, Gitlab, and Homebrew.

There's a lot that you can do with GoReleaser. These are the things that we've found the most useful for the majority of projects:

  • Files
  • Basic Usage & Versioning
  • Publishing Builds to GitHub
  • Publishing to Gitea and Gitlab
  • Building for RPi et al
  • Building from one or more cmd/s
  • Cross-Compiling with cgo
  • Full .goreleaser.yml example

Files

These are the files / directories that are created and/or modified with this install:

~/.config/envman/PATH.env
~/.config/goreleaser/github_token
~/.local/bin/goreleaser
<PROJECT-DIR>/.goreleaser.yaml

Basic Usage & Versioning

To create an example .goreleaser.yaml file, and test the configuration:

goreleaser init

# dry run
goreleaser --snapshot --skip=publish --clean
  • --snapshot allows "dirty" builds (when the repo has uncommitted changes)
  • --skip=publish will NOT publish to GitHub, etc
  • --clean will automatically remove the ./dist/ directory

The default .goreleaser.yml works well for projects for which package main is at the root.

GoReleaser provides version information. Here's a good, generic way to print it out:

package main

var (
    // these will be replaced by goreleaser
    version = "0.0.0"
    date    = "0001-01-01T00:00:00Z"
    commit  = "0000000"
)

func main() {
    if len(os.Args) >= 2 {
        if os.Args[1] == "-V" || strings.TrimPrefix(os.Args[1]) == "version" {
            fmt.Printf("CHANGE_ME v%s %s (%s)\n", version, commit[:7], date)
            os.Exit(0)
        }
    }

    // ...
}

How to Publish Builds to GitHub

You'll need a Personal Access Token with the repo scope.
You can get one at https://github.com/settings/tokens/new.

You can export the environment variable:

export GITHUB_TOKEN="YOUR_GITHUB_TOKEN"

Or place the token in the default config location:

~/.config/goreleaser/github_token

You can also set env_files in .goreleaser.yml:

env_files:
  github_token: ~/.config/goreleaser/github_token

Running GoReleaser without --snapshot must use the latest Git tag of your repository. Create a tag and push it to Git:

git tag -a v1.0.0 -m "First release"
git push origin v1.0.0

Running GoReleaser without --skip=publish will publish the builds:

goreleaser --clean

Check the console output to make sure that there are no messages about a failed publish.
If all is well you should the git tag on the releases page updated with a ChangeLog and the published binaries.

How to Publish to Gitea and others

Gitea Token: https://try.gitea.io/user/settings/applications

env_files:
  gitea_token: ~/.config/goreleaser/gitea_token
gitea_urls:
  api: https://try.gitea.io/api/v1/

GitLab Token: https://gitlab.com/profile/personal_access_tokens

env_files:
  gitlab_token: ~/.config/goreleaser/gitlab_token
gitlab_urls:
  api: https://gitlab.com/api/v1/

Also see https://goreleaser.com/environment/

How to Build for Raspberry Pi (ARM)

All of the Raspberry Pis are ARM processors and can run Linux. Most can run Windows as well.

  • RPi 4 is ARM 64, also known as aarch64, arm64, and armv8.
  • RPi 3 could run armv7 and arm64.
  • RPi 2, RPi Zero, and RPi can run either armv6 or armv7.

To build Go binaries for ARM, you'll need to update the build section of your .goreleases.yml.

builds:
  - env:
      - CGO_ENABLED=0
    goos:
      - linux
      - windows
      - darwin
    goarch:
      - 386
      - amd64
      - arm
      - arm64
    goarm:
      - 6
      - 7

For information on other supported build options, such as BSD and ppc, see Go (Golang) GOOS and GOARCH.

How to Build from the cmd Directory

By default GoReleaser assumes that the root of your package is package main.

If your package main is in a cmd/ directory or you have multiple commands, you should update your builds directive accordingly.

- builds:
    - id: command123
      main: ./cmd/command123/command123.go
      binary: command123
      goos:
        - linux
        - windows
        - darwin
      goarch:
        - amd64
        - arm64
    - id: other321
      main: ./cmd/other321/other321.go
      binary: other123
      goos:
        - linux
        - windows
        - darwin
      goarch:
        - amd64
        - arm64

How to Cross-Compile cgo

cgo is not Go - Dave Cheney

Most Go programs are "pure Go" and will cross-compile CGO_ENABLED=0 without any special configuration.

Some programs include C libraries, especially SQLite3 or 7z, and require integration with C libraries.

Mac Cross-Compilers

From macOS you can easily cross-compile cgo for Windows and Linux.

Install brew, if needed:

curl -sS https://webi.sh/brew | sh

Install mingw and musl-cross:
(this may take hours if pre-built binaries are not available)

brew install mingw-w64
brew install FiloSottile/musl-cross/musl-cross --with-aarch64 --with-arm # --with-mips --with-486

You may want to manually test compiling for multiple platforms before automating it:

GOARCH=amd64 GOOS=darwin                              go build -o unarr_darwin cmd/unarr/unarr.go
GOARCH=amd64 GOOS=windows CC=x86_64-w64-mingw32-gcc   go build -o unarr.exe cmd/unarr/unarr.go
GOARCH=amd64 GOOS=linux   CC=x86_64-linux-musl-gcc    go build -o unarr_linux_amd64 cmd/unarr/unarr.go
GOARCH=arm64 GOOS=linux   CC=aarch64-linux-musl-gcc   go build -o unarr_linux_arm64 cmd/unarr/unarr.go
GOARCH=arm   GOOS=linux   CC=arm-linux-musl-gcc       go build -o unarr_linux_armv7 cmd/unarr/unarr.go

If you have simple instructions for how to set up cross-compiling from Windows or Linux, please let us know.

Build Changes

You'll need to manually create a different builds item for each unique id:

- builds:
    - id: unarr-linux-x64
      main: ./cmd/unarr/unarr.go
      env:
        - CGO_ENABLED=1
        - CC=x86_64-linux-musl-gcc
      flags:
        - '-ldflags'
        - '-extldflags "-static"'
      goos:
        - linux
      goarch:
        - amd64
    - id: unarr-linux-aarch64
      main: ./cmd/unarr/unarr.go
      env:
        - CGO_ENABLED=1
        - CC=aarch64-linux-musl-gcc
      flags:
        - '-ldflags'
        - '-extldflags "-static"'
      goos:
        - linux
      goarch:
        - arm64
    - id: unarr-linux-armv7
      main: ./cmd/unarr/unarr.go
      env:
        - CGO_ENABLED=1
        - CC=arm-linux-musleabi-gcc
      flags:
        - '-ldflags'
        - '-extldflags "-static"'
      goos:
        - linux
      goarch:
        - arm
      goarm:
        - 7
    - id: unarr-windows-x64
      main: ./cmd/unarr/unarr.go
      env:
        - CGO_ENABLED=1
        - CC=x86_64-w64-mingw32-gcc
      flags:
        - '-ldflags'
        - '-extldflags "-static"'
      goos:
        - linux
      goarch:
        - amd64

If you compile without -static, you will need the musl libraries to run on (non-Alpine) Linuxes:

sudo apt-get install -y musl

Full Example Config

The full file will look something like this:

.goreleaser.yml

project_name: exampleproject
before:
  hooks:
    - go mod download
    - go generate ./...
builds:
  - env:
      - CGO_ENABLED=0
    goos:
      - linux
      - windows
      - darwin
      - freebsd
      - js
    goarch:
      - 386
      - amd64
      - arm
      - arm64
      - wasm
    goarm:
      - 7
archives:
  - id: my-binary
    format: tar.xz
    format_overrides:
      - goos: windows
        format: zip
checksum:
  name_template: 'checksums.txt'
snapshot:
  name_template: '{{ .Tag }}-next'
changelog:
  sort: asc
  filters:
    exclude:
      - '^docs:'
      - '^test:'

Contribute

Report an Issue Submit Installer Star on GitHub