GoReleaser v2 + GitHub Actions: Go Release Guide

Xinwei Xiong
57 min · 12032 words

Learn GoReleaser v2 through local snapshot builds, a field-by-field .goreleaser.yaml reference, and a GitHub Actions entry point for multi-platform releases.

The goal of GoReleaser is to automate much of the tedious work when releasing software, by using sensible defaults and making it simple for the most common use cases.

Preparation:

  • .goreleaser.yaml file: contains all configuration information. (For more information, see Customization )
  • Clean working tree: Make sure the code is up to date and all changes have been committed.
  • SemVer compliant version number (e.g. 10.21.34-prerelease+buildmeta)

GoReleaser running steps:

The operation of GoReleaser is mainly divided into the following four steps:

  1. defaulting: Configure reasonable default values for each step
  2. building: Build binaries, archives, packages, Docker images, etc.
  3. releasing: Release the version to the configured SCM, Docker registry, blob storage, etc.
  4. announcing: Announce your release to the configured channel

Some steps may be skipped with the --skip flag, for example --skip=publish.

Quick Start

First, run the init command to create the example .goreleaser.yaml file:

goreleaser init

We then run a “local only” build to see if it works using the release command:

goreleaser release --snapshot --clean

At this point, you can customize the generated .goreleaser.yaml file, or leave it as-is, it’s up to you. Best practice is to put the .goreleaser.yaml file into your version control system.

You can also use GoReleaser to build a binary for a given GOOS/GOARCH (https://goreleaser.com/cmd/goreleaser_build/) , which is useful for local development:

goreleaser build --single-target

Prepare GitHub Token:

export GITHUB_TOKEN="YOUR_GH_TOKEN"

GoReleaser will use the latest Git tag for your repository.

Create a tag and push it to GitHub (replace v0.1.0 with your version):

git tag v0.1.0
git push origin v0.1.0

Now you can run GoReleaser in the root directory of your project:

goreleaser release

Version boundary (October 2026): the build and archives examples in this article, and the GitHub Actions snippets, target GoReleaser OSS 2.18.0 (config schema , strict loader ). Later releases may rename or remove fields; upgrade only after re-validating your configuration with goreleaser check .

Using GoReleaser in GitHub Actions

GoReleaser is also available in our official GoReleaser Action via GitHub Actions.

Put this YAML configuration in .github/workflows/release.yml, following the official GoReleaser Action example .

name: goreleaser

on:
   push:
     # Only run on labels
     tags:
       - '*'

permissions:
   contents: write
   # packages: write
   # issues: write

jobs:
   goreleaser:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v4
         with:
           fetch-depth: 0
       - run: git fetch --force --tags
       - uses: actions/setup-go@v5
         with:
           go-version: stable
       # More settings may be required, such as Docker login, GPG, etc. These all depend on your needs.
       - uses: goreleaser/goreleaser-action@v7
         with:
           # You can choose 'goreleaser' (default) or 'goreleaser-pro'
           distribution: goreleaser
           version: v2.18.0
           args: release --clean
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
           # If you are using the 'goreleaser-pro' distribution, you will need the GoReleaser Pro key:
           # GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}

GoReleaser requires the following permissions :

The GITHUB_TOKEN permission only contains your Workflow repository.

If you need to push Homebrew Tap to another repository, then you must create a personal access token that you have access to and add it as the repository’s secret. If you created a secret named GH_PAT, the steps would be as follows:

       - name: Run GoReleaser
         uses: goreleaser/goreleaser-action@v7
         with:
           version: v2.18.0
           args: release --clean
         env:
           GITHUB_TOKEN: ${{ secrets.GH_PAT }}

Customized requirements

GoReleaser can be customized by adjusting the .goreleaser.yaml file.

goreleaser init You can generate a sample configuration by running or starting from scratch.

You can also check that your configuration is valid by running goreleaser check , which will tell you if you are using deprecated or invalid options.

Name template

KeyDescription
.ProjectNameProject name
.VersionThe version being released (Details )
.BranchThe current git branch
.PrefixedTagThe current git tag prefixed by the monorepo configuration tag prefix (if any)
.TagThe current git tag
.PrefixedPreviousTagThe previous git tag prefixed with the monorepo configuration tag (if any)
.PreviousTagThe previous git tag, or empty if there is no previous tag
.ShortCommitgit commit short hash
.FullCommitgit commits the complete hash value
.Commitgit commit hash (deprecated)
.CommitDateUTC submission date in RFC 3339 format
.CommitTimestampUTC commit date in Unix format
.GitURLgit remote URL
.IsGitDirtyWhether the current git status is dirty. Since v1.19.
.MajorVersion (Details )
.MinorVersion (Details )
.PatchPatch section (Details )
.PrereleaseThe pre-release part of the version, such as beta (Details )
.RawVersionComposed of {Major}.{Minor}.{Patch} (Details )
.ReleaseNotesGenerated release notes, available after executing the changelog step
.IsDrafttrue if release.draft is set in the configuration, false otherwise. Since v1.17.
.IsSnapshottrue if --snapshot is set, false otherwise
.IsNightlytrue if --nightly is set, false otherwise
.EnvContains a map of system environment variables
.DateCurrent UTC date in RFC 3339 format
.NowThe current UTC date as a time.Time structure, allowing all time.Time functionality (e.g. {{ .Now.Format "2006" }} ). Since v1.17.
.TimestampCurrent UTC time in Unix format
.ModulePathgo module path, as reported go list -m
incpatch "v1.2.4"Patch (Details )
incminor "v1.2.4"Minor version (Details )
incmajor "v1.2.4"Increase the given version (Details )
.ReleaseURLCurrent version download address (Details )
.Summarygit summary, for example v1.0.0-10-g34f56g3 (Details )
.PrefixedSummaryA git summary prefixed with the monorepo configuration tag prefix (if any)
.TagSubjectThe annotated tag message subject, or the message subject of the commit it points to (Details ). Starting with v1.2.
.TagContentsThe annotated tag message, or the commit message it points to (Details ) . Since v1.2 start.
.TagBodyThe annotated tag message body, or the message body of the commit it points to (Details ). Starting with v1.2.
.Runtime.GoosEquivalent to runtime.GOOS. Since v1.5.
.Runtime.GoarchEquivalent to runtime.GOARCH. Since v1.5.
.ArtifactsThe current list of artifacts. The fields are shown in the table below. Since v1.16-pro.

Configuration options

# Default: './dist'
dist: _output/dist

git:
   # What should be used to sort tags when gathering the current and previous
   # tags if there are more than one tag in the same commit.
   #
   # Default: '-version:refname'
   tag_sort: -version:creatordate

   # What should be used to specify prerelease suffix while sorting tags when gathering
   # the current and previous tags if there are more than one tag in the same commit.
   #
   # Since: v1.17
   prerelease_suffix: "-"

Build options

The build can be customized in a variety of ways. You can specify which GOOS, GOARCH and GOARM binaries are built (GoReleaser will generate a matrix of all combinations), and you can change the binaries’ names, flags, environment variables, hooks, etc.

builds is the most important option in the configuration file:

The long field listing below is a combined reference excerpt of build options (Go build options ); do not copy it wholesale as a production configuration.

# .goreleaser.yaml
builds:
  # You can have multiple builds defined as a yaml list
  - #
    # ID of the build.
    #
    # Default: Binary name
    id: "my-build"

    # Path to main.go file or main package.
    # Notice: when used with `gomod.proxy`, this must be a package.
    #
    # Default is `.`.
    main: ./cmd/my-app

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

    # Custom flags.
    #
    # Templates: allowed
    flags:
      - -tags=dev
      - -v

    # Custom asmflags.
    #
    # Templates: allowed
    asmflags:
      - -D mysymbol
      - all=-trimpath={{.Env.GOPATH}}

    # Custom gcflags.
    #
    # Templates: allowed
    gcflags:
      - all=-trimpath={{.Env.GOPATH}}
      - ./dontoptimizeme=-N

    # Custom ldflags.
    #
    # Default: '-s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}} -X main.builtBy=goreleaser'
    # Templates: allowed
    ldflags:
      - -s -w -X main.build={{.Version}}
      - ./usemsan=-msan

    # Custom Go build mode.
    #
    # Valid options:
    # - `c-shared`
    # - `c-archive`
    #
    # Since: v1.13
    buildmode: c-shared

    # Custom build tags templates.
    tags:
      - osusergo
      - netgo
      - static_build
      - feature

    # Custom environment variables to be set during the builds.
    # Invalid environment variables will be ignored.
    #
    # Default: os.Environ() ++ env config section
    # Templates: allowed (since v1.14)
    env:
      - CGO_ENABLED=0
      # complex, templated envs (v1.14+):
      - >-
        {{- if eq .Os "darwin" }}
          {{- if eq .Arch "amd64"}}CC=o64-clang{{- end }}
          {{- if eq .Arch "arm64"}}CC=aarch64-apple-darwin20.2-clang{{- end }}
        {{- end }}
        {{- if eq .Os "windows" }}
          {{- if eq .Arch "amd64" }}CC=x86_64-w64-mingw32-gcc{{- end }}
        {{- end }}

    # GOOS list to build for.
    # For more info refer to: https://golang.org/doc/install/source#environment
    #
    # Default: [ 'darwin', 'linux', 'windows' ]
    goos:
      - freebsd
      - windows

    # GOARCH to build for.
    # For more info refer to: https://golang.org/doc/install/source#environment
    #
    # Default: [ '386', 'amd64', 'arm64' ]
    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: [ 6 ]
    goarm:
      - 6
      - 7

    # GOAMD64 to build when GOARCH is amd64.
    # For more info refer to: https://golang.org/doc/install/source#environment
    #
    # Default: [ 'v1' ]
    goamd64:
      - v2
      - v3

    # GOMIPS and GOMIPS64 to build when GOARCH is mips, mips64, mipsle or mips64le.
    # For more info refer to: https://golang.org/doc/install/source#environment
    #
    # Default: [ 'hardfloat' ]
    gomips:
      - hardfloat
      - softfloat

    # List of combinations of GOOS + GOARCH + GOARM to ignore.
    ignore:
      - goos: darwin
        goarch: 386
      - goos: linux
        goarch: arm
        goarm: 7
      - goarm: mips64
      - gomips: hardfloat
      - goamd64: v4

    # Optionally override the matrix generation and specify only the final list
    # of targets.
    #
    # Format is `{goos}_{goarch}` with their respective suffixes when
    # applicable: `_{goarm}`, `_{goamd64}`, `_{gomips}`.
    #
    # Special values:
    # - go_118_first_class: evaluates to the first-class ports of go1.18.
    # - go_first_class: evaluates to latest stable go first-class ports,
    #   currently same as 1.18.
    #
    # This overrides `goos`, `goarch`, `goarm`, `gomips`, `goamd64` and
    # `ignores`.
    targets:
      # Since: v1.9
      - go_first_class
      # Since: v1.9
      - go_118_first_class
      - linux_amd64_v1
      - darwin_arm64
      - linux_arm_6

    # Set a specific go binary to use when building.
    # It is safe to ignore this option in most cases.
    #
    # Default is "go"
    gobinary: "go1.13.4"

    # Sets the command to run to build.
    # Can be useful if you want to build tests, for example,
    # in which case you can set this to "test".
    # It is safe to ignore this option in most cases.
    #
    # Default: build.
    # Since: v1.9
    command: test

    # Set the modified timestamp on the output binary, typically
    # you would do this to ensure a build was reproducible. Pass
    # empty string to skip modifying the output.
    #
    # Templates: allowed.
    mod_timestamp: "{{ .CommitTimestamp }}"

    # Hooks can be used to customize the final binary,
    # for example, to run generators.
    #
    # Templates: allowed
    hooks:
      pre: rice embed-go
      post: ./script.sh {{ .Path }}

    # If true, skip the build.
    # Useful for library projects.
    skip: false

    # By default, GoReleaser will create your binaries inside
    # `dist/${BuildID}_${BuildTarget}`, which is a unique directory per build
    # target in the matrix.
    # You can set subdirs within that folder using the `binary` property.
    #
    # However, if for some reason you don't want that unique directory to be
    # created, you can set this property.
    # If you do, you are responsible for keeping different builds from
    # overriding each other.
    no_unique_dist_dir: true

    # By default, GoReleaser will check if the main filepath has a main
    # function.
    # This can be used to skip that check, in case you're building tests, for
    # example.
    #
    # Since: v1.9
    no_main_check: true

    # Path to project's (sub)directory containing Go code.
    # This is the working directory for the Go build command(s).
    # If dir does not contain a `go.mod` file, and you are using `gomod.proxy`,
    # produced binaries will be invalid.
    # You would likely want to use `main` instead of this.
    #
    # Default: '.'
    dir: go

    # Builder allows you to use a different build implementation.
    # This is a GoReleaser Pro feature.
    # Valid options are: `go` and `prebuilt`.
    #
    # Default: 'go'
    builder: prebuilt

    # Overrides allows to override some fields for specific targets.
    # This can be specially useful when using CGO.
    # Note: it'll only match if the full target matches.
    #
    # Since: v1.5
    overrides:
      - goos: darwin
        goarch: arm64
        goamd64: v1
        goarm: ""
        gomips: ""
        ldflags:
          - foo
        tags:
          - bar
        asmflags:
          - foobar
        gcflags:
          - foobaz
        env:
          - CGO_ENABLED=1

Builds containing multiple binaries:

# .goreleaser.yaml
builds:
   - main: ./cmd/cli
     id: "cli"
     binary: cli
     goos:
       - linux
       - darwin
       - windows

   - main: ./cmd/worker
     id: "worker"
     binary: worker
     goos:
       - linux
       - darwin
       - windows

   - main: ./cmd/tracker
     id: "tracker"
     binary: tracker
     goos:
       - linux
       - darwin
       - windows

Binary name fields support templating . The following build details are exposed:

KeyDescription
.OsGOOS
.ArchGOARCH
.ArmGOARM
.ExtExtension, e.g. .exe
.TargetBuild target, e.g. darwin_amd64

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

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

Then you can run:

GOVERSION=$(go version) goreleaser

build hooks

Both pre and post hooks run against every build target, whether those targets are generated via the operating system and architecture matrix or defined explicitly.

In addition to the simple declaration shown above, multiple hooks can be declared (see the official build hooks reference ) to help keep the configuration reusable between different build environments.

# .goreleaser.yaml
builds:
   - id: "with-hooks"
     targets:
       - "darwin_amd64"
       - "windows_amd64"
     hooks:
       pre:
         - first-script.sh
         - second-script.sh
       post:
         - upx "{{ .Path }}"
         - codesign -project="{{ .ProjectName }}" "{{ .Path }}"

Each hook can also have its own working directory and environment variables:

# .goreleaser.yaml
builds:
   - id: "with-hooks"
     targets:
       - "darwin_amd64"
       - "windows_amd64"
     hooks:
       pre:
         - cmd: first-script.sh
           dir:
             "{{ dir .Dist}}"
             # Always print command output, otherwise only visible in debug mode.
             # Since: v1.5
           output: true
           env:
             - HOOK_SPECIFIC_VAR={{ .Env.GLOBAL_VAR }}
         - second-script.sh

All properties of hooks (cmd, dir and env) support using hooks with binary artifacts available for templating (https://goreleaser.com/customization/templates/ ) (as they are built *run later). *In addition, the following build details are also exposed to and hooks: postprepost

KeyDescription
.NameFilename of the binary, e.g. bin.exe
.ExtExtension, e.g. .exe
.PathAbsolute path to the binary
.TargetBuild target, e.g. darwin_amd64

Environment variables are inherited and overridden in the following order:

  • global (env)
  • build (builds[].env)
  • Hooks (builds[].hooks.pre[].env and builds[].hooks.post[].env)

Module

If you are using Go 1.11+ with the go module or vgo, when GoReleaser runs, it may try to download dependencies. Since multiple builds are running in parallel, it is likely to fail.

You can solve this by running goreleaser before calling go mod tidy or adding a hook .goreleaser.yaml that does this on the file question:

# .goreleaser.yaml
before:
   hooks:
     - go mod tidy
# rest of the file...

archives

Binaries built by README will be archived together with LICENSE files into a tar.gz file. In this archives section you can customize the archive name, additional files and formats.

# .goreleaser.yaml
archives:
  - #
    # ID of this archive.
    #
    # Default: 'default'
    id: my-archive

    # `ids` reference which build instances should be archived in this archive.
    #
    # Replaces the deprecated `builds` key, which 2.18.0 still accepts as an alias.
    ids:
      - default

    # Archive formats. Valid options are `tar.gz`, `tgz`, `tar.xz`, `txz`, `tar`, `gz`, `zip` and `binary`.
    # If a format is `binary`, no archives are created and the binaries are instead
    # uploaded directly.
    #
    # Replaces the deprecated `format` key, which 2.18.0 still accepts as an alias.
    #
    # Default: ['tar.gz']
    formats:
      - zip

    # Setting this to `true` creates a files-only meta archive: it contains none of
    # the built binaries, only the configured files. That is a separate mode from the
    # binary archive shown here, so this example keeps it off. When enabled, the name
    # template must not contain any references to `Os`, `Arch` and etc, since the
    # archive will be meta.
    #
    # Since: v1.9
    # Templates: allowed
    meta: false

    # Archive name.
    #
    #Default:
    # - if format is `binary`:
    # - `{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ with .Mips }}_{{ . }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}`
    # - if format is anything else:
    # - `{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ with .Mips }}_{{ . }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}`
    # Templates: allowed
    name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"

    # Sets the given file info to all the binaries included from the `builds`.
    #
    # Default: copied from the source binary.
    # Since: v1.14
    builds_info:
      group: root
      owner: root
      mode: 0644
      # format is `time.RFC3339Nano`
      mtime: 2008-01-02T15:04:05Z

    # Set this 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'll get a folder 'goreleaser_Linux_arm64'.
    # If set to falsee, all files are extracted separately.
    # You can also set it to a custom folder name (templating is supported).
    wrap_in_directory: true

    # If set to true, will strip the parent directories away from binary files.
    #
    # This might be useful if you have your binary be built with a subdir for some reason, but do no want that subdir inside the archive.
    #
    # `strip_binary_directory` replaces `strip_parent_binary_folder`, which is no
    # longer in the 2.18.0 schema and is rejected by the strict loader.
    strip_binary_directory: true

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

    # Additional files/globs you want to add to the archive.
    #
    # Default: [ 'LICENSE*', 'README*', 'CHANGELOG', 'license*', 'readme*', 'changelog']
    # Templates: allowed
    files:
      - LICENSE.txt
      - README_{{.Os}}.md
      - CHANGELOG.md
      - docs/*
      - design/*.png
      - templates/**/*
      # a more complete example, check the globbing deep dive below
      - src: "*.md"
        dst: docs

        # Strip parent folders when adding files to the archive.
        strip_parent: true

        # File info.
        # Not all fields are supported by all formats available formats.
        #
        # Default: copied from the source file
        info:
          # Templates: allowed (since v1.14)
          owner: root

          # Templates: allowed (since v1.14)
          group: root

          # Must be in time.RFC3339Nano format.
          #
          # Templates: allowed (since v1.14)
          mtime: "{{ .CommitDate }}"

          # File mode.
          mode: 0644

    # Disables the binary count check.
    allow_different_binary_count: true

Field names in the block above follow the GoReleaser OSS 2.18.0 archives schema and its strict loader . ids and formats (including format_overrides.formats) replace the deprecated builds and format keys, which 2.18.0 still accepts as deprecated aliases - a deprecated field is not by itself a runtime failure (deprecations ). By contrast, rlcp and strip_parent_binary_folder are no longer in the schema and are rejected outright; strip_binary_directory replaces the latter. Because meta: true builds a files-only archive without any binaries, this binary archive example keeps meta: false.

The archive fields below are GoReleaser Pro only. Keep them out of an OSS .goreleaser.yaml; see the archives documentation for the Pro reference.

# GoReleaser Pro only: reference snippet, not part of the OSS configuration above.
archives:
  - #
    # Additional templated files to add to the archive.
    # Those files will have their contents pass through the template engine,
    # and its results will be added to the archive.
    #
    # Since: v1.17 (pro)
    # This feature is only available in GoReleaser Pro.
    # Templates: allowed
    templated_files:
      # a more complete example, check the globbing deep dive below
      - src: "LICENSE.md.tpl"
        dst: LICENSE.md

        # File info.
        # Not all fields are supported by all formats available formats.
        #
        # Default: copied from the source file
        info:
          # Templateable (since v1.14.0)
          owner: root

          # Templateable (since v1.14.0)
          group: root

          # Must be in time.RFC3339Nano format.
          # Templateable (since v1.14.0)
          mtime: "{{ .CommitDate }}"

          # File mode.
          mode: 0644

    # Before and after hooks for each archive.
    # Skipped if archive format is binary.
    # This feature is only available in GoReleaser Pro.
    hooks:
      before:
        - make clean # simple string
        - cmd: go generate ./... # specify cmd
        - cmd: go mod tidy
          output: true # always prints command output
          dir: ./submodule # specify command working directory
        - cmd: touch {{ .Env.FILE_TO_TOUCH }}
          env:
            - "FILE_TO_TOUCH=something-{{ .ProjectName }}" # specify hook level environment variables

      after:
        - make clean
        - cmd: cat *.yaml
          dir: ./submodule
        - cmd: touch {{ .Env.RELEASE_DONE }}
          env:
            - "RELEASE_DONE=something-{{ .ProjectName }}" # specify hook level environment variables

Linux packages

GoReleaser can connect to nfpm to generate and publish .deb, .rpm, .apk, and Archlinux packages.

# .goreleaser.yaml
nfpms:
  # note that this is an array of nfpm configs
  - #
    # ID of the nfpm config, must be unique.
    #
    # Default: 'default'
    id: foo

    # Name of the package.
    # Default: ProjectName
    # Templates: allowed (since v1.18)
    package_name: foo

    # You can change the file name of the package.
    #
    # Default: '{{ .PackageName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ with .Mips }}_{{ . }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}'
    # Templates: allowed
    file_name_template: "{{ .ConventionalFileName }}"

    # Build IDs for the builds you want to create NFPM packages for.
    # Defaults empty, which means no filtering.
    builds:
      - foo
      - bar

    # Your app's vendor.
    vendor: Drum Roll Inc.

    # Your app's homepage.
    homepage: https://example.com/

    # Your app's maintainer (probably you).
    maintainer: Drummer <drum-roll@example.com>

    # Your app's description.
    description: |-
      Drum rolls installer package.
      Software to create fast and easy drum rolls.

    # Your app's license.
    license: Apache 2.0

    # Formats to be generated.
    formats:
      - apk
      - deb
      - rpm
      - termux.deb # Since: v1.11
      - archlinux # Since: v1.13

    # Umask to be used on files without explicit mode set. (overridable)
    #
    # Default: 0o002 (will remove world-writable permissions)
    # Since: v1.19
    umask: 0o002

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

    # Packages it provides. (overridable)
    #
    # Since: v1.11
    provides:
      - bar

    # Packages your package recommends installing. (overridable)
    recommends:
      - bzr
      - gtk

    # Packages your package suggests installing. (overridable)
    suggests:
      - cvs
      - ksh

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

    # Packages it replaces. (overridable)
    replaces:
      - fish

    # Path that the binaries should be installed.
    # Default: '/usr/bin'
    bindir: /usr/bin

    # Version Epoch.
    # Default: extracted from `version` if it is semver compatible
    epoch: 2

    # Version Prerelease.
    # Default: extracted from `version` if it is semver compatible
    prerelease: beta1

    # Version Metadata (previously deb.metadata).
    # Setting metadata might interfere with version comparisons depending on the
    # packager.
    #
    # Default: extracted from `version` if it is semver compatible
    version_metadata: git

    # Version Release.
    release: 1

    # Section.
    section: default

    # Priority.
    priority: extra

    # Makes a meta package - an empty package that contains only supporting
    # files and dependencies.
    # When set to `true`, the `builds` option is ignored.
    #
    # Default: false
    meta: true

    # Changelog YAML file, see: https://github.com/goreleaser/chglog
    #
    # You can use goreleaser/chglog to create the changelog for your project,
    # pass that changelog yaml file to GoReleaser,
    # and it should in turn setup it accordingly for the given available
    # formats (deb and rpm at the moment).
    #
    # Experimental.
    # Since: v1.11
    changelog: ./foo.yml

    # Contents to add to the package.
    # GoReleaser will automatically add the binaries.
    contents:
      # Basic file that applies to all packagers
      - src: path/to/foo
        dst: /usr/bin/foo

      # This will add all files in some/directory or in subdirectories at the
      # same level under the directory /etc. This means the tree structure in
      # some/directory will not be replicated.
      - src: some/directory/
        dst: /etc

      # This will replicate the directory structure under some/directory at
      # /etc, using the "tree" type.
      #
      # Since: v1.17
      # Templates: allowed
      - src: some/directory/
        dst: /etc
        type: tree

      # Simple config file
      - src: path/to/foo.conf
        dst: /etc/foo.conf
        type: config

      # Simple symlink.
      # Corresponds to `ln -s /sbin/foo /usr/local/bin/foo`
      - src: /sbin/foo
        dst: /usr/bin/foo
        type: "symlink"

      # Corresponds to `%config(noreplace)` if the packager is rpm, otherwise it
      # is just a config file
      - src: path/to/local/bar.conf
        dst: /etc/bar.conf
        type: "config|noreplace"

      # The src and dst attributes also supports name templates
      - src: path/{{ .Os }}-{{ .Arch }}/bar.conf
        dst: /etc/foo/bar-{{ .ProjectName }}.conf

    # Additional templated contents to add to the archive.
    # Those files will have their contents pass through the template engine,
    # and its results will be added to the package.
    #
    # Since: v1.17 (pro)
    # This feature is only available in GoReleaser Pro.
    # Templates: allowed
    templated_contents:
      # a more complete example, check the globbing deep dive below
      - src: "LICENSE.md.tpl"
        dst: LICENSE.md

      # These files are not actually present in the package, but the file names
      # are added to the package header. From the RPM directives documentation:
      #
      # "There are times when a file should be owned by the package but not
      # installed - log files and state files are good examples of cases you
      # might desire this to happen."
      #
      # "The way to achieve this, is to use the %ghost directive. By adding this
      # directive to the line containing a file, RPM will know about the ghosted
      # file, but will not add it to the package."
      #
      # For non rpm packages ghost files are ignored at this time.
      - dst: /etc/casper.conf
        type: ghost
      - dst: /var/log/boo.log
        type: ghost

      # You can use the packager field to add files that are unique to a
      # specific packager
      - src: path/to/rpm/file.conf
        dst: /etc/file.conf
        type: "config|noreplace"
        packager: rpm
      - src: path/to/deb/file.conf
        dst:/etc/file.conf
        type: "config|noreplace"
        packager: deb
      - src: path/to/apk/file.conf
        dst: /etc/file.conf
        type: "config|noreplace"
        packager: apk

      # Sometimes it is important to be able to set the mtime, mode, owner, or
      # group for a file that differs from what is on the local build system at
      # build time.
      - src: path/to/foo
        dst: /usr/local/foo
        file_info:
          mode: 0644
          mtime: 2008-01-02T15:04:05Z
          owner: notRoot
          group: notRoot

      # If `dst` ends with a `/`, it'll create the given path and copy the given
      # `src` into it, the same way `cp` works with and without trailing `/`.
      - src: ./foo/bar/*
        dst: /usr/local/myapp/

      # Using the type 'dir', empty directories can be created. When building
      # RPMs, however, this type has another important purpose: Claiming
      # ownership of that folder. This is important because when upgrading or
      # removing an RPM package, only the directories for which it has claimed
      # ownership are removed. However, you should not claim ownership of a
      # folder that is created by the OS or a dependency of your package.
      #
      # A directory in the build environment can optionally be provided in the
      # 'src' field in order copy mtime and mode from that directory without
      # having to specify it manually.
      - dst: /some/dir
        type: dir
        file_info:
          mode: 0700

    # Scripts to execute during the installation of the package. (overridable)
    #
    # 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"

    # All fields above marked as `overridable` can be overridden for a given
    # package format in this section.
    overrides:
      # The dependencies override can for example be used to provide version
      # constraints for dependencies where  different package formats use
      # different versions or for dependencies that are named differently.
      deb:
        dependencies:
          - baz (>= 1.2.3-0)
          - some-lib-dev
        # ...
      rpm:
        dependencies:
          - baz >= 1.2.3-0
          - some-lib-devel
        # ...
      apk:
        # ...

    # Custom configuration applied only to the RPM packager.
    rpm:
      # RPM specific scripts.
      scripts:
        # The pretrans script runs before all RPM package transactions / stages.
        pretrans: ./scripts/pretrans.sh
        # The posttrans script runs after all RPM package transactions / stages.
        posttrans: ./scripts/posttrans.sh

      # The package summary.
      #
      # Default: first line of the description
      summary: Explicit Summary for Sample Package

      # The package group.
      # This option is deprecated by most distros but required by old distros
      # like CentOS 5 / EL 5 and earlier.
      group: Unspecified

      # The packager is used to identify the organization that actually packaged
      # the software, as opposed to the author of the software.
      # `maintainer` will be used as fallback if not specified.
      # This will expand any env var you set in the field, eg packager: ${PACKAGER}
      packager: GoReleaser <staff@goreleaser.com>

      # Compression algorithm (gzip (default), lzma or xz).
      compression: lzma

      # Prefixes for relocatable packages.
      #
      # Since: v1.20.
      prefixes:
        - /usr/bin

      # The package is signed if a key_file is set
      signature:
        # PGP secret key file path (can also be ASCII-armored).
        # The passphrase is taken from the environment variable
        # `$NFPM_ID_RPM_PASSPHRASE` with a fallback to `$NFPM_ID_PASSPHRASE`,
        # where ID is the id of the current nfpm config.
        # The id will be transformed to uppercase.
        # E.g. If your nfpm id is 'default' then the rpm-specific passphrase
        # should be set as `$NFPM_DEFAULT_RPM_PASSPHRASE`
        #
        # Templates: allowed
        key_file: "{{ .Env.GPG_KEY_PATH }}"

    # Custom configuration applied only to the Deb packager.
    deb:
      # Lintian overrides
      lintian_overrides:
        - statically-linked-binary
        - changelog-file-missing-in-native-package

      # Custom deb special files.
      scripts:
        # Deb rules script.
        rules: foo.sh
        # Deb templates file, when using debconf.
        templates: templates

      # Custom deb triggers
      triggers:
        # register interest on a trigger activated by another package
        # (also available: interest_await, interest_noawait)
        interest:
          - some-trigger-name
        # activate a trigger for another package
        # (also available: activate_await, activate_noawait)
        activate:
          - another-trigger-name

      # Packages which would break if this package would be installed.
      # The installation of this package is blocked if `some-package`
      # is already installed.
      breaks:
        - some-package

      # The package is signed if a key_file is set
      signature:
        # PGP secret key file path (can also be ASCII-armored).
        # The passphrase is taken from the environment variable
        # `$NFPM_ID_DEB_PASSPHRASE` with a fallback to `$NFPM_ID_PASSPHRASE`,
        # where ID is the id of the current nfpm config.
        # The id will be transformed to uppercase.
        # E.g. If your nfpm id is 'default' then the deb-specific passphrase
        # should be set as `$NFPM_DEFAULT_DEB_PASSPHRASE`
        #
        # Templates: allowed
        key_file: "{{ .Env.GPG_KEY_PATH }}"

        # The type describes the signers role, possible values are "origin",
        # "maint" and "archive".
        #
        # Default: 'origin'
        type: origin

    apk:
      # APK specific scripts.
      scripts:
        # The preupgrade script runs before APK upgrade.
        preupgrade: ./scripts/preupgrade.sh
        # The postupgrade script runs after APK.
        postupgrade: ./scripts/postupgrade.sh

      # The package is signed if a key_file is set
      signature:
        # PGP secret key file path (can also be ASCII-armored).
        # The passphrase is taken from the environment variable
        # `$NFPM_ID_APK_PASSPHRASE` with a fallback to `$NFPM_ID_PASSPHRASE`,
        # where ID is the id of the current nfpm config.
        # The id will be transformed to uppercase.
        # E.g. If your nfpm id is 'default' then the apk-specific passphrase
        # should be set as `$NFPM_DEFAULT_APK_PASSPHRASE`
        #
        # Templates: allowed
        key_file: "{{ .Env.GPG_KEY_PATH }}"

        # The name of the signing key. When verifying a package, the signature
        # is matched to the public key store in /etc/apk/keys/<key_name>.rsa.pub.
        #
        # Default: maintainer's email address
        # Templates: allowed (since v1.15)
        key_name: origin

    archlinux:
      # Archlinux-specific scripts
      scripts:
        # The preupgrade script runs before pacman upgrades the package.
        preupgrade: ./scripts/preupgrade.sh
        # The postupgrade script runs after pacman upgrades the package.
        postupgrade: ./scripts/postupgrade.sh

      # The pkgbase can be used to explicitly specify the name to be used to refer
      # to a group of packages. See: https://wiki.archlinux.org/title/PKGBUILD#pkgbase.
      pkgbase: foo

      # The packager refers to the organization packaging the software, not to be confused
      # with the maintainer, which is the person who maintains the software.
      packager: GoReleaser <staff@goreleaser.com>

Learn more about the name template engine .

Checksums verification

GoReleaser generates a file and uploads it along with the release, so that your users can verify that the downloaded files are correct.

This section allows customizing the file name:

# .goreleaser.yaml
checksum:
  # You can change the name of the checksums file.
  #
  # Default: {{ .ProjectName }}_{{ .Version }}_checksums.txt
  # Templates: allowed
  name_template: "{{ .ProjectName }}_checksums.txt"

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

  # IDs of artifacts to include in the checksums file.
  #
  # If left empty, all published binaries, archives, linux packages and source archives
  # are included in the checksums file.
  ids:
    - foo
    - bar

  # Disable the generation/upload of the checksum file.
  disable: true

  # You can add extra pre-existing files to the checksums file.
  # The filename on the checksum will be the last part of the path (base).
  # If another file with the same name exists, the last one found will be used.
  #
  # Templates: allowed
  extra_files:
    - glob: ./path/to/file.txt
    - glob: ./glob/**/to/**/file/**/*
    - glob: ./glob/foo/to/bar/file/foobar/override_from_previous
    - glob: ./single_file.txt
      name_template: file.txt # note that this only works if glob matches 1 file only

  # Additional templated extra files to add to the checksum.
  # Those files will have their contents pass through the template engine,
  # and its results will be added to the checksum.
  #
  # Since: v1.17 (pro)
  # This feature is only available in GoReleaser Pro.
  # Templates: allowed
  templated_extra_files:
    - src: LICENSE.tpl
      dst: LICENSE.txt

Snapcraft Packages (snaps) Snapcraft Packages

GoReleaser can also generate packages. Snaps are a new packaging format that lets you publish your project directly to the Ubuntu store. From there, it can be installed on all supported Linux distributions, with automatic and transactional updates.

You can read more about this in the snapcraft documentation.

Snaps are Linux application packages for the desktop, the cloud and IoT, easy to install, secure, cross-platform, and dependency-free.

They update automatically, and usually run in confined transaction-based environments. Security and robustness are their main features; in addition, they are easy to install, easy to maintain, and easy to upgrade.

Snapd release process

snapd is the background service that manages and maintains snaps. It is itself available as snap packages or traditional Linux packages (such as deb or RPM).

There are two types of releases; major and minor releases, represented by the numeric status of their version number, with a minor period and a number reserved for minor releases:

  • Major version releases: 2.53, 2.54, 2.55
  • Minor version releases: 2.53.1, 2.53.2

The difference between a major release and a minor release is its planning, preparation, and motivation. There is a major release cycle every few weeks, but sometimes we need intermediate minor releases that contain smaller changes and fixes.

Differences between major releases and subsequent minor releases (e.g. 2.53 -> 2.53.1) are kept as small and targeted as possible, and major code refactorings and new features are omitted. This is not always possible because sometimes the bugs or features are complex, but this is our primary goal.

Step-by-step release process

Use Snapcraft to build and publish Snap installation packages

Generate an initial project:

$ snapcraft init
Created snap/snapcraft.yaml.

Docker Images

GoReleaser can build and push Docker images. Let’s see how it works.

You can declare multiple Docker images. They will be matched against section-generated binaries and section-generated packages.

If you only have one setting, configuration is as simple as adding the image name to a file:

dockers:
   - image_templates:
       -user/repo

You will also need to create a Dockerfile in the root folder of your project:

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

This configuration will build and push a Docker image named .

Customization

# .goreleaser.yaml
dockers:
   # You can have multiple Docker images.
   - #
     # ID of the image, needed if you want to filter by it later on (e.g. on custom publishers).
     id: myimg

     # GOOS of the built binaries/packages that should be used.
     # Default: 'linux'
     goos: linux

     # GOARCH of the built binaries/packages that should be used.
     # Default: 'amd64'
     goarch: amd64

     # GOARM of the built binaries/packages that should be used.
     # Default: '6'
     goarm: ""

     # GOAMD64 of the built binaries/packages that should be used.
     # Default: 'v1'
     goamd64: "v2"

     # IDs to filter the binaries/packages.
     ids:
       -mybuild
       -mynfpm

     # Templates of the Docker image names.
     #
     # Templates: allowed
     image_templates:
       - "myuser/myimage:latest"
       - "myuser/myimage:{{ .Tag }}"
       - "myuser/myimage:{{ .Tag }}-{{ .Env.FOOBAR }}"
       - "myuser/myimage:v{{ .Major }}"
       - "gcr.io/myuser/myimage:latest"

     # Skips the docker build.
     # Could be useful if you want to skip building the windows docker image on
     # linux, for example.
     #
     # Templates: allowed
     # Since: v1.14 (pro)
     # This option is only available on GoReleaser Pro.
     skip_build: false

     # 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 of a prerelease in the tag, e.g. v1.0.0-rc1.
     #
     # Templates: allowed (since v1.19)
     skip_push: false

     # Path to the Dockerfile (from the project root).
     #
     # Default: 'Dockerfile'
     dockerfile: "{{ .Env.DOCKERFILE }}"

     # Set the "backend" for the Docker pipe.
     #
     # Valid options are: docker, buildx, podman.
     #
     # Podman is a GoReleaser Pro feature and is only available on Linux.
     #
     # Default: 'docker'
     use:docker

     # Docker build flags.
     #
     # Templates: allowed
     build_flag_templates:
       - "--pull"
       - "--label=org.opencontainers.image.created={{.Date}}"
       - "--label=org.opencontainers.image.title={{.ProjectName}}"
       - "--label=org.opencontainers.image.revision={{.FullCommit}}"
       - "--label=org.opencontainers.image.version={{.Version}}"
       - "--build-arg=FOO={{.Env.Bar}}"
       - "--platform=linux/arm64"

     # Extra flags to be passed down to the push command.
     push_flags:
       - --tls-verify=false

     # If your Dockerfile copies files other than binaries and packages,
     # you should list them here as well.
     # Note that GoReleaser will create the same structure inside a 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 (usually the repository root folder).
     # 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

     # Additional templated extra files to add to the Docker image.
     # Those files will have their contents pass through the template engine,
     # and its results will be added to the build context the same way as the
     # extra_files field above.
     #
     # Since: v1.17 (pro)
     # This feature is only available in GoReleaser Pro.
     # Templates: allowed
     templated_extra_files:
       - src: LICENSE.tpl
         dst: LICENSE.txt
         mode: 0644

Docker Images

GoReleaser can build and push Docker images. Let’s see how it works.

You can declare multiple Docker images. They will be matched against section-generated binaries and section-generated packages.

If you only have a build setting, configuration is as simple as adding the image name to a file:

dockers:
   - image_templates:
       -user/repo

You also need to create one in the root folder of your project:

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

This configuration will build and push a Docker image named .

Customization

# .goreleaser.yaml
dockers:
   # You can have multiple Docker images.
   - #
     # ID of the image, needed if you want to filter by it later on (e.g. on custom publishers).
     id: myimg

     #GOOS of the built binariess/packages that should be used.
    # Default: 'linux'
    goos: linux

    # GOARCH of the built binaries/packages that should be used.
    # Default: 'amd64'
    goarch: amd64

    # GOARM of the built binaries/packages that should be used.
    # Default: '6'
    goarm: ""

    # GOAMD64 of the built binaries/packages that should be used.
    # Default: 'v1'
    goamd64: "v2"

    # IDs to filter the binaries/packages.
    ids:
      - mybuild
      - mynfpm

    # Templates of the Docker image names.
    #
    # Templates: allowed
    image_templates:
      - "myuser/myimage:latest"
      - "myuser/myimage:{{ .Tag }}"
      - "myuser/myimage:{{ .Tag }}-{{ .Env.FOOBAR }}"
      - "myuser/myimage:v{{ .Major }}"
      - "gcr.io/myuser/myimage:latest"

    # Skips the docker build.
    # Could be useful if you want to skip building the windows docker image on
    # linux, for example.
    #
    # Templates: allowed
    # Since: v1.14 (pro)
    # This option is only available on GoReleaser Pro.
    skip_build: false

    # 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 of a prerelease in the tag, e.g. v1.0.0-rc1.
    #
    # Templates: allowed (since v1.19)
    skip_push: false

    # Path to the Dockerfile (from the project root).
    #
    # Default: 'Dockerfile'
    dockerfile: "{{ .Env.DOCKERFILE }}"

    # Set the "backend" for the Docker pipe.
    #
    # Valid options are: docker, buildx, podman.
    #
    # Podman is a GoReleaser Pro feature and is only available on Linux.
    #
    # Default: 'docker'
    use: docker

    # Docker build flags.
    #
    # Templates: allowed
    build_flag_templates:
      - "--pull"
      - "--label=org.opencontainers.image.created={{.Date}}"
      - "--label=org.opencontainers.image.title={{.ProjectName}}"
      - "--label=org.opencontainers.image.revision={{.FullCommit}}"
      - "--label=org.opencontainers.image.version={{.Version}}"
      - "--build-arg=FOO={{.Env.Bar}}"
      - "--platform=linux/arm64"

    # Extra flags to be passed down to the push command.
    push_flags:
      - --tls-verify=false

    # If your Dockerfile copies files other than binaries and packages,
    # you should list them here as well.
    # Note that GoReleaser will create the same structure inside a 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 (usually the repository root folder).
    # 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

    # Additional templated extra files to add to the Docker image.
    # Those files will have their contents pass through the template engine,
    # and its results will be added to the build context the same way as the
    # extra_files field above.
    #
    # Since: v1.17 (pro)
    # This feature is only available in GoReleaser Pro.
    # Templates: allowed
    templated_extra_files:
      - src: LICENSE.tpl
        dst: LICENSE.txt
        mode: 0644

Please note that you must manually log in to the Docker registry you want to push to - GoReleaser will not log in for you.

Please note that you must manually log in to the Docker registry you want to push to - GoReleaser will not log in for you.

These settings should allow you to generate multiple Docker images, e.g. using multiple statements, generating one image for each binary in your project or one image with multiple binaries, as well as installing the generated packages instead of manually copying binaries and configuration.

Generic image names

Some users may want to make their image names as generic as possible. This can be achieved by adding template expressions in the definition:

# .goreleaser.yaml
project_name: foo
dockers:
  - image_templates:
      - "myuser/{{.ProjectName}}"

This will generate and publish the following images:

  • myuser/foo

Keeping the docker image up to date with the current main content

Some users may want to push the docker tags … and … as well as when (for example) building. This can be done by using multiple:

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

This will generate 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 push multiple Docker images with multiple tags.

Publishing to multiple docker registries

Some users may want to push their images to multiple docker registries. This can be done by using multiple:

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

This generates the following images and publishes them to docker.io and gcr.io:

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

Applying Docker build flags

You can use build_flag_templates to apply build flags. These flags must be valid Docker build flags.

# .goreleaser.yaml
dockers:
  - image_templates:
      - "myuser/myimage"
    build_flag_templates:
      - "--pull"
      - "--label=org.opencontainers.image.created={{.Date}}"
      - "--label=org.opencontainers.image.title={{.ProjectName}}"
      - "--label=org.opencontainers.image.revision={{.FullCommit}}"
      - "--label=org.opencontainers.image.version={{.Version}}"

This will execute the following command:

docker build -t myuser/myimage . \
   --pull \
   --label=org.opencontainers.image.created=2020-01-19T15:58:07Z \
   --label=org.opencontainers.image.title=mybinary \
   --label=org.opencontainers.image.revision=da39a3ee5e6b4b0d3255bfef95601890afd80709 \
   --label=org.opencontainers.image.version=1.6.4

Using specific builders with Docker buildx

If enabled, the context builder is used when building the image. This builder is always available and powered by BuildKit in the Docker engine. If you want to use a different builder, you can specify it using the following fields:

# .goreleaser.yaml
dockers:
   - image_templates:
       - "myuser/myimage"
     use: buildx
     build_flag_templates:
       - "--builder=mybuilder"

Podman

You can use instead by setting it on the config to:

# .goreleaser.yaml
dockers:
   - image_templates:
       - "myuser/myimage"
     use:podman

Please note that GoReleaser will not install Podman for you, nor will it change any of its configuration.

Docker Manifests

GoReleaser can also use the tool to create and push Docker multi-platform images.

There is no need to switch devices. We can directly build amd64, which is the Linux platform image, on the Apple M2 chip machine. The docker build command provides the --platform parameter to build a cross-platform image.

docker build --platform=linux/amd64 -t kubecub/echo-platform-amd64 .

What happens when running images for different platforms:

You may be wondering what will happen if you run an amd64 platform image on a host device with an Apple M2 chip. The simple image we have built so far can actually run, but you will get a warning message:

$ docker run --rm kubecub/echo-platform-amd64
WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
Linux buildkitsandbox 5.15.49-linuxkit #1 SMP PREEMPT Tue Sep 13 07:51:32 UTC 2022 x86_64 Linux

x86_64 in the output content means AMD64 architecture.

Note: Although this simple image can run successfully, if the program inside the container does not support cross-platform, the amd64 platform image cannot run successfully on the arm64 platform.

Use manifest to merge multi-platform images

We can use the create subcommand of docker manifest to create a manifest list, that is, to merge the images of multiple platforms into one image.

The usage of the create command is very simple. The first parameter jianghushinian/echo-platform followed is the merged image. Starting from the second parameter, you can specify one or more images of different platforms.

docker manifest create kubecub/echo-platform kubecub/echo-platform-arm64 kubecub/echo-platform-amd64

Log in to Docker Hub in the browser to view the successfully pushed image:

Enter the Tags tab of the image information details page, and you can see that the image supports the two platforms amd64 and arm64/v8.

Manifest command

It can be found that docker manifest provides a total of 5 sub-commands: annotate, create, inspect, push, and rm.

It can be found that the create subcommand supports two optional parameters -a/--amend to modify existing multi-architecture images.

Specifying the --insecure parameter allows the use of insecure (non-https) mirror repositories.

push

We have also seen the push subcommand. Using push we can push multi-architecture images to the image warehouse.

Similarly, push also has a --insecure parameter that allows the use of insecure (non-https) mirror repositories.

  • The function of the p/--purge option is to delete the local manifest list after pushing the local image to the remote warehouse.

inspect

inspect is used to view the image information contained in manifest/manifest list.

The --insecure parameter allows the use of insecure (non-https) mirror repositories. This is the third time we have seen this parameter, which also verifies the statement that the docker manifest command requires an Internet connection to be used, because these subcommands basically involve interaction with the remote mirror repository.

annotate

The annotate subcommand can add additional information to a local image manifest. This is a bit like what K8s Annotations means.

The optional parameter list is as follows:

OptionsDescription
–archSet CPU architecture information.
–osSet operating system information.
–os-featuresSet operating system feature information.
–os-versionSet operating system version information.
–variantSet the variant information of the CPU architecture (translated as “variant”), such as v7, v8, etc. of the ARM architecture.

rm

The last subcommand to be introduced is rm. Use rm to delete one or more local multi-architecture mirrors (manifest lists).

###Customization

You can create multiple manifests in one GoReleaser run, here are all the available options:

# .goreleaser.yaml
docker_manifests:
   # You can have multiple Docker manifests.
-
   # ID of the manifest, needed if you want to filter by it later on (e.g. on
   # custom publishers).
   id: myimg

   # Name for the manifest.
   #
   # Templates: allowed
   name_template: "foo/bar:{{ .Version }}"

   # Image name to be added to this manifest.
   #
   # Templates: allowed
   image_templates:
   - "foo/bar:{{ .Version }}-amd64"
   - "foo/bar:{{ .Version }}-arm64v8"

   # Extra flags to be passed down to the manifest create command.
   create_flags:
   - --insecure

   # Extra flags to be passed down to the manifest push command.
   push_flags:
   - --insecure

   # Skips the Docker manifest.
   # If you set this to `false` or `auto` on your source Docker configuration,
   # you'll probably want to do the same here.
   #
   # If set to `auto`, the manifest will not be created in case there is an
   # indicator of a prerelease in the tag, e.g. v1.0.0-rc1.
   #
   # Templates: allowed (since v1.19)
   skip_push: false

   # Set the "backend" for the Docker manifest pipe.
   # Valid options are: docker, podman
   #
   # Relevant notes:
   # 1. podman is a GoReleaser Pro feature and is only available on Linux;
   # 2. if you set podman here, the respective docker configuration need to use
   #podman too.
   #
   # Default: 'docker'
   use:docker

KO

https://github.com/ko-build/ko

KO is Build and deploy Go applications

installdocs:

Installation - ko: Easy Go Containers

User Actions:

steps:
- uses: imjasonh/setup-ko@v0.6

User Ko:

ko depends on the authentication configured in the Docker configuration (usually ~/.docker/config.json).

✨**If you can push images using docker push, you have passed the statusVerify ko! **✨

Since ko does not require docker, ko login also provides an interface to log into the container image registry using a username and password, similar to [docker login](https://docs.docker.com/engine/ reference/commandline/login/).

Additionally, even if authentication is not configured in the Docker configuration, ko includes built-in support for authenticating to the following container registries using credentials configured in the environment:

ko depends on the environment variable KO_DOCKER_REPO to determine where its built image should be pushed. Typically this will be the remote registry, for example:

  • KO_DOCKER_REPO=gcr.io/my-project, or
  • KO_DOCKER_REPO=ghcr.io/my-org/my-repo, or
  • KO_DOCKER_REPO=my-dockerhub-user

step:

echo "***" | docker login ghcr.io -u kuebcub --password-stdin
export GITHUB_TOKEN="******"
export KO_DOCKER_REPO=ghcr.io/kubecub/exporter; ko build ./cmd/exporter

test:

docker run -p 8080:8080 $(ko build ./cmd/app)

Docker Images with Ko

Note that ko will build your binary again. This shouldn’t increase release time too much, as it will use the same build options as the build pipeline where possible, so the results may be cached.

# .goreleaser.yaml
kos:
-
   # ID of this image.
   id: foo

   # Build ID that should be used to import the build settings.
   build: build-id

   # Main path to build.
   #
   # Default: build.main
   main: ./cmd/...

   # Working directory used to build.
   #
   # Default: build.dir
   working_dir: .

   # Base image to publish to use.
   #
   # Default: 'cgr.dev/chainguard/static'
   base_image: alpine

   # Labels for the image.
   #
   # Since: v1.17
   labels:
     foo: bar

   # Repository to push to.
   #
   # Default: $KO_DOCKER_REPO
   repository: ghcr.io/foo/bar

   # Platforms to build and publish.
   #
   # Default: 'linux/amd64'
   platforms:
   - linux/amd64
   - linux/arm64

   # Tag to build and push.
   # Empty tags are ignored.
   #
   # Default: 'latest'
   # Templates: allowed
   tags:
   -latest
   - '{{.Tag}}'
   - '{{if not .Prerelease}}stable{{end}}'

   # Creation time given to the image
   # in seconds since the Unix epoch as a string.
   #
   # Since: v1.17
   # Templates: allowed
   creation_time: '{{.CommitTimestamp}}'

   # Creation time given to the files in the kodata directory
   # in seconds since the Unix epoch as a string.
   #
   # Since: v1.17
   # Templates: allowed
   ko_data_creation_time: '{{.CommitTimestamp}}'

   # SBOM format to use.
   #
   # Default: 'spdx'
   # Valid options are: spdx, cyclonedx, go.version-m and none.
   sbom: none

   # Ldflags to use on build.
   #
   # Default: build.ldflags
   ldflags:
   - foo
   - bar

   # Flags to use on build.
   #
   # Default: build.flags
   flags:
   - foo
   - bar

   # Env to use on build.
   #
   # Default: build.env
   env:
   - FOO=bar
   - SOMETHING=value

   # Bare uses a tag on the $KO_DOCKER_REPO without anything additional.
   bare: true

   # Whether to preserve the full import path after the repository name.
   preserve_import_paths: true

   # Whether to use the base path without the MD5 hash after the repository name.
   base_import_paths: true

Here’s a minimal example:

# .goreleaser.yml
before:
   hooks:
     - go mod tidy

builds:
   - env: [ "CGO_ENABLED=1" ]
     binary: test
     goos:
     - darwin
     - linux
     goarch:
     -amd64
     - arch64

kos:
   - repository: ghcr.io/caarlos0/test-ko
     tags:
     - '{{.Version}}'
     -latest
     bare: true
     preserve_import_paths: false
     platforms:
     - linux/amd64
     - linux/arm64

This will build binaries for , , and Docker images and manifests for Linux.

Package size

# .goreleaser.yaml
# Whether to enable the size reporting or not.
report_sizes: true

Metadata Metadata

GoReleaser creates some metadata files in the folder before finishing running.

# .goreleaser.yaml
#
metadata:
   # Set the modified timestamp on the metadata files.
   #
   # Templates: allowed.
   mod_timestamp: "{{ .CommitTimestamp }}"

Signature verification

GoReleaser provides methods for signing executable files and archives.

Signatures are used in conjunction with a checksum file, and it is usually sufficient to just sign the checksum file.

The default configuration is to create a standalone signature for the checksum file using GnuPG , along with your default key. To enable signing just add

# .goreleaser.yaml
signs:
   - artifacts: checksum

To customize the signing pipeline, you have the following options:

# .goreleaser.yaml
signs:
   -
     # ID of the sign config, must be unique.
     #
     # Default: 'default'
     id: foo

     # Name of the signature file.
     #
     # Default: '${artifact}.sig'
     # Templates: allowed
     signature: "${artifact}_sig"

     # Path to the signature command
     #
     # Default: '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} "]
     #
     # Default: ["--output", "${signature}", "--detach-sign", "${artifact}"]
     # Templates: allowed
     args: ["--output", "${signature}", "${artifact}", "{{ .ProjectName }}"]

     # Which artifacts to sign
     #
     # all: all artifacts
     # none: no signing
     # checksum: only checksum file(s)
     # source: source archive
     # package: linux packages (deb, rpm, apk)
     # archive: archives from archive pipe
    #   binary:   binaries if archiving format is set to binary
    #   sbom:     any Software Bill of Materials generated for other artifacts
    #
    # Default: 'none'
    artifacts: all

    # IDs of the artifacts to sign.
    #
    # If `artifacts` is checksum or source, this fields has no effect.
    ids:
      - foo
      - bar

    # Stdin data to be given to the signature command as stdin.
    #
    # Templates: allowed
    stdin: '{{ .Env.GPG_PASSWORD }}'

    # StdinFile file to be given to the signature command as stdin.
    stdin_file: ./.password

    # Sets a certificate that your signing command should write to.
    # You can later use `${certificate}` or `.Env.certificate` in the `args` section.
    # This is particularly useful for keyless signing (for instance, with cosign).
    # Note that this should be a name, not a path.
    certificate: '{{ trimsuffix .Env.artifact ".tar.gz" }}.pem'

    # List of environment variables that will be passed to the signing command
    # as well as the templates.
    env:
    - FOO=bar
    - HONK=honkhonk

    # By default, the stdout and stderr of the signing cmd are discarded unless
    # GoReleaser is running with `--debug` set.
    # You can set this to true if you want them to be displayed regardless.
    #
    # Since: v1.2
    output: true

Available variable names

These environment variables may be available in fields that accept templates:

  • ${artifact}: the path of the artifact to be signed
  • ${artifactID}: the ID of the artifact to be signed
  • ${certificate}: the certificate file name (if provided)
  • ${signature}: the signature file name

Assuming you have a cosign.key in the repository root and the COSIGN_PWD environment variable set, a simple usage example follows:

# .goreleaser.yaml
signs:
- cmd: cosign
  stdin: '{{ .Env.COSIGN_PWD }}'
  args:
  - "sign-blob"
  - "--key=cosign.key"
  - "--output-signature=${signature}"
  - "${artifact}"
  - "--yes" # needed on cosign 2.0.0+
  artifacts: all

Then, your users can verify the signature as follows:

cosign verify-blob -key cosign.pub -signature file.tar.gz.sig file.tar.gz

Signing Docker images and manifests

GoReleaser can also sign Docker images and manifests. This pipeline is designed after the generic signs pipeline, with co-signing in mind.

# .goreleaser.yml
docker_signs:
  -
    # ID of the sign config, must be unique.
    # Only relevant if you want to produce some sort of signature file.
    #
    # Default: 'default'
    id: foo

    # Path to the signature command
    #
    # Default: 'cosign'
    cmd: cosign

    # Command line arguments for the command
    #
    # Templates: allowed
    # Default: ["sign", "--key=cosign.key", "${artifact}@${digest}", "--yes"]
    args:
    - "sign"
    - "--key=cosign.key"
    - "--upload=false"
    - "${artifact}"
    - "--yes" # needed on cosign 2.0.0+

    # Which artifacts to sign
    #
    #   all:       all artifacts
    #   none:      no signing
    #   images:    only docker images
    #   manifests: only docker manifests
    #
    # Default: 'none'
    artifacts: all

    # IDs of the artifacts to sign.
    ids:
      - foo
      - bar

    # Stdin data to be given to the signature command as stdin.
    #
    # Templates: allowed
    stdin: '{{ .Env.COSIGN_PWD }}'

    # StdinFile file to be given to the signature command as stdin.
    stdin_file: ./.password

    # List of environment variables that will be passed to the signing command as well as the templates.
    env:
    - FOO=bar
    - HONK=honkhonk

    # By default, the stdout and stderr of the signing cmd are discarded unless GoReleaser is running with `--debug` set.
    # You can set this to true if you want them to be displayed regardless.
    #
    # Since: v1.2
    output: true

These environment variables may be available in fields that support templates:

  • ${artifact}: the path of the item to be signed
  • ${digest}: the digest of the image/manifest to be signed
  • ${artifactID}: the ID of the item to be signed
  • ${certificate}: the certificate file name (if provided)

Release

GoReleaser can create GitHub/GitLab/Gitea releases with the current tag, upload all artifacts, and generate a changelog from the new commits since the previous tag.

Let’s take a look at what can be customized in the GitHub section:

# .goreleaser.yaml
release:
  # Repo in which the release will be created.
  # Default is extracted from the origin remote URL or empty if its private hosted.
  github:
    owner: user
    name: repo

  # IDs of the archives to use.
  # Empty means all IDs.
  #
  # Default: []
  ids:
    - foo
    - bar

  # If set to true, will not auto-publish the release.
  # Available only for GitHub and Gitea.
  #
  # Default: false
  draft: false

  # Whether to remove existing draft releases with the same name before creating
  # a new one.
  # Only effective if `draft` is set to true.
  # Available only for GitHub.
  #
  # Default: false
  # Since: v1.11
  replace_existing_draft: false

  # Useful if you want to delay the creation of the tag in the remote.
  # You can create the tag locally, but not push it, and run GoReleaser.
  # It'll then set the `target_commitish` portion of the GitHub release to the
  # value of this field.
  # Only works on GitHub.
  #
  # Default: ''
  # Since: v1.11
  # Templates: allowed
  target_commitish: "{{ .Commit }}"

  # This allows to change which tag GitHub will create.
  # Usually you'll use this together with `target_commitish`, or if you want to
  # publish a binary from a monorepo into a public repository somewhere,without
  # the tag prefix.
  #
  # Default: '{{ .PrefixedCurrentTag }}'
  # Since: v1.19 (pro)
  # Templates: allowed
  tag: "{{ .CurrentTag }}"

  # If set, will create a release discussion in the category specified.
  #
  # Warning: do not use categories in the 'Announcement' format.
  #  Check https://github.com/goreleaser/goreleaser/issues/2304 for more info.
  #
  # Default is empty.
  discussion_category_name: General

  # 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

  # If set to false, will NOT mark the release as "latest".
  # This prevents it from being shown at the top of the release list,
  # and from being returned when calling https://api.github.com/repos/OWNER/REPO/releases/latest.
  #
  # Available only for GitHub.
  #
  # Default is true.
  # Since: v1.20.
  make_latest: true

  # What to do with the release notes in case there the release already exists.
  #
  # Valid options are:
  # - `keep-existing`: keep the existing notes
  # - `append`: append the current release notes to the existing notes
  # - `prepend`: prepend the current release notes to the existing notes
  # - `replace`: replace existing notes
  #
  # Default is `keep-existing`.
  mode: append

  # Header for the release body.
  #
  # Templates: allowed
  header: |
    ## Some title ({{ .Date }})

    Welcome to this new release!

  # Footer for the release body.
  #
  # Templates: allowed
  footer: |
    ## Thanks!

    Those were the changes on {{ .Tag }}!

  # You can change the name of the release.
  #
  # Default: '{{.Tag}}' ('{{.PrefixedTag}}' on Pro)
  # Templates: allowed
  name_template: "{{.ProjectName}}-v{{.Version}} {{.Env.USER}}"

  # You can disable this pipe in order to not create the release on any SCM.
  # Keep in mind that this might also break things that depend on the release
  # URL, for instance, homebrew taps.
  #
  # Templates: allowed (since v1.15)
  disable: true

  # Set this to true if you want to disable just the artifact upload to the SCM.
  # If this is true, GoReleaser will still create the release with the
  # changelog, but won't upload anything to it.
  #
  # Since: v1.11
  # Templates: allowed (since v1.15)
  skip_upload: true

  # You can add extra pre-existing files to the release.
  # The filename on the release will be the last part of the path (base).
  # If another file with the same name exists, the last one found will be used.
  #
  # Templates: allowed
  extra_files:
    - glob: ./path/to/file.txt
    - glob: ./glob/**/to/**/file/**/*
    - glob: ./glob/foo/to/bar/file/foobar/override_from_previous
    - glob: ./single_file.txt
      name_template: file.txt # note that this only works if glob matches 1 file only

  # Additional templated extra files to add to the release.
  # Those files will have their contents pass through the template engine,
  # and its results will be added to the release.
  #
  # Since: v1.17 (pro)
  # This feature is only available in GoReleaser Pro.
  # Templates: allowed
  templated_extra_files:
    - src: LICENSE.tpl
      dst: LICENSE.txt

GPG authentication

GitHub supports several GPG key algorithms. If you try to add a key generated with an unsupported algorithm, you may encounter errors.

Checking existing GPG keys

Use the gpg --list-secret-keys --keyid-format=long command to list the long form of the GPG keys for which you have both a public and private key. Signing commits or tags requires the private key.

gpg --list-secret-keys --keyid-format=long

Generating a new GPG key

Validated via git parameters. Configuration:

git config --global gpg.program gpg2

Generate the key pair:

gpg --full-generate-key

Check the key pair:

gpg --list-secret-keys --keyid-format=long

From the GPG key list, copy the full form of the GPG key ID you want to use.

  1. In this example, the GPG key ID is 3AA5C34371567BD2:

    $ gpg --list-secret-keys --keyid-format=long
    /Users/hubot/.gnupg/secring.gpg
    ------------------------------------
    sec   4096R/3AA5C34371567BD2 2016-03-10 [expires: 2017-03-10]
    uid                          Hubot <hubot@example.com>
    ssb   4096R/4BB6D45482678BE3 2016-03-10
    
  2. Paste the text below, replacing it with the GPG key ID you want to use. In this example, the GPG key ID is 3AA5C34371567BD2:

    gpg --armor --export 3AA5C34371567BD2
    # Prints the GPG key ID, in ASCII armor format
    
  3. Copy your GPG key, beginning with ----BEGIN PGP PUBLIC KEY BLOCK----- and ending with ----END PGP PUBLIC KEY BLOCK-----.

cat /root/.gnupg/openpgp-revocs.d/4DDA37AE0F3AEA3044B33F1B1BAD6F395338EFDE.rev

Then just link this key to your GitHub account. This step is very simple and will not be covered here

Tell Git your signing key:

You also need to tell Git about your signing key, because if you have multiple GPG keys, you need to tell Git which one to use.

  1. If you previously configured Git to use a different key format when signing with openpgp, unset this configuration so that the -gpg-sign default format is used.

    git config --global --unset gpg.format
    

Use the gpg --list-secret-keys --keyid-format=long command to list the long form of the GPG keys for which you have both a public and private key. Signing commits or tags requires the private key.

gpg --list-secret-keys --keyid-format=long

From the GPG key list, copy the full form of the GPG key ID you want to use. In this example, the GPG key ID is 3AA5C34371567BD2:

$ gpg --list-secret-keys --keyid-format=long
/Users/hubot/.gnupg/secring.gpg
-------------------------------------
sec 4096R/3AA5C34371567BD2 2016-03-10 [expires: 2017-03-10]
uid Hubot <hubot@example.com>
ssb 4096R/4BB6D45482678BE3 2016-03-10

To set a master GPG signing key in Git, paste the text below and replace it with the GPG master key ID you want to use. In this example, the GPG key ID is 3AA5C34371567BD2:

git config --global user.signingkey 3AA5C34371567BD2

Alternatively, include the suffix ! when setting the subkey. In this example, the GPG subkey ID is 4BB6D45482678BE3:

git config --global user.signingkey 4BB6D45482678BE3!

Alternatively, to configure Git to sign all commits by default, enter the following command:

git config --global commit.gpgsign true

You can use an existing SSH key to sign commits and tags, or generate a new key specifically for signing. For more information, see “[Generating new SSH keys and adding them to ssh-agent](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating -a-new-ssh-key-and-adding-it-to-the-ssh-agent)”.

Notice:

We may need to add export GPG_TTY=$(tty) to the environment variables

Signature tag

$ git tag -s MYTAG
# Creates a signed tag

Verify your signing tag by running git tag -v [tag-name].

$ git tag -v MYTAG
# Verifies the signed tag

Cloud storage service

Allows you to upload artifacts to Amazon S3, Azure Blob, and Google GCS.

In fact, it’s not just these, but also domestic COS and CSS.

# .goreleaser.yaml
blobs:
   # You can have multiple blob configs
   - # Cloud provider name:
     # - s3 for AWS S3 Storage
     # - azblob for Azure Blob Storage
     # - gs for Google Cloud Storage
     #
     # Templates: allowed
     provider: azblob

     # Set a custom endpoint, useful if you're using a minio backend or
     # other s3-compatible backends.
     #
     # Implies s3ForcePathStyle and requires provider to be `s3`
     #
     # Templates: allowed
     endpoint: https://minio.foo.bar

     # Sets the bucket region.
     # Requires provider to be `s3`
     #
     # Templates: allowed
     region: us-west-1

     # Disables SSL
     # Requires provider to be `s3`
     disableSSL: true

     # Bucket name.
     #
     # Templates: allowed
     bucket: goreleaser-bucket

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

     # Path/name inside the bucket.
     #
     # Default: '{{ .ProjectName }}/{{ .Tag }}'
     # Templates: allowed
     folder: "foo/bar/{{.Version}}"

     # Whether to disable this particular upload configuration.
     #
     # Since: v1.17
     # Templates: allowed
     disable: '{{ neq .BLOB_UPLOAD_ONLY "foo" }}'

     # You can add extra pre-existing files to the bucket.
     # The filename on the release will be the last part of the path (base).
     # If another file with the same name exists, the last one found will be used.
     # These globs can also include templates.
     extra_files:
       - glob: ./path/to/file.txt
       - glob: ./glob/**/to/**/file/**/*
       - glob: ./glob/foo/to/bar/file/foobar/override_from_previous
       - glob: ./single_file.txt
         # Templates: allowed
         name_template: file.txt # note that this only works if glob matches 1 file only

     # Additional templated extra files to uploaded.
     # Those files will have their contents pass through the template engine,
     # and its results will be uploaded.
     #
     # Since: v1.17 (pro)
     # This feature is only available in GoReleaser Pro.
     # Templates: allowed
     templated_extra_files:
       - src: LICENSE.tpl
         dst: LICENSE.txt

   - provider: gs
     bucket: goreleaser-bucket
     folder: "foo/bar/{{.Version}}"
   - provider: s3
     bucket: goreleaser-bucket
     folder: "foo/bar/{{.Version}}"

Fury.io (apt and rpm repositories)

This is an advanced feature, but sealos also uses it, using bash logic

You can easily create and repository on fury.io using GoReleaser.

First, you need to create an account on fury.io and get a push token.

You then need to pass your account name to GoReleaser and your push token as a file named FURY_TOKEN :

# .goreleaser.yaml
furies:
-account:myaccount

This will automatically upload all your files.

customize:

# goreleaser.yaml

furies:
   -
     # fury.io account.
     # Config is skipped if empty
     account: "{{ .Env.FURY_ACCOUNT }}"

     # Skip the announced feature in some conditions, for instance, when
     # publishing patch releases.
     # Any value different of 'true' will be considered 'false'.
     #
     # Templates: allowed
     skip: "{{gt .Patch 0}}"

     # Environment variable name to get the push token from.
     # You might want to change it if you have multiple fury configurations for
     # some reason.
     #
     # Default: 'FURY_TOKEN'
     secret_name: MY_ACCOUNT_FURY_TOKEN

     # IDs to filter by.
     # configurations get uploaded.
     ids:
       - packages

     # Formats to upload.
     # Available options are `deb` and `rpm`.
     #
     # Default: ['deb', 'rpm']
     formats:
       -deb

Homebrew Taps

After publishing to GitHub, GitLab, or Gitea, GoReleaser can generate homebrew-tap and publish it to a repository that you have access to.

Announce

GoReleaser can also announce new releases on social networks, chat rooms and email!

It is run at the very end of the pipeline and can be skipped using the command’s flags or via the skip attribute:

# .goreleaser.yaml
announce:
   # Skip the announced feature in some conditions, for instance, when
   # publishing patch releases.
   #
   # Any value different from 'true' is evaluated to false.
   #
   # Templates: allowed
   skip: "{{gt .Patch 0}}"

Currently supports many accounts

Discode:

To use Discord, you need to create a Webhook and set the following environment variables on the pipe:

  • DISCORD_WEBHOOK_ID
  • DISCORD_WEBHOOK_TOKEN

After this you can add the following section to your configuration:

# .goreleaser.yaml
announce:
   discord:
     # Whether its enabled or not.
     enabled: true

     # Message template to use while publishing.
     #
     # Default: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
     # Templates: allowed
     message_template: 'Awesome project {{.Tag}} is out!'

     # Set author of the embed.
     #
     # Default: 'GoReleaser'
     author: ''

     # Color code of the embed. You have to use decimal numeral system, not hexadecimal.
     #
     # Default: '3888754' (the grey-ish from GoReleaser)
     color: ''

     # URL to an image to use as the icon for the embed.
     #
     # Default: 'https://goreleaser.com/static/avatar.png'
     icon_url: ''

To make it work, you need to set some environment variables on the pipe:

  • LINKEDIN_ACCESS_TOKEN

We currently don’t support posting in groups.

You can then add something like the following to your configuration:

# .goreleaser.yaml
announce:
   linkedin:
     # Whether its enabled or not.
     enabled: true

     # Message to use while publishing.
     #
     # Default: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
     message_template: 'Awesome project {{.Tag}} is out!'

slack

Like discode, slack also needs to pass in a new Webhook

  • SLACK_WEBHOOK

You can then add something like the following to your configuration:

# .goreleaser.yaml
announce:
   slack:
     # Whether its enabled or not.
     enabled: true

     ****# Message template to use while publishing.
     #
     # Default: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
     # Templates: allowed
     message_template: 'Awesome project {{.Tag}} is out!'

     # The name of the channel that the user selected as a destination for webhook messages.
     channel: '#channel'

     # Set your Webhook's user name.
     username: ''

     # Emoji to use as the icon for this message. Overrides icon_url.
     icon_emoji: ''

     # URL to an image to use as the icon for this message.
     icon_url: ''

     # Blocks for advanced formatting, see: https://api.slack.com/messaging/webhooks#advanced_message_formatting
     # and https://api.slack.com/messaging/composing/layouts#adding-blocks.
     #
     # Attention: goreleaser doesn't check the structure full of the Slack API: please make sure that
     # your configuration for advanced message formatting abides by this API.
     #
     # Templates: allowed
     blocks: []

     # Attachments, see: https://api.slack.com/reference/messaging/attachments
     #
     # Attention: goreleaser doesn't check the structure full of the Slack API: please make sure that
     # your configuration for advanced message formatting abides by this API.
     #
     # Templates: allowed
     attachments: []

References

Responses

— Join the Dialogue

New posts, straight to your inbox

One email per new post. Double opt-in, unsubscribe anytime.