Customization

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.

Table of Contents:

Project Name

The project name is used in the name of the Brew formula, archives, etc. If none is given, it will be inferred from the name of the Git project.

# .goreleaser.yml
project_name: myproject

Environment Variables

Global environment variables to be passed down to all hooks and builds.

This is useful for GO111MODULE, for example. You can have your .goreleaser.yaml file like the following:

# .goreleaser.yml
env:
  - GO111MODULE=on
before:
  hooks:
    - go mod download
builds:
- binary: program

This way, both go mod download and the underlying go build will have GO111MODULE set to on.

Global Hooks

Some builds may need pre-build steps before building, e.g. go generate. The before section allows for global hooks which will be executed before the build is started.

The configuration is very simple, here is a complete example:

# .goreleaser.yml
before:
  # Templates for the commands to be ran.
  hooks:
  - make clean
  - go generate ./...
  - go mod download
  - touch {{ .Env.FILE_TO_TOUCH }}

If any of the hooks fails the build process is aborted.

It is important to note that you can’t have “complex” commands, like bash -c "echo foo bar" or foo | bar or anything like that. If you need to do things that are more complex than just calling a command with some attributes, wrap it in a shell script or into your Makefile.

Learn more about the name template engine.

Name Templates

Several fields in GoReleaser’s config file support templating.

Those fields are often suffixed with _template, but sometimes they may not be. The documentation of each section should explicit in which fields templating is available.

On fields that support templating, this fields are always available:

Key Description
.ProjectName the project name
.Version the version being released (v prefix stripped)
.Tag the current git tag
.ShortCommit the git commit short hash
.FullCommit the git commit full hash
.Commit the git commit hash (deprecated)
.GitURL the git remote url
.Major the major part of the version
.Minor the minor part of the version
.Patch the patch part of the version
.Env a map with system’s environment variables
.Date current UTC date in RFC3339 format
.Timestamp current UTC time in Unix format

On fields that are related to a single artifact (e.g., the binary name), you may have some extra fields:

Key Description
.Os GOOS (usually allow replacements)
.Arch GOARCH (usually allow replacements)
.Arm GOARM (usually allow replacements)
.Binary Binary name
.ArtifactName Archive name

On all fields, you have these available functions:

Usage Description
time "01/02/2006" current UTC time in the specified format

With all those fields, you may be able to compose the name of your artifacts pretty much the way you want:

example_template: '{{ .ProjectName }}_{{ .Env.USER }}_{{ time "2006" }}'

For example, if you want to add the go version to some artifact:

foo_template: 'foo_{{ .Env.GOVERSION }}'

And then you can run:

GOVERSION_NR=$(go version | awk '{print $3;}') goreleaser

Note that those are hypothetical examples and the fields foo_template and example_template are not valid GoReleaser configurations.

Builds

Builds can be customized in multiple ways. You can specify for which GOOS, GOARCH and GOARM binaries are built (goreleaser will generate a matrix of all combinations), and you can changed the name of the binary, flags, environment variables, hooks and etc.

Here is a commented builds section with all fields specified:

# .goreleaser.yml
builds:
  # You can have multiple builds defined as a yaml list
  -
    # ID of the build.
    # Defaults to the project name.
    id: "my-build"

    # Path to main.go file or main package.
    # Default is `.`.
    main: ./cmd/main.go

    # Binary name.
    # Can be a path (e.g. `bin/app`) to wrap the binary in a directory.
    # Default is the name of the project directory.
    binary: program

    # Custom flags templates.
    # Default is empty.
    flags:
      - -tags=dev
      - -v

    # Custom asmflags templates.
    # Default is empty.
    asmflags:
      - -D mysymbol
      - all=-trimpath={{.Env.GOPATH}}

    # Custom gcflags templates.
    # Default is empty.
    gcflags:
      - all=-trimpath={{.Env.GOPATH}}
      - ./dontoptimizeme=-N

    # Custom ldflags templates.
    # Default is `-s -w -X main.version={{.Version}} -X main.commit={{.ShortCommit}} -X main.date={{.Date}} -X main.builtBy=goreleaser`.
    ldflags:
     - -s -w -X main.build={{.Version}}
     - ./usemsan=-msan

    # Custom environment variables to be set during the builds.
    # Default is empty.
    env:
      - CGO_ENABLED=0

    # GOOS list to build for.
    # For more info refer to: https://golang.org/doc/install/source#environment
    # Defaults are darwin and linux.
    goos:
      - freebsd
      - windows

    # GOARCH to build for.
    # For more info refer to: https://golang.org/doc/install/source#environment
    # Defaults are 386 and amd64.
    goarch:
      - amd64
      - arm
      - arm64

    # GOARM to build for when GOARCH is arm.
    # For more info refer to: https://golang.org/doc/install/source#environment
    # Default is only 6.
    goarm:
      - 6
      - 7

    # List of combinations of GOOS + GOARCH + GOARM to ignore.
    # Default is empty.
    ignore:
      - goos: darwin
        goarch: 386
      - goos: linux
        goarch: arm
        goarm: 7

    # Hooks can be used to customize the final binary,
    # for example, to run generators.
    # Those fields allow templates.
    # Default is both hooks empty.
    hooks:
      pre: rice embed-go
      post: ./script.sh

Learn more about the name template engine.

Passing environment variables to ldflags

You can do that by using {{ .Env.VARIABLE_NAME }} in the template, for example:

builds:
  - ldflags:
   - -s -w -X "main.goversion={{.Env.GOVERSION}}"

Then you can run:

GOVERSION=$(go version) goreleaser

Go Modules

If you use Go 1.11+ with go modules or vgo, when GoReleaser runs it may try to download the dependencies. Since several builds run in parallel, it is very likely to fail.

You can solve this by running go mod download before calling goreleaser or by adding a hook doing that on your .goreleaser.yaml file:

 before:
   hooks:
   - go mod download
 # rest of the file...

Archive

The binaries built will be archived together with the README and LICENSE files into a tar.gz file. In the archives section you can customize the archive name, additional files, and format.

Here is a commented archives section with all fields specified:

# .goreleaser.yml
archives:
  -
    # ID of this archive.
    # Defaults to `default`.
    id: my-archive

    # Builds reference which build instances should be archived in this archive.
    builds:
    - default

    # Archive name template.
    # Defaults:
    # - if format is `tar.gz`, `gz` or `zip`:
    #   - `{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}`
    # - if format is `binary`:
    #   - `{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}`
    name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"

    # Replacements for GOOS and GOARCH in the archive name.
    # Keys should be valid GOOSs or GOARCHs.
    # Values are the respective replacements.
    # Default is empty.
    replacements:
      amd64: 64-bit
      386: 32-bit
      darwin: macOS
      linux: Tux

    # Set to true, if you want all files in the archive to be in a single directory.
    # If set to true and you extract the archive 'goreleaser_Linux_arm64.tar.gz',
    # you get a folder 'goreleaser_Linux_arm64'.
    # If set to false, all files are extracted separately.
    # You can also set it to a custom folder name (templating is supported).
    # Default is false.
    wrap_in_directory: true

    # Archive format. Valid options are `tar.gz`, `gz`, `zip` and `binary`.
    # If format is `binary`, no archives are created and the binaries are instead
    # uploaded directly.
    # Default is `tar.gz`.
    format: zip

    # Can be used to change the archive formats for specific GOOSs.
    # Most common use case is to archive as zip on Windows.
    # Default is empty.
    format_overrides:
      - goos: windows
        format: zip

    # Additional files/globs you want to add to the archive.
    # Defaults are any files matching `LICENCE*`, `LICENSE*`,
    # `README*` and `CHANGELOG*` (case-insensitive).
    files:
      - LICENSE.txt
      - README.md
      - CHANGELOG.md
      - docs/*
      - design/*.png
      - templates/**/*

Learn more about the name template engine.

You can add entire folders, its subfolders and files by using the glob notation, for example: myfolder/**/*.

Packaging only the binaries

Since GoReleaser will always add the README and LICENSE files to the archive if the file list is empty, you’ll need to provide a filled files on the archive section.

A working hack is to use something like this:

# goreleaser.yml
archives:
- files:
  - none*

This would add all files matching the glob none*, provide that you don’t have any files matching that glob, only the binary will be added to the archive.

For more information, check #602

A note about Gzip

Gzip is a compression-only format, therefore, it couldn’t have more than one file inside.

Presumably, you’ll want that file to be the binary, so, your archive section will probably look like this:

# goreleaser.yml
archive:
  format: gz
  files:
  - none*

This should create .gz files with the binaries only, which should be extracted with something like gzip -d file.gz.

Multiple builds will also not work in this case and will be handled on #705.

Checksum

GoReleaser generates a project_1.0.0_checksums.txt file and uploads it with the release, so your users can validate if the downloaded files are correct.

The checksum section allows customizations of the filename:

# .goreleaser.yml
checksum:
  # You can change the name of the checksums file.
  # Default is `{{ .ProjectName }}_{{ .Version }}_checksums.txt`.
  name_template: "{{ .ProjectName }}_checksums.txt"

  # Algorithm to be used.
  # Accepted options are sha256, sha512, sha1, crc32, md5, sha224 and sha384.
  # Default is sha256.
  algorithm: sha256

Learn more about the name template engine.

Signing

GoReleaser can sign some or all of the generated artifacts. Signing ensures that the artifacts have been generated by yourself and your users can verify that by comparing the generated signature with your public signing key.

Signing works in combination with checksum files and it is generally sufficient to sign the checksum files only.

The default is configured to create a detached signature for the checksum files with GnuPG and your default key. To enable signing just add

# goreleaser.yml
signs:
  - artifacts: checksum

To customize the signing pipeline you can use the following options:

# .goreleaser.yml
signs:
  -
    # name of the signature file.
    # '${artifact}' is the path to the artifact that should be signed.
    #
    # defaults to `${artifact}.sig`
    signature: "${artifact}_sig"

    # path to the signature command
    #
    # defaults to `gpg`
    cmd: gpg2

    # command line arguments for the command
    #
    # to sign with a specific key use
    # args: ["-u", "<key id, fingerprint, email, ...>", "--output", "${signature}", "--detach-sign", "${artifact}"]
    #
    # defaults to `["--output", "${signature}", "--detach-sign", "${artifact}"]`
    args: ["--output", "${signature}", "${artifact}"]


    # which artifacts to sign
    #
    #   checksum: only checksum file(s)
    #   all:      all artifacts
    #   none:     no signing
    #
    # defaults to `none`
    artifacts: all

Snapshots

Sometimes we want to generate a full build of our project, but neither want to validate anything nor upload it to anywhere.

GoReleaser supports this with the --snapshot flag and also with the snapshot customization section:

# .goreleaser.yml
snapshot:
  # Allows you to change the name of the generated snapshot
  # Default is `SNAPSHOT-{{.ShortCommit}}`.
  name_template: SNAPSHOT-{{.Commit}}

Learn more about the name template engine.

Note that the idea behind GoReleaser’s snapshots if mostly for local builds or to validate your build on the CI pipeline. Artifacts shouldn’t be uploaded anywhere, and will only be generated to the dist folder.

NFPM

GoReleaser can be wired to nfpm to generate and publish .deb and .rpm packages.

Available options:

# .goreleaser.yml
nfpms:
  # note that this is an array of nfpm configs
  -
    # ID of the nfpm config, must be unique.
    # Defaults to "default".
    id: foo
    # You can change the name of the package.
    # Default: `{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}`
    name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"

    # Build IDs for the builds you want to create NFPM packages for.
    # Defaults to all builds.
    builds:
    - foo
    - bar

    # Replacements for GOOS and GOARCH in the package name.
    # Keys should be valid GOOSs or GOARCHs.
    # Values are the respective replacements.
    # Default is empty.
    replacements:
      amd64: 64-bit
      386: 32-bit
      darwin: macOS
      linux: Tux

    # Your app's vendor.
    # Default is empty.
    vendor: Drum Roll Inc.
    # Your app's homepage.
    # Default is empty.
    homepage: https://example.com/

    # Your app's maintainer (probably you).
    # Default is empty.
    maintainer: Drummer <[email protected]>

    # Your app's description.
    # Default is empty.
    description: Software to create fast and easy drum rolls.

    # Your app's license.
    # Default is empty.
    license: Apache 2.0

    # Formats to be generated.
    formats:
      - deb
      - rpm

    # Packages your package depends on.
    dependencies:
      - git
      - zsh

    # Packages your package recommends installing.
    # For RPM packages rpmbuild >= 4.13 is required
    recommends:
      - bzr
      - gtk

    # Packages your package suggests installing.
    # For RPM packages rpmbuild >= 4.13 is required
    suggests:
      - cvs
      - ksh

    # Packages that conflict with your package.
    conflicts:
      - svn
      - bash

    # Override default /usr/local/bin destination for binaries
    bindir: /usr/bin

    # Package epoch.
    # Defaults to empty.
    epoch: 1

    # Empty folders that should be created and managed by the packager
    # implementation.
    # Default is empty.
    empty_folders:
    - /var/log/foobar

    # Files or directories to add to your package (beyond the binary).
    # Keys are source paths/globs to get the files from.
    # Values are the destination locations of the files in the package.
    files:
      "scripts/etc/init.d/": "/etc/init.d"
      "path/**/glob": "/var/foo/glob"

    # Config files to add to your package. They are about the same as
    # the files keyword, except package managers treat them differently (while
    # uninstalling, mostly).
    # Keys are source paths/globs to get the files from.
    # Values are the destination locations of the files in the package.
    config_files:
      "tmp/app_generated.conf": "/etc/app.conf"
      "conf/*.conf": "/etc/foo/"

    # Scripts to execute during the installation of the package.
    # Keys are the possible targets during the installation process
    # Values are the paths to the scripts which will be executed
    scripts:
      preinstall: "scripts/preinstall.sh"
      postinstall: "scripts/postinstall.sh"
      preremove: "scripts/preremove.sh"
      postremove: "scripts/postremove.sh"

    # Some attributes can be overrided per package format.
    overrides:
      deb:
        conflicts:
          - subversion
        dependencies:
          - git
        suggests:
          - gitk
        recommends:
          - tig
        empty_folders:
        - /var/log/bar
      rpm:
        replacements:
          amd64: x86_64
        name_template: "{{ .ProjectName }}-{{ .Version }}-{{ .Arch }}"
        files:
          "tmp/man.gz": "/usr/share/man/man8/app.8.gz"
        config_files:
          "tmp/app_generated.conf": "/etc/app-rpm.conf"
        scripts:
          preinstall: "scripts/preinstall-rpm.sh"

Learn more about the name template engine.

Note that GoReleaser will not install rpmbuild or any dependencies for you. As for now, rpmbuild is recommended if you want to generate rpm packages. You can install it with apt-get install rpm or brew install rpm.

Snapcraft

GoReleaser can also generate snap packages. Snaps are a new packaging format, that will let you publish your project directly to the Ubuntu store. From there it will be installable in all the supported Linux distros, with automatic and transactional updates.

You can read more about it in the snapcraft docs.

Available options:

# .goreleaser.yml
snapcrafts:
  -
    # ID of the snapcraft config, must be unique.
    # Defaults to "default".
    id: foo

    # Build IDs for the builds you want to create snapcraft packages for.
    # Defaults to all builds.
    builds:
    - foo
    - bar

    # You can change the name of the package.
    # Default: `{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}`
    name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"

    # Replacements for GOOS and GOARCH in the package name.
    # Keys should be valid GOOSs or GOARCHs.
    # Values are the respective replacements.
    # Default is empty.
    replacements:
      amd64: 64-bit
      386: 32-bit
      darwin: macOS
      linux: Tux

    # The name of the snap. This is optional.
    # Default is project name.
    name: drumroll

    # Wether to publish the snap to the snapcraft store.
    # Remember you need to `snapcraft login` first.
    # Defaults to false.
    publish: true

    # Single-line elevator pitch for your amazing snap.
    # 79 char long at most.
    summary: Software to create fast and easy drum rolls.

    # This the description of your snap. You have a paragraph or two to tell the
    # most important story about your snap. Keep it under 100 words though,
    # we live in tweetspace and your description wants to look good in the snap
    # store.
    description: This is the best drum roll application out there. Install it and awe!

    # A guardrail to prevent you from releasing a snap to all your users before
    # it is ready.
    # `devel` will let you release only to the `edge` and `beta` channels in the
    # store. `stable` will let you release also to the `candidate` and `stable`
    # channels. More info about channels here:
    # https://snapcraft.io/docs/reference/channels
    grade: stable

    # Snaps can be setup to follow three different confinement policies:
    # `strict`, `devmode` and `classic`. A strict confinement where the snap
    # can only read and write in its own namespace is recommended. Extra
    # permissions for strict snaps can be declared as `plugs` for the app, which
    # are explained later. More info about confinement here:
    # https://snapcraft.io/docs/reference/confinement
    confinement: strict

    # Your app's license, based on SPDX license expressions: https://spdx.org/licenses
    # Default is empty.
    license: MIT

    # A snap of type base to be used as the execution environment for this snap.
    # Valid values are:
    # * bare - Empty base snap;
    # * core - Ubuntu Core 16;
    # * core18 - Ubuntu Core 18.
    # Default is empty.
    base: core18

    # Each binary built by GoReleaser is an app inside the snap. In this section
    # you can declare extra details for those binaries. It is optional.
    apps:

      # The name of the app must be the same name as the binary built or the snapcraft name.
      drumroll:

        # If your app requires extra permissions to work outside of its default
        # confined space, declare them here.
        # You can read the documentation about the available plugs and the
        # things they allow:
        # https://snapcraft.io/docs/reference/interfaces.
        plugs: ["home", "network", "personal-files"]

        # If you want your app to be autostarted and to always run in the
        # background, you can make it a simple daemon.
        daemon: simple

        # If you any to pass args to your binary, you can add them with the
        # args option.
        args: --foo

        # Bash completion snippet. More information about completion here:
        # https://docs.snapcraft.io/tab-completion-for-snaps.
        completer: drumroll-completion.bash

    # Allows plugs to be configured. Plugs like system-files and personal-files
    # require this.
    # Default is empty.
    plugs:
      personal-files:
        read:
        - $HOME/.foo
        write:
        - $HOME/.foo
        - $HOME/.foobar

Learn more about the name template engine.

Note that GoReleaser will not install snapcraft nor any of its dependencies for you.

Homebrew

After releasing to GitHub or GitLab, GoReleaser can generate and publish a homebrew-tap recipe into a repository that you have access to.

The brew section specifies how the formula should be created. You can check the Homebrew documentation and the formula cookbook for more details.

# .goreleaser.yml
brews:
  -
    # Name template of the recipe
    # Default to project name
    name: myproject

    # IDs of the archives to use.
    # Defaults to all.
    ids:
    - foo
    - bar


    # NOTE: make sure the url_template, the token and given repo (github or gitlab) owner and name are from the
    # same kind. We will probably unify this in the next major version like it is done with scoop.

    # Github repository to push the tap to.
    github:
      owner: github-user
      name: homebrew-tap

    # OR Gitlab
    # gitlab:
    #   owner: gitlab-user
    #   name: homebrew-tap

    # Template for the url which is determined by the given Token (github or gitlab)
    # Default for github is "https://github.com/<repo_owner>/<repo_name>/releases/download/{{ .Tag }}/{{ .ArtifactName }}"
    # Default for gitlab is "https://gitlab.com/<repo_owner>/<repo_name>/uploads/{{ .ArtifactUploadHash }}/{{ .ArtifactName }}"
    url_template: "http://github.mycompany.com/foo/bar/releases/{{ .Tag }}/{{ .ArtifactName }}"

    # Allows you to set a custom download strategy.
    # Default is empty.
    download_strategy: GitHubPrivateRepositoryReleaseDownloadStrategy

    # Allows you to add a custom require_relative at the top of the formula template
    # Default is empty
    custom_require: custom_download_strategy

    # Git author used to commit to the repository.
    # Defaults are shown.
    commit_author:
      name: goreleaserbot
      email: [email protected]

    # Folder inside the repository to put the formula.
    # Default is the root folder.
    folder: Formula

    # Caveats for the user of your binary.
    # Default is empty.
    caveats: "How to use this binary"

    # Your app's homepage.
    # Default is empty.
    homepage: "https://example.com/"

    # Your app's description.
    # Default is empty.
    description: "Software to create fast and easy drum rolls."

    # Setting this will prevent goreleaser to actually try to commit the updated
    # formula - instead, the formula file will be stored on the dist folder only,
    # leaving the responsibility of publishing it to the user.
    # If set to auto, the release will not be uploaded to the homebrew tap
    # in case there is an indicator for prerelease in the tag e.g. v1.0.0-rc1
    # Default is false.
    skip_upload: true

    # Custom block for brew.
    # Can be used to specify alternate downloads for devel or head releases.
    # Default is empty.
    custom_block: |
      head "https://github.com/some/package.git"
      ...

    # Packages your package depends on.
    dependencies:
      - git
      - zsh

    # Packages that conflict with your package.
    conflicts:
      - svn
      - bash

    # Specify for packages that run as a service.
    # Default is empty.
    plist: |
      <?xml version="1.0" encoding="UTF-8"?>
      ...

    # So you can `brew test` your formula.
    # Default is empty.
    test: |
      system "#{bin}/program --version"
      ...

    # Custom install script for brew.
    # Default is 'bin.install "program"'.
    install: |
      bin.install "program"
      ...

Learn more about the name template engine.

By defining the brew section, GoReleaser will take care of publishing the Homebrew tap. Assuming that the current tag is v1.2.3, the above configuration will generate a program.rb formula in the Formula folder of user/homebrew-tap repository:

class Program < Formula
  desc "How to use this binary"
  homepage "https://github.com/user/repo"
  version "v1.2.3"

  if os.Mac?
    url "https://github.com/user/repo/releases/download/v1.2.3/program_v1.2.3_macOs_64bit.zip"
    sha256 "9ee30fc358fae8d248a2d7538957089885da321dca3f09e3296fe2058e7fff74"
  elsif os.Linux?
    url "https://github.com/user/repo/releases/download/v1.2.3/program_v1.2.3_Linux_64bit.zip"
    sha256 "b41bebd25fd7bb1a67dc2cd5ee12c9f67073094567fdf7b3871f05fd74a45fdd"
  end

  depends_on "git"
  depends_on "zsh"

  def install
    bin.install "program"
  end
end

Important: Note that GoReleaser does not generate a valid homebrew-core formula. The generated formulas are meant to be published as homebrew taps, and in their current form will not be accepted in any of the official homebrew repositories.

Scoop

After releasing to GitHub or GitLab, GoReleaser can generate and publish a Scoop App Manifest into a repository that you have access to.

The scoop section specifies how the manifest should be created. See the commented example bellow:

# .goreleaser.yml
scoop:
  # Template for the url which is determined by the given Token (github or gitlab)
  # Default for github is "https://github.com/<repo_owner>/<repo_name>/releases/download/{{ .Tag }}/{{ .ArtifactName }}"
  # Default for gitlab is "https://gitlab.com/<repo_owner>/<repo_name>/uploads/{{ .ArtifactUploadHash }}/{{ .ArtifactName }}"
  url_template: "http://github.mycompany.com/foo/bar/releases/{{ .Tag }}/{{ .ArtifactName }}"

  # Repository to push the app manifest to.
  bucket:
    owner: user
    name: scoop-bucket

  # Git author used to commit to the repository.
  # Defaults are shown.
  commit_author:
    name: goreleaserbot
    email: [email protected]

  # Your app's homepage.
  # Default is empty.
  homepage: "https://example.com/"

  # Your app's description.
  # Default is empty.
  description: "Software to create fast and easy drum rolls."

  # Your app's license
  # Default is empty.
  license: MIT

  # Persist data between application updates
  persist:
  - "data"
  - "config.toml"

By defining the scoop section, GoReleaser will take care of publishing the Scoop app. Assuming that the project name is drumroll and the current tag is v1.2.3, the above configuration will generate a drumroll.json manifest in the root of the repository specified in the bucket section.

{
  "version": "1.2.3",
  "architecture": {
    "64bit": {
      "url":
        "https://github.com/user/drumroll/releases/download/1.2.3/drumroll_1.2.3_windows_amd64.tar.gz",
      "bin": "drumroll.exe",
      "hash": "86920b1f04173ee08773136df31305c0dae2c9927248ac259e02aafd92b6008a"
    },
    "32bit": {
      "url":
        "https://github.com/user/drumroll/releases/download/1.2.3/drumroll_1.2.3_windows_386.tar.gz",
      "bin": "drumroll.exe",
      "hash": "283faa524ef41987e51c8786c61bb56658a489f63512b32139d222b3ee1d18e6"
    }
  },
  "homepage": "https://example.com/"
}

Your users can then install your app by doing:

scoop bucket add app https://github.com/org/repo.git
scoop install app

You can check the Scoop documentation for more details.

Release

GoReleaser will create a GitHub/GitLab release with the current tag, upload all the artifacts and generate the changelog based on the new commits since the previous tag.

Let’s see what can be customized in the release section for GitHub:

# .goreleaser.yml
release:
  # Repo in which the release will be created.
  # Default is extracted from the origin remote URL.
  # Note: it can only be one: either github or gitlab
  github:
    owner: user
    name: repo

  # If set to true, will not auto-publish the release.
  # Default is false.
  draft: true

  # If set to auto, will mark the release as not ready for production
  # in case there is an indicator for this in the tag e.g. v1.0.0-rc1
  # If set to true, will mark the release as not ready for production.
  # Default is false.
  prerelease: auto

  # You can change the name of the GitHub release.
  # Default is `{{.Tag}}`
  name_template: "{{.ProjectName}}-v{{.Version}} {{.Env.USER}}"

  # You can disable this pipe in order to not upload any artifacts to
  # GitHub.
  # Defaults to false.
  disable: true

Second, let’s see what can be customized in the release section for GitLab. Note that only GitLab v11.7+ are supported for releases:

# .goreleaser.yml
release:
  # Same as for github
  # Note: it can only be one: either github or gitlab
  gitlab:
    owner: user
    name: repo

  # You can change the name of the GitLab release.
  # Default is `{{.Tag}}`
  name_template: "{{.ProjectName}}-v{{.Version}} {{.Env.USER}}"

  # You can disable this pipe in order to not upload any artifacts to
  # GitLab.
  # Defaults to false.
  disable: true

Note: draft and prerelease is only supported by GitHub.

Learn more about the name template engine.

Customize the changelog

You can customize how the changelog is generated using the changelog section in the config file:

# .goreleaser.yml
changelog:
  # set it to true if you wish to skip the changelog generation
  skip: true
  # could either be asc, desc or empty
  # Default is empty
  sort: asc
  filters:
    # commit messages matching the regexp listed here will be removed from
    # the changelog
    # Default is empty
    exclude:
      - '^docs:'
      - typo
      - (?i)foo

Custom release notes

You can specify a file containing your custom release notes, and pass it with the --release-notes=FILE flag. GoReleaser will then skip its own release notes generation, using the contents of your file instead. You can use Markdown to format the contents of your file.

On Unix systems you can also generate the release notes in-line by using process substitution. To list all commits since the last tag, but skip ones starting with Merge or docs, you could run this command:

$ goreleaser --release-notes <(some_changelog_generator)

Some changelog generators you can use:

Important: If you create the release before running GoReleaser, and the said release has some text in its body, GoReleaser will not override it with it’s release notes.

S3

Since v0.74.0, GoReleaser supports pushing artifacts to Amazon S3 and other API-compatible object storages (minio for example).

Right now, the implementation is quite simple and probably won’t cover all use cases. If you need one of such use cases, please open an issue/pull request.

Here is what you can customize:

Customization

# .goreleaser.yml
s3:
  # You can have multiple s3 configs
  -
    # Template for the bucket name(without the s3:// prefix)
    # Default is empty.
    bucket: my-bucket

    # IDs of the artifacts you want to upload.
    ids:
    - foo
    - bar

    # AWS Region to use.
    # Defaults is us-east-1
    region: us-east-1

    # Template for the path/name inside the bucket.
    # Default is `{{ .ProjectName }}/{{ .Tag }}`
    folder: "foo/bar/{{.Version}}"

    # Set a custom profile to use for this s3 config. If you have multiple
    # profiles setup in you ~/.aws config, this shall help defining which
    # profile to use in which s3 bucket.
    # Default is empty.
    profile: my-profile

    # Endpoint allows you to set a custom endpoint, which is useful if you
    # want to push your artifacts to a minio server for example.
    # Default is AWS S3 URL.
    endpoint: "http://minio.foo.com"

    # Sets the ACL of the object using the specified canned ACL.
    # Default is private.
    acl: public-read

Learn more about the name template engine. Learn more about the acl.

Authentication

GoReleaser will authenticate using the same methods defined by aws-cli. You can read the docs to find out more about it.

Currently it supports authentication with:

  • An EnvProvider which retrieves credentials from the environment variables of the running process. Environment credentials never expire. Environment variables used:
    • Access Key ID: AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY
    • Secret Access Key: AWS_SECRET_ACCESS_KEY or AWS_SECRET_KEY
  • A SharedCredentialsProvider which retrieves credentials from the current user’s home directory, and keeps track if those credentials are expired. Profile ini file example: $HOME/.aws/credentials
  • A AssumeRoleTokenProvider with enabled SharedConfigState which uses MFA prompting for token code on stdin. Go to session doc for more details.

You can also set different profile names for each S3 config, so you may be able to push to buckets in different accounts, for example.

Artifactory

Since v0.38.0, GoReleaser supports building and pushing artifacts into Artifactory.

How it works

You can declare multiple Artifactory instances. All binaries generated by your builds section will be pushed to each configured Artifactory.

If you have only one Artifactory instance, the configuration is as easy as adding the upload target and a username to your .goreleaser.yml file:

artifactories:
  - name: production
    target: http://<Your-Instance>:8081/artifactory/example-repo-local/{{ .ProjectName }}/{{ .Version }}/
    username: goreleaser

Prerequisites:

  • A running Artifactory instances
  • A user + password / API key with grants to upload an artifact

Target

The target is the URL to upload the artifacts to (without the name of the artifact).

An example configuration for goreleaser in upload mode binary with the target can look like

- mode: binary
  target: 'http://artifacts.company.com:8081/artifactory/example-repo-local/{{ .ProjectName }}/{{ .Version }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}{{ .Arm }}{{ end }}'

and will result in a final deployment like http://artifacts.company.com:8081/artifactory/example-repo-local/goreleaser/1.0.0/Darwin/x86_64/goreleaser.

Supported variables:

  • Version
  • Tag
  • ProjectName
  • Os
  • Arch
  • Arm

Attention: Variables Os, Arch and Arm are only supported in upload mode binary.

Username

Your configured username needs to be authenticated against your Artifactory.

You can have the username set in the configuration file as shown above or you can have it read from an environment variable. The configured name of your Artifactory instance will be used to build the environment variable name. This way we support auth for multiple instances. This also means that the name per configured instance needs to be unique per goreleaser configuration.

The name of the environment variable will be ARTIFACTORY_NAME_USERNAME. If your instance is named production, you can store the username in the environment variable ARTIFACTORY_PRODUCTION_USERNAME. The name will be transformed to uppercase.

If a configured username is found in the configuration file, then the environment variable is not used at all.

Password / API Key

The password or API key will be stored in a environment variable. The configured name of your Artifactory instance will be used. With this way we support auth for multiple instances. This also means that the name per configured instance needs to be unique per goreleaser configuration.

The name of the environment variable will be ARTIFACTORY_NAME_SECRET. If your instance is named production, you need to store the secret in the environment variable ARTIFACTORY_PRODUCTION_SECRET. The name will be transformed to uppercase.

Server authentication

You can authenticate your Artifactory TLS server adding a trusted X.509 certificate chain in your configuration.

The trusted certificate chain will be used to validate the server certificates.

You can set the trusted certificate chain using the trusted_certificates setting the artifactory section with PEM encoded certificates on a YAML literal block like this:

puts:
  - name: "some artifactory server with a private TLS certificate"
    #...(other settings)...
    trusted_certificates: |
      -----BEGIN CERTIFICATE-----
      MIIDrjCCApagAwIBAgIIShr2zchZo+8wDQYJKoZIhvcNAQENBQAwNTEXMBUGA1UE
      ...(edited content)...
      TyzMJasj5BPZrmKjJb6O/tOtEIJ66xPSBTxPShkEYHnB7A==
      -----END CERTIFICATE-----
      -----BEGIN CERTIFICATE-----
      MIIDrjCCApagAwIBAgIIShr2zchZo+8wDQYJKoZIhvcNAQENBQAwNTEXMBUGA1UE
      ...(edited content)...
      TyzMJasj5BPZrmKjJb6O/tOtEIJ66xPSBTxPShkEYHnB7A==
      -----END CERTIFICATE-----

Customization

Of course, you can customize a lot of things:

# .goreleaser.yml
artifactories:
  # You can have multiple Artifactory instances.
  -
    # Unique name of your artifactory instance. Used to identify the instance
    name: production
    # Upload mode. Valid options are `binary` and `archive`.
    # If mode is `archive`, variables _Os_, _Arch_ and _Arm_ for target name are not supported.
    # In that case these variables are empty.
    # Default is `archive`.
    mode: archive
    # URL of your Artifactory instance + path to deploy to
    target: http://artifacts.company.com:8081/artifactory/example-repo-local/{{ .ProjectName }}/{{ .Version }}/
    # User that will be used for the deployment
    username: deployuser
    # Upload checksums (defaults to false)
    checksum: true
    # Upload signatures (defaults to false)
    signature: true
    # Certificate chain used to validate server certificates
    trusted_certificates: |
      -----BEGIN CERTIFICATE-----
      MIIDrjCCApagAwIBAgIIShr2zchZo+8wDQYJKoZIhvcNAQENBQAwNTEXMBUGA1UE
      ...(edited content)...
      TyzMJasj5BPZrmKjJb6O/tOtEIJ66xPSBTxPShkEYHnB7A==
      -----END CERTIFICATE-----

These settings should allow you to push your artifacts into multiple Artifactories.

Bintray

How it works

Uploading to Bintray is a simple case of using HTTP PUT.

Pre and post requisites:

  • Create a user and/or an org in Bintray
  • Create a generic repository in Bintray
  • Create a package with a name matching your ProjectName
  • After publishing, dont’ forget to publish the uploaded files (either via UI or REST API)

    puts:
    - name: bintray
    target: https://api.bintray.com/content/user.or.org.name/generic.repo.name/{{ .ProjectName }}/{{ .Version }}/
    username: goreleaser

Please see HTTP Put for more details.

HTTP Put

GoReleaser supports building and pushing artifacts to HTTP servers using simple HTTP PUT requests.

How it works

You can declare multiple Put instances. All binaries generated by your builds section will be pushed to each configured Put.

If you have only one Put instance, the configuration is as easy as adding the upload target and a username to your .goreleaser.yml file:

puts:
  - name: production
    target: http://some.server/some/path/example-repo-local/{{ .ProjectName }}/{{ .Version }}/
    username: goreleaser

Prerequisites:

  • An HTTP server accepting PUT requests
  • A user + password with grants to upload an artifact using PUT requests (if the server requires it)

Target

The target is the URL to upload the artifacts to (without the name of the artifact).

An example configuration for goreleaser in upload mode binary with the target can look like

- mode: binary
  target: 'http://some.server/some/path/example-repo-local/{{ .ProjectName }}/{{ .Version }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}{{ .Arm }}{{ end }}'

and will result in an HTTP PUT request sent to http://some.server/some/path/example-repo-local/goreleaser/1.0.0/Darwin/x86_64/goreleaser.

Supported variables:

  • Version
  • Tag
  • ProjectName
  • Os
  • Arch
  • Arm

Warning: Variables Os, Arch and Arm are only supported in upload mode binary.

Username

Your configured username needs to be valid against your HTTP server.

You can have the username set in the configuration file as shown above or you can have it read from and environment variable. The configured name of your HTTP server will be used to build the environment variable name. This way we support auth for multiple instances. This also means that the name per configured instance needs to be unique per goreleaser configuration.

The name of the environment variable will be PUT_NAME_USERNAME. If your instance is named production, you can store the username in the environment variable PUT_PRODUCTION_USERNAME. The name will be transformed to uppercase.

If a configured username is found in the configuration file, then the environment variable is not used at all.

Password

The password will be stored in a environment variable. The configured name of your HTTP server will be used. This way we support auth for multiple instances. This also means that the name per configured instance needs to be unique per goreleaser configuration.

The name of the environment variable will be PUT_NAME_SECRET. If your instance is named production, you need to store the secret in the environment variable PUT_PRODUCTION_SECRET. The name will be transformed to uppercase.

Server authentication

You can authenticate your TLS server adding a trusted X.509 certificate chain in your put configuration.

The trusted certificate chain will be used to validate the server certificates.

You can set the trusted certificate chain using the trusted_certificates setting the put section with PEM encoded certificates on a YAML literal block like this:

puts:
  - name: "some HTTP/TLS server"
    #...(other settings)...
    trusted_certificates: |
      -----BEGIN CERTIFICATE-----
      MIIDrjCCApagAwIBAgIIShr2zchZo+8wDQYJKoZIhvcNAQENBQAwNTEXMBUGA1UE
      ...(edited content)...
      TyzMJasj5BPZrmKjJb6O/tOtEIJ66xPSBTxPShkEYHnB7A==
      -----END CERTIFICATE-----
      -----BEGIN CERTIFICATE-----
      MIIDrjCCApagAwIBAgIIShr2zchZo+8wDQYJKoZIhvcNAQENBQAwNTEXMBUGA1UE
      ...(edited content)...
      TyzMJasj5BPZrmKjJb6O/tOtEIJ66xPSBTxPShkEYHnB7A==
      -----END CERTIFICATE-----

Customization

Of course, you can customize a lot of things:

# .goreleaser.yml
puts:
  # You can have multiple Put instances.
  -
    # Unique name of your Put instance. Used to identify the instance.
    name: production

    # IDs of the artifacts you want to PUT.
    ids:
    - foo
    - bar

    # Upload mode. Valid options are `binary` and `archive`.
    # If mode is `archive`, variables _Os_, _Arch_ and _Arm_ for target name are not supported.
    # In that case these variables are empty.
    # Default is `archive`.
    mode: archive

    # URL to be used as target of the HTTP PUT request
    target: https://some.server/some/path/example-repo-local/{{ .ProjectName }}/{{ .Version }}/

    # User that will be used for the deployment
    username: deployuser

    # An optional header you can use to tell GoReleaser to pass the artifact's
    # SHA256 checksum within the upload request.
    # Default is empty.
    checksum_header: -X-SHA256-Sum

    # Upload checksums (defaults to false)
    checksum: true

    # Upload signatures (defaults to false)
    signature: true

   # Certificate chain used to validate server certificates
    trusted_certificates: |
      -----BEGIN CERTIFICATE-----
      MIIDrjCCApagAwIBAgIIShr2zchZo+8wDQYJKoZIhvcNAQENBQAwNTEXMBUGA1UE
      ...(edited content)...
      TyzMJasj5BPZrmKjJb6O/tOtEIJ66xPSBTxPShkEYHnB7A==
      -----END CERTIFICATE-----

These settings should allow you to push your artifacts into multiple HTTP servers.

Docker

Since v0.31.0, GoReleaser supports building and pushing Docker images.

How it works

You can declare multiple Docker images. They will be matched against the binaries generated by your builds section.

If you have only one build setup, the configuration is as easy as adding the name of your image to your .goreleaser.yml file:

The docker image declaration supports templating. Learn more about the name template engine.

dockers:
  - image_templates:
    - user/repo

You also need to create a Dockerfile in your project’s root folder:

FROM scratch
COPY mybin /
ENTRYPOINT ["/mybin"]

This configuration will build and push a Docker image named user/repo:tagname.

Attention: Note that were are not building any go files in the docker build phase, we are merely copying the binary to a scratch image and setting up the entrypoint.

Customization

Of course, you can customize a lot of things:

# .goreleaser.yml
dockers:
  # You can have multiple Docker images.
  -
    # GOOS of the built binary that should be used.
    goos: linux
    # GOARCH of the built binary that should be used.
    goarch: amd64
    # GOARM of the built binary that should be used.
    goarm: ''
    # Name templates of the built binaries that should be used.
    binaries:
    - mybinary
    # Templates of the Docker image names.
    image_templates:
    - "myuser/myimage:latest"
    - "myuser/myimage:{{ .Tag }}"
    - "myuser/myimage:{{ .Tag }}-{{ .Env.GO_VERSION }}"
    - "myuser/myimage:v{{ .Major }}"
    - "gcr.io/myuser/myimage:latest"
    # Skips the docker push. Could be useful if you also do draft releases.
    # If set to auto, the release will not be pushed to the docker repository
    # in case there is an indicator for prerelease in the tag e.g. v1.0.0-rc1
    # Defaults to false.
    skip_push: false
    # Path to the Dockerfile (from the project root).
    dockerfile: Dockerfile
    # Template of the docker build flags.
    build_flag_templates:
    - "--label=org.label-schema.schema-version=1.0"
    - "--label=org.label-schema.version={{.Version}}"
    - "--label=org.label-schema.name={{.ProjectName}}"
    - "--build-arg=FOO={{.Env.Bar}}"
    # If your Dockerfile copies files other than the binary itself,
    # you should list them here as well.
    # Note that goreleaser will create the same structure inside the temporary
    # folder, so if you add `foo/bar.json` here, on your Dockerfile you can
    # `COPY foo/bar.json /whatever.json`.
    # Also note that the paths here are relative to the folder in which
    # goreleaser is being run.
    # This field does not support wildcards, you can add an entire folder here
    # and use wildcards when you `COPY`/`ADD` in your Dockerfile.
    extra_files:
    - config.yml

Learn more about the name template engine.

These settings should allow you to generate multiple Docker images, for example, using multiple FROM statements, as well as generate one image for each binary in your project.

Generic Image Names

Some users might want to keep their image name as generic as possible. That can be accomplished simply by adding template language in the definition:

# .goreleaser.yml
project: foo
dockers:
  -
    binaries:
    - mybinary
    image_templates:
    - "myuser/{{.ProjectName}}"

This will build and public the following images:

  • myuser/foo

Learn more about the name template engine.

Keeping docker images updated for current major

Some users might want to when version to push docker tags :v1, :v1.6, :v1.6.4 and :latest when v1.6.4 (for example) is built. That can be accomplished by using multiple image_templates:

# .goreleaser.yml
dockers:
  -
    binaries:
    - mybinary
    image_templates:
    - "myuser/myimage:{{ .Tag }}"
    - "myuser/myimage:v{{ .Major }}"
    - "myuser/myimage:v{{ .Major }}.{{ .Minor }}"
    - "myuser/myimage:latest"

This will build and publish the following images:

  • myuser/myimage:v1.6.4
  • myuser/myimage:v1
  • myuser/myimage:v1.6
  • myuser/myimage:latest

With these settings you can hopefully push several different docker images with multiple tags.

Learn more about the name template engine.

Publishing to multiple docker registries

Some users might want to push images to multiple docker registries. That can be accomplished by using multiple image_templates:

# .goreleaser.yml
dockers:
  -
    binaries:
    - mybinary
    image_templates:
    - "docker.io/myuser/myimage:{{ .Tag }}"
    - "docker.io/myuser/myimage:latest"
    - "gcr.io/myuser/myimage:{{ .Tag }}"
    - "gcr.io/myuser/myimage:latest"

This will build and publish the following images to docker.io and gcr.io:

  • myuser/myimage:v1.6.4
  • myuser/myimage:latest

Applying docker build flags

Build flags can be applied using build_flag_templates. The flags must be valid docker build flags.

# .goreleaser.yml
dockers:
  -
    binaries:
    - mybinary
    image_templates:
    - "myuser/myimage"
    build_flag_templates:
    - "--label=org.label-schema.schema-version=1.0"
    - "--label=org.label-schema.version={{.Version}}"
    - "--label=org.label-schema.name={{.ProjectName}}"

This will execute the following command:

docker build -t myuser/myimage . \
  --label=org.label-schema.schema-version=1.0 \
  --label=org.label-schema.version=1.6.4 \
  --label=org.label-schema.name=mybinary"

Learn more about the name template engine.

Blob

Customization

# .goreleaser.yml
blobs:
  # You can have multiple blob configs
  -
    # Template for the cloud provider name
    # s3 for AWS S3 Storage
    # azblob for Azure Blob Storage
    # gs for Google Cloud Storage
    provider: azblob

    # Template for the bucket name
    bucket: goreleaser-bucket

    # IDs of the artifacts you want to upload.
    ids:
    - foo
    - bar

    # Template for the path/name inside the bucket.
    # Default is `{{ .ProjectName }}/{{ .Tag }}`
    folder: "foo/bar/{{.Version}}"
  -
    provider: gs
    bucket: goreleaser-bucket
    folder: "foo/bar/{{.Version}}"
  -
    provider: s3
    bucket: goreleaser-bucket
    folder: "foo/bar/{{.Version}}"

Learn more about the name template engine.

Authentication

Goreleaser’s blob pipe authentication varies depending upon the blob provider as mentioned below:

S3 Provider

S3 provider support AWS default credential provider chain in the following order:

  • Environment variables.

  • Shared credentials file.

  • If your application is running on an Amazon EC2 instance, IAM role for Amazon EC2.

Azure Blob Provider

Currently it supports authentication only with environment variables:

  • AZURE_STORAGE_ACCOUNT
  • AZURE_STORAGE_KEY or AZURE_STORAGE_SAS_TOKEN

GCS Provider

GCS provider uses Application Default Credentials in the following order:

  • Environment Variable (GOOGLE_APPLICATION_CREDENTIALS)
  • Default Service Account from the compute instance(Compute Engine, Kubernetes Engine, Cloud function etc).