GoReleaser Ship Go releases

Version 2.18 · source

Start here

goreleaser init
Create .goreleaser.yaml
goreleaser check
Validate the config
goreleaser build --snapshot --clean
Build only, no tag needed
goreleaser release --snapshot --clean
Dry run of a full release
git tag -a v0.1.0 -m "<msg>"
Tag the version
git push origin v0.1.0
Push the tag
export GITHUB_TOKEN=<token>
Allow publishing
goreleaser release --clean
Build and publish

Concepts

  1. Git tag v1.2.3
  2. Binaries per OS/arch
  3. Archives + checksums
  4. Signatures optional
  5. GitHub release + changelog
What a release does

Setup

goreleaser init
Write an example .goreleaser.yaml
goreleaser check
Validate the config file
goreleaser healthcheck
Check that needed tools are installed
goreleaser --help
List commands and global flags
goreleaser <command> --help
Flags of one command
goreleaser --version
Show the installed version
goreleaser check --config <file>
Validate a non-default config
goreleaser --config <file> <command>
Use a custom config path
goreleaser jsonschema
Print the config JSON schema
Point your editor at it for completion on .goreleaser.yaml
goreleaser completion <shell>
Print a shell completion script

Build

goreleaser build --snapshot --clean
Build all targets without a tag
goreleaser build --single-target --clean
Build only for this machine
GOOS=<os> GOARCH=<arch> goreleaser build --single-target
Build one chosen target
goreleaser build --id <build>
Build one build ID
goreleaser build --output <path>
Copy the binary to a path
goreleaser build --skip=<hook>
Skip a step such as before hooks
goreleaser build --parallelism <n>
Limit concurrent tasks
goreleaser build --timeout <dur>
Set the build time limit

Release

goreleaser release --clean
Publish the release for the current tag
goreleaser release --snapshot --clean
Full local run, nothing published
goreleaser release --skip=publish
Build and package but do not publish
goreleaser release --skip=<step>,<step>
Skip several steps
goreleaser release --draft
Create the release as a draft
goreleaser release --release-notes <file>
Use your own release notes
goreleaser release --release-header <file>
Add a header to the notes
goreleaser release --release-footer <file>
Add a footer to the notes
goreleaser release --fail-fast
Stop at the first failed publisher
goreleaser release --auto-snapshot
Snapshot if the tree is dirty
goreleaser release --parallelism <n>
Limit concurrent tasks
goreleaser release --timeout <dur>
Set the release time limit
git tag -a v<x.y.z> -m "<msg>"
Create the release tag
git push origin v<x.y.z>
Push the tag
GITHUB_TOKEN=<token> goreleaser release
Pass the token for one run
Classic token needs repo scope; fine-grained needs contents: write

Config keys

version: 2
First line of the config file
project_name: <name>
Name used in templates and archives
builds:
Binaries to compile
archives:
How binaries are packaged
checksum:
Checksum file settings
changelog:
Release notes from commits
release:
GitHub/GitLab/Gitea release options
signs:
Sign artifacts with an external tool
before: hooks:
Commands run before the build
snapshot:
Version template for snapshots
env_files:
Files with tokens to load

Builds

main: ./cmd/<name>
Path of the main package
binary: <name>
Output binary name
goos: [linux, darwin, windows]
Target operating systems
goarch: [amd64, arm64]
Target architectures
env: [CGO_ENABLED=0]
Build environment variables
ldflags: [-s -w -X main.version={{.Version}}]
Linker flags with version stamp
flags: [-trimpath]
Extra go build flags
tags: [<tag>]
Go build tags
ignore: [{goos: <os>, goarch: <arch>}]
Skip one OS/arch pair
targets: [<os>_<arch>]
Explicit target list, replaces goos/goarch
mod_timestamp: "{{ .CommitTimestamp }}"
Reproducible file times
id: <build>
Name a build to reference it elsewhere

Archives and checksums

formats: [tar.gz]
Archive formats (tar.gz is default)
name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
Archive file name
format_overrides: [{goos: windows, formats: [zip]}]
Zip for Windows only
files: [LICENSE*, README*]
Extra files inside the archive
wrap_in_directory: true
Put contents in one top folder
formats: [binary]
Upload raw binaries, no archive
checksum: name_template: checksums.txt
Name of the checksum file

Changelog and release

changelog: sort: asc
Order commits in the notes
changelog: filters: exclude: ["^docs:"]
Hide commits matching a regex
changelog: use: github-native
Let GitHub generate the notes
Turns off groups, sort and filters
changelog: groups:
Sort commits into titled sections
changelog: disable: true
Skip the changelog
release: draft: true
Leave the release as a draft
release: prerelease: auto
Mark rc/beta tags as pre-releases
release: mode: append
Combine with existing notes
release: header: "<text>"
Text above the notes
release: github: {owner: <o>, name: <n>}
Target repo (default: from origin)

Templates and signing

{{ .Version }}
Version without the leading v
{{ .Tag }}
Git tag as pushed
{{ .ProjectName }}
Project name
{{ .Os }} / {{ .Arch }}
Target OS and arch (per artifact)
{{ .Env.<NAME> }}
Read an environment variable
{{ .ShortCommit }}
Short commit hash
.Commit is deprecated
{{ tolower .ProjectName }}
Lowercase a value
{{ envOrDefault "<NAME>" "<value>" }}
Env var with fallback
signs: artifacts: checksum
Sign only the checksum file
signs: cmd: cosign
Use cosign instead of gpg
signs: args: ["${artifact}"]
Arguments for the signing command

Recipes

Minimal .goreleaser.yaml
version: 2builds:  - env: [CGO_ENABLED=0]    goos: [linux, darwin, windows]    goarch: [amd64, arm64]    ldflags: [-s -w -X main.version={{.Version}}]archives:  - formats: [tar.gz]    format_overrides:      - {goos: windows, formats: [zip]}
Try it locally, then release
goreleaser checkgoreleaser release --snapshot --cleanls dist/git tag -a v0.1.0 -m "First release"git push origin v0.1.0goreleaser release --clean
Release from GitHub Actions
# on: push: tags: ['*']; permissions: contents: write- uses: actions/checkout@v7  with: {fetch-depth: 0}- uses: actions/setup-go@v7  with: {go-version: stable}- uses: goreleaser/goreleaser-action@v7  with: {version: "~> v2", args: release --clean}  env: {GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"}
Sign checksums with cosign
checksum:  name_template: checksums.txtsigns:  - cmd: cosign    signature: "${artifact}.sigstore.json"    args: [sign-blob, "--bundle=${signature}", "${artifact}", "--yes"]    artifacts: checksum
Build one target to test
GOOS=linux GOARCH=arm64 goreleaser build --single-target --cleanfile dist/*/<name>