GoReleaser is a release automation tool for Go projects. The goal is to simplify the build, release and publish steps while providing variant customization options for all steps.
GoReleaser is built for CI tools; you only need to download and execute it in your build script. Of course, you can also install it locally if you wish.
You can also customize your release process through a
.goreleaser.yml
file.
4151 GitHub projects trust their release process to GoReleaser.
You can install the pre-compiled binary (in several different ways), use Docker or compile from source.
Here are the steps for each of them:
homebrew tap (only on macOS for now):
$ brew install goreleaser/tap/goreleaser
homebrew (may not be the latest version):
$ brew install goreleaser
snapcraft:
$ sudo snap install --classic goreleaser
scoop:
$ scoop bucket add goreleaser https://github.com/goreleaser/scoop-bucket.git
$ scoop install goreleaser
deb/rpm:
Download the .deb
or .rpm
from the releases page and
install with dpkg -i
and rpm -i
respectively.
Shell script:
$ curl -sfL https://install.goreleaser.com/github.com/goreleaser/goreleaser.sh | sh
manually:
Download the pre-compiled binaries from the releases page and copy to the desired location.
You can also use it within a Docker container. To do that, you’ll need to execute something more-or-less like the following:
$ docker run --rm --privileged \
-v $PWD:/go/src/github.com/user/repo \
-v /var/run/docker.sock:/var/run/docker.sock \
-w /go/src/github.com/user/repo \
-e GITHUB_TOKEN \
-e DOCKER_USERNAME \
-e DOCKER_PASSWORD \
-e DOCKER_REGISTRY \
goreleaser/goreleaser release
ATTENTION: Currently, the provided docker image does not support the generation of snapcraft packages.
Note that the image will almost always have the last stable Go version.
The DOCKER_REGISTRY
environment variable can be left empty when you are
releasing to the public docker registry.
If you need more things, you are encouraged to keep your own image. You can always use GoReleaser’s own Dockerfile as an example though and iterate from that.
Here you have two options:
If just want to build from source for whatever reason, follow the steps bellow:
# clone it outside GOPATH
git clone https://github.com/goreleaser/goreleaser
cd goreleaser
# get dependencies using go modules (needs go 1.11+)
go get ./...
# build
go build -o goreleaser .
# check it works
./goreleaser --version
In this example we will build, archive and release a sample Go project.
Create a GitHub repository and add a single main package:
// main.go
package main
func main() {
println("Ba dum, tss!")
}
Run goreleaser init
to create an example .goreleaser.yaml
file:
$ goreleaser init
• Generating .goreleaser.yml file
• config created; please edit accordingly to your needs file=.goreleaser.yml
You can customize the generated .goreleaser.yml
or leave
it as-is, it’s up to you.
You can test the configuration at any time by running GoReleaser with a few extra parameters to not require a version tag, skip publishing to GitHub, and remove any already-built files:
$ goreleaser --snapshot --skip-publish --rm-dist
If you are not using vgo or Go modules, then you will need to comment out the before hooks in the generated config file or update them to match your setup accordingly.
GoReleaser will build the binaries for your app for Windows, Linux and macOS,
both amd64 and i386 architectures. You can customize that by changing the
builds
section. Check the documentation for more information.
After building the binaries, GoReleaser will create an archive for each OS/Arch
pair into a separate file. You can customize several things by changing
the archive
section, including releasing only the binaries and not creating
archives at all. Check the documentation for more information.
You’ll need to export either a GITHUB_TOKEN
or GITLAB_TOKEN
environment variable, which should
contain a valid GitHub token with the repo
scope or GitLab token with api
scope.
It will be used to deploy releases to your GitHub/GitLab repository.
You can create a token here for GitHub or here for GitLab.
$ export GITHUB_TOKEN=`YOUR_GH_TOKEN`
# or
$ export GITLAB_TOKEN=`YOUR_GL_TOKEN`
GoReleaser will use the latest Git tag of your repository. Create a tag and push it to GitHub:
$ git tag -a v0.1.0 -m "First release"
$ git push origin v0.1.0
Attention: Check if your tag adheres to semantic versioning.
If you don’t want to create a tag yet, you can also create a release
based on the latest commit by using the --snapshot
flag. (Note: only GitHub supports snapshots)
Now you can run GoReleaser at the root of your repository:
$ goreleaser
That’s all! Check your GitHub project’s release page. The release should look like this:
Or check your GitLab project’s release page. The release should also look like this:
Note: Releasing to a private-hosted GitLab CE will only work for version v11.7+
, because the release feature
was introduced in this version.
If you want to test everything before doing a release “for real”, you can
use the --skip-publish
flag, which will only build and package things:
$ goreleaser release --skip-publish
You can check the other options by running:
$ goreleaser --help
and
$ goreleaser release --help
GoReleaser enforces semantic versioning and will error on non compliant tags.
Your tag should be a valid semantic version. If it is not, GoReleaser will error.
The v
prefix is not mandatory. You can check the templating
documentation to see how to use the tag or each part of the semantic version
in name templates.
Unfortunately, GoReleaser does not support CGO.
You can see the discussion about this in this issue.
You can see the comments on the issue referenced for workarounds on it.
GoReleaser requires either a GitHub API token with the repo
scope selected to
deploy the artifacts to GitHub or a GitLab API token with api
scope or a Gitea API token.
You can create one here for GitHub
or here for GitLab
or in Settings | Applications | Generate New Token
page of your Gitea instance.
This token should be added to the environment variables as GITHUB_TOKEN
or GITLAB_TOKEN
or GITEA_TOKEN
respecively.
Here is how to do it with Travis CI:
Defining Variables in Repository Settings.
Alternatively, you can provide the GitHub/GitLab token in a file.
GoReleaser will check ~/.config/goreleaser/github_token
, ~/.config/goreleaser/gitlab_token
and ~/.config/goreleaser/gitea_token
by default, you can change that in
the .goreleaser.yml
file:
# .goreleaser.yml
env_files:
# use only one or release will fail!
github_token: ~/.path/to/my/gh_token
gitlab_token: ~/.path/to/my/gl_token
gitea_token: ~/.path/to/my/gitea_token
IMPORTANT: you can define multiple env files, but the release process will fail because multiple tokens are defined. Use only one.
You can use GoReleaser with GitHub Enterprise by providing its URLs in
the .goreleaser.yml
configuration file:
# .goreleaser.yml
github_urls:
api: https://git.company.com/api/v3/
upload: https://git.company.com/api/uploads/
download: https://git.company.com/
# set to true if you use a self-signed certificate
skip_tls_verify: false
If none are set, they default to GitHub’s public URLs.
You can use GoReleaser with GitLab Enterprise by providing its URLs in
the .goreleaser.yml
configuration file:
# .goreleaser.yml
gitlab_urls:
api: https://gitlab.mycompany.com/api/v4/
download: https://gitlab.company.com
# set to true if you use a self-signed certificate
skip_tls_verify: false
If none are set, they default to GitLab’s public URLs.
You can use GoReleaser with Gitea by providing its URLs in
the .goreleaser.yml
configuration file:
# .goreleaser.yml
gitea_urls:
api: https://gitea.myinstance.com/api/v1/
# set to true if you use a self-signed certificate
skip_tls_verify: false
By default, GoReleaser will create its artifacts in the ./dist
folder.
If you must, you can change it by setting it in the .goreleaser.yml
file:
# .goreleaser.yml
dist: another-folder-that-is-not-dist
main.version
Default wise GoReleaser sets three ldflags:
main.version
: Current Git tag (the v
prefix is stripped) or the name of
the snapshot, if you’re using the --snapshot
flagmain.commit
: Current git commit SHAmain.date
: Date according RFC3339You can use it in your main.go
file:
package main
import "fmt"
var (
version = "dev"
commit = "none"
date = "unknown"
)
func main() {
fmt.Printf("%v, commit %v, built at %v", version, commit, date)
}
You can override this by changing the ldflags
option in the build
section.
GoReleaser provides multiple customizations via the .goreleaser.yml
file.
You can generate it by running goreleaser init
or start from scratch.
The defaults are sensible and fit for most projects.
GoReleaser was built from the very first commit with the idea of running it as part of the CI pipeline in mind.
Let’s see how we can get it working on popular CI software.
You may want to setup your project to auto-deploy your new tags on Travis, for example:
# .travis.yml
language: go
addons:
apt:
packages:
# needed for the nfpm pipe:
- rpm
# needed for the snap pipe:
- snapd
env:
# needed for the snap pipe:
- PATH=/snap/bin:$PATH
install:
# needed for the snap pipe:
- sudo snap install snapcraft --classic
# needed for the docker pipe
services:
- docker
after_success:
# docker login is required if you want to push docker images.
# DOCKER_PASSWORD should be a secret in your .travis.yml configuration.
- test -n "$TRAVIS_TAG" && docker login -u=myuser -p="$DOCKER_PASSWORD"
# snapcraft login is required if you want to push snapcraft packages to the
# store.
# You'll need to run `snapcraft export-login snap.login` and
# `travis encrypt-file snap.login --add` to add the key to the travis
# environment.
- test -n "$TRAVIS_TAG" && snapcraft login --with snap.login
# calls goreleaser
deploy:
- provider: script
skip_cleanup: true
script: curl -sL https://git.io/goreleaser | bash
on:
tags: true
condition: $TRAVIS_OS_NAME = linux
Note the last line (condition: $TRAVIS_OS_NAME = linux
): it is important
if you run a build matrix with multiple Go versions and/or multiple OSes. If
that’s the case you will want to make sure GoReleaser is run just once.
Here is how to do it with CircleCI 2.0:
# .circleci/config.yml
version: 2
jobs:
release:
docker:
- image: circleci/golang:1.10
steps:
- checkout
- run: curl -sL https://git.io/goreleaser | bash
workflows:
version: 2
release:
jobs:
- release:
filters:
branches:
ignore: /.*/
tags:
only: /v[0-9]+(\.[0-9]+)*(-.*)*/
By default, drone does not fetch tags. plugins/git
is used with default values,
in most cases we’ll need overwrite the clone
step enabling tags in order to make
goreleaser
work correctly.
In this example we’re creating a new release every time a new tag is pushed.
Note that you’ll need to enable tags
in repo settings and add github_token
secret.
# .drone.yml
kind: pipeline
name: default
steps:
- name: fetch
image: docker:git
commands:
- git fetch --tags
- name: test
image: golang
volumes:
- name: deps
path: /go
commands:
- go test -race -v ./... -cover
- name: release
image: golang
environment:
GITHUB_TOKEN:
from_secret: github_token
volumes:
- name: deps
path: /go
commands:
- curl -sL https://git.io/goreleaser | bash
when:
event: tag
volumes:
- name: deps
temp: {}
pipeline:
clone:
image: plugins/git
tags: true
test:
image: golang:1.10
commands:
- go test ./... -race
release:
image: golang:1.10
secrets: [github_token]
commands:
curl -sL https://git.io/goreleaser | bash
when:
event: tag
CloudBuild works off a different clone than your github repo: it seems that your changes are pulled to a repo like source.developers.google.com/p/YourProjectId/r/github-YourGithubUser-YourGithubRepo, and that’s what you’re building off.
This repo has the wrong name, so to prevent Goreleaser from publishing to
the wrong github repo, add to your .goreleaser.yml
file’s release section:
release:
github:
owner: YourGithubUser
name: YourGithubRepo
Create two build triggers:
The push to any branch trigger could use a Dockerfile or a cloudbuild.yaml, whichever you prefer.
You should have a dedicated cloudbuild.release.yaml that is only used by the “push to tag” trigger.
In this example we’re creating a new release every time a new tag is pushed. See Using Encrypted Resources for how to encrypt and base64-encode your github token.
The clone that the build uses has no tags, which is why we must explicitly run git tag $TAG_NAME (note that $TAG_NAME is only set when your build is triggered by a “push to tag”.) This will allow goreleaser to create a release with that version, but it won’t be able to build a proper changelog containing just the messages from the commits since the prior tag. Note that the build performs a shallow clone of git repositories and will only contain tags that reference the latest commit.
steps:
# Setup the workspace so we have a viable place to point GOPATH at.
- name: gcr.io/cloud-builders/go
env: ['PROJECT_ROOT=github.com/YourGithubUser/YourGithubRepo']
args: ['env']
# Create github release.
- name: goreleaser/goreleaser
entrypoint: /bin/sh
dir: gopath/src/github.com
env: ['GOPATH=/workspace/gopath']
args: ['-c', 'cd YourGithubUser/YourGithubRepo && git tag $TAG_NAME && /goreleaser' ]
secretEnv: ['GITHUB_TOKEN']
secrets:
- kmsKeyName: projects/YourProjectId/locations/global/keyRings/YourKeyRing/cryptoKeys/YourKey
secretEnv:
GITHUB_TOKEN: |
ICAgICAgICBDaVFBZUhVdUVoRUtBdmZJSGxVWnJDZ0hOU2NtMG1ES0k4WjF3L04zT3pEazhRbDZr
QVVTVVFEM3dVYXU3cVJjK0g3T25UVW82YjJaCiAgICAgICAgREtBMWVNS0hOZzcyOUtmSGoyWk1x
ICAgICAgIEgwYndIaGUxR1E9PQo=
In Sempahore 2.0 each project starts with the default pipeline specified in .semaphore/semaphore.yml.
# .semaphore/semaphore.yml.
version: v1.0
name: Build
agent:
machine:
type: e1-standard-2
os_image: ubuntu1804
blocks:
- name: "Test"
task:
prologue:
commands:
# set go version
- sem-version go 1.11
- "export GOPATH=~/go"
- "export PATH=/home/semaphore/go/bin:$PATH"
- checkout
jobs:
- name: "Lint"
commands:
- go get ./...
- go test ./...
# On Semaphore 2.0 deployment and delivery is managed with promotions,
# which may be automatic or manual and optionally depend on conditions.
promotions:
- name: Release
pipeline_file: goreleaser.yml
auto_promote_on:
- result: passed
branch:
- "^refs/tags/v*"
Pipeline file in .semaphore/goreleaser.yml:
version: "v1.0"
name: GoReleaser
agent:
machine:
type: e1-standard-2
os_image: ubuntu1804
blocks:
- name: "Release"
task:
secrets:
- name: goreleaser
prologue:
commands:
- sem-version go 1.11
- "export GOPATH=~/go"
- "export PATH=/home/semaphore/go/bin:$PATH"
- checkout
jobs:
- name: goreleaser
commands:
- curl -sL https://git.io/goreleaser | bash
The following YAML file, createSecret.yml
creates a new secret item that is called goreleaser
with one environment variable, named GITHUB_TOKEN:
apiVersion: v1alpha
kind: Secret
metadata:
name: goreleaser
data:
env_vars:
- name: GITHUB_TOKEN
value: "4afk4388304hfhei34950dg43245"
Check Managing Secrets for more detailed documentation.
To push releases to both GitHub and the official Docker registry, add a file .gitlab-ci.yml
in the Go project directory:
image: docker:stable
services:
- docker:dind
stages:
- build
variables:
GORELEASER_IMAGE: goreleaser/goreleaser:latest
DOCKER_REGISTRY: https://index.docker.io/v1/
build:
stage: build
script:
- docker pull $GORELEASER_IMAGE
- docker run --rm --privileged -v $PWD:/go/src/github.com/YourGithubUser/YourGithubRepo -v /var/run/docker.sock:/var/run/docker.sock -w /go/src/github.com/YourGithubUser/YourGithubRepo -e GITHUB_TOKEN -e DOCKER_USERNAME -e DOCKER_PASSWORD -e DOCKER_REGISTRY $GORELEASER_IMAGE release --rm-dist
Next, in the GitLab sidebar add the variables DOCKER_USERNAME
, DOCKER_PASSWORD
and GITHUB_TOKEN
through Project –> Settings –> CI / CD –> Variables.
Make sure they are set to Masked (Protection is not needed).
To push to some other Docker registry (e.g. to a GitLab registry), set different variables in the file above:
CI_REGISTRY: gitlab.example.com:4567
DOCKER_REGISTRY: $CI_REGISTRY
DOCKER_USERNAME: gitlab-ci-token
DOCKER_PASSWORD: $CI_JOB_TOKEN
Make sure the image_templates
in the file .goreleaser.yml
reflect that custom registry!
Example:
dockers:
-
goos: linux
goarch: amd64
binaries:
- program
image_templates:
- 'gitlab.example.com:4567/Group/Project:{{ .Tag }}'
- 'gitlab.example.com:4567/Group/Project:latest'
Codefresh uses Docker based pipelines where all steps must be Docker containers. Using Goreleaser is very easy via the existing Docker image.
Here is an example pipeline that builds a Go application and then uses Goreleaser.
version: '1.0'
stages:
- prepare
- build
- release
steps:
main_clone:
title: 'Cloning main repository...'
type: git-clone
repo: '${{CF_REPO_OWNER}}/${{CF_REPO_NAME}}'
revision: '${{CF_REVISION}}'
stage: prepare
BuildMyApp:
title: Compiling go code
stage: build
image: 'golang:1.13'
commands:
- go build
ReleaseMyApp:
title: Creating packages
stage: release
image: 'goreleaser/goreleaser'
commands:
- goreleaser --rm-dist
You need to pass the variable GITHUB_TOKEN
in the Codefresh UI that contains credentials to your Github account or load it from shared configuration.
You should also restrict this pipeline to run only on tags when you add git triggers on it.
More details can be found in the goreleaser example page.
GoReleaser can also be used within our official GoReleaser Action through GitHub Actions.
You can create a workflow for pushing your releases by putting YAML configuration to .github/workflows/release.yml
.
Below is a simple snippet to use this action in your workflow:
name: goreleaser
on:
pull_request:
push:
jobs:
goreleaser:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v1
-
name: Set up Go
uses: actions/setup-go@v1
-
name: Run GoReleaser
uses: goreleaser/goreleaser-action@v1
with:
version: latest
args: release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
For detailed intructions please follow GitHub Actions workflow syntax.
Following inputs can be used as step.with
keys
Name | Type | Default | Description |
---|---|---|---|
version |
String | latest |
GoReleaser version. Example: v0.117.0 |
args |
String | Arguments to pass to GoReleaser | |
key |
String | Private key to import |
If signing is enabled in your GoReleaser configuration, populate the
key
input with your private key and reference the key in your signing
configuration, e.g.
signs:
- artifacts: checksum
args: ["--batch", "-u", "<key id, fingerprint, email, ...>", "--output", "${signature}", "--detach-sign", "${artifact}"]
This feature is currently only compatible when using the default gpg
command and a private key without a passphrase.
Does your company use goreleaser? Help keep the project bug-free and feature rich by sponsoring the project.
Love our work and community? Become a backer.
This page will eventually have information for those who want to contribute to the project.
Also check the CONTRIBUTING.md file on the root of our repository.
Tutorials made by the community.
Want to add your tutorial here? Please do! Click on the improve this page
link bellow!
This project adheres to the Contributor Covenant code of conduct. By participating, you are expected to uphold this code.