Skip to content

feat: add GoReleaser configuration file#21

Merged
tmknom merged 10 commits intomainfrom
feat/add-goreleaser-config-for-default
Dec 23, 2024
Merged

feat: add GoReleaser configuration file#21
tmknom merged 10 commits intomainfrom
feat/add-goreleaser-config-for-default

Conversation

@tmknom
Copy link
Copy Markdown
Owner

@tmknom tmknom commented Dec 23, 2024

The GoReleaser configuration file, written in YAML, forms the foundation of GoReleaser, a robust tool built to automate and simplify the release process for Go projects. This configuration file defines all the necessary steps for packaging, signing, and releasing Go binaries, Docker images, and other related artifacts across various platforms. By leveraging GoReleaser, developers can ensure their release process is consistent, reproducible, and secure. This significantly simplifies the task of managing releases while maintaining a high level of reliability and efficiency.

The GoReleaser configuration file, written in YAML, forms the foundation of **GoReleaser**, a robust tool built to automate and simplify the release process for Go projects.
This configuration file defines all the necessary steps for packaging,signing, and releasing Go binaries, Docker images, and other related artifacts across various platforms.
By leveraging GoReleaser, developers can ensure their release process is consistent, reproducible, and secure.
This significantly simplifies the task of managing releases while maintaining a high level of reliability and efficiency.

---

# Quoting the GoReleaser documentation:

---

- https://goreleaser.com/how-it-works/

## How it works

GoReleaser's goal is to automate most of the boring work you'll have while
releasing software, ideally using sensible defaults and making the most common
use cases easy.

GoReleaser expects a couple of things:

- a `.goreleaser.yaml` file with the configuration (see the
  [customization section](./customization/index.md) for more info)
- a clean working tree
- a SemVer-compatible version (e.g. `10.21.34-prerelease+buildmeta`)

And that's it.

### What happens when you release

A GoReleaser run is split into 4 major steps:

- **defaulting**: configures sensible defaults for each step
- **building**: builds the binaries, archives, packages, Docker images, etc
- **publishing**: publishes the release to the configured SCM, Docker
  registries, blob storages...
- **announcing**: announces your release to the configured channels

Some steps might be skipped with `--skip` flags (check the
[command line docs](./cmd/goreleaser.md) for details).

If any of the previous steps fails, the next steps will not run.

---

- https://goreleaser.com/customization/templates/

## 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 be explicit about which fields
support templating.

### Common Fields

In fields that support templates, these fields are always available:

| Key                    | Description                                                                                                |
| ---------------------- | ---------------------------------------------------------------------------------------------------------- |
| `.ProjectName`         | the project name                                                                                           |
| `.Version`             | the version being released[^version-prefix]                                                                |
| `.Branch`              | the current git branch                                                                                     |
| `.PrefixedTag`         | the current git tag prefixed with the monorepo config tag prefix (if any)                                  |
| `.Tag`                 | the current git tag                                                                                        |
| `.PrefixedPreviousTag` | the previous git tag prefixed with the monorepo config tag prefix (if any)                                 |
| `.PreviousTag`         | the previous git tag, or empty if no previous tags                                                         |
| `.ShortCommit`         | the git commit short hash                                                                                  |
| `.FullCommit`          | the git commit full hash                                                                                   |
| `.Commit`              | the git commit hash (deprecated)                                                                           |
| `.CommitDate`          | the UTC commit date in RFC 3339 format                                                                     |
| `.CommitTimestamp`     | the UTC commit date in Unix format                                                                         |
| `.GitURL`              | the git remote url                                                                                         |
| `.GitTreeState`        | either 'clean' or 'dirty'                                                                                  |
| `.IsGitClean`          | whether or not current git state is clean                                                                  |
| `.IsGitDirty`          | whether or not current git state is dirty                                                                  |
| `.Major`               | the major part of the version[^tag-is-semver]                                                              |
| `.Minor`               | the minor part of the version[^tag-is-semver]                                                              |
| `.Patch`               | the patch part of the version[^tag-is-semver]                                                              |
| `.Prerelease`          | the prerelease part of the version, e.g. `beta`[^tag-is-semver]                                            |
| `.RawVersion`          | composed of `{Major}.{Minor}.{Patch}` [^tag-is-semver]                                                     |
| `.ReleaseNotes`        | the generated release notes, available after the changelog step has been executed                          |
| `.IsDraft`             | `true` if `release.draft` is set in the configuration, `false` otherwise                                   |
| `.IsSnapshot`          | `true` if `--snapshot` is set, `false` otherwise                                                           |
| `.IsNightly`           | `true` if `--nightly` is set, `false` otherwise                                                            |
| `.IsSingleTarget`      | `true` if `--single-target` is set, `false` otherwise (since v2.3)                                         |
| `.Env`                 | a map with system's environment variables                                                                  |
| `.Date`                | current UTC date in RFC 3339 format                                                                        |
| `.Now`                 | current UTC date as `time.Time` struct, allows all `time.Time` functions (e.g. `{{ .Now.Format "2006" }}`) |
| `.Timestamp`           | current UTC time in Unix format                                                                            |
| `.ModulePath`          | the go module path, as reported by `go list -m`                                                            |
| `.ReleaseURL`          | the current release download url[^scm-release-url]                                                         |
| `.Summary`             | the git summary, e.g. `v1.0.0-10-g34f56g3`[^git-summary]                                                   |
| `.PrefixedSummary`     | the git summary prefixed with the monorepo config tag prefix (if any)                                      |
| `.TagSubject`          | the annotated tag message subject, or the message subject of the commit it points out[^git-tag-subject]    |
| `.TagContents`         | the annotated tag message, or the message of the commit it points out[^git-tag-body]                       |
| `.TagBody`             | the annotated tag message's body, or the message's body of the commit it points out[^git-tag-body]         |
| `.Runtime.Goos`        | equivalent to `runtime.GOOS`                                                                               |
| `.Runtime.Goarch`      | equivalent to `runtime.GOARCH`                                                                             |
| `.Artifacts`           | the current artifact list. See table below for fields[^pro]                                                |

[^pro]: This feature is only available in [GoReleaser Pro](/pro).

[^version-prefix]:
    The `v` prefix is stripped, and it might be changed in
    `snapshot` and `nightly` builds.

[^tag-is-semver]: Assuming `Tag` is a valid a SemVer, otherwise empty/zeroed.

[^scm-release-url]:
    Composed of the current SCM's download URL and current tag.
    For instance, on GitHub, it'll be
    `https://github.com/{owner}/{repo}/releases/tag/{tag}`.

[^git-summary]:
    It is generated by `git describe --dirty --always --tags`, the
    format will be `{Tag}-$N-{CommitSHA}`

[^git-tag-subject]: As reported by `git tag -l --format='%(contents:subject)'`

[^git-tag-body]: As reported by `git tag -l --format='%(contents)'`

### Artifacts

<!-- md:featpro -->

If you use the `.Artifacts` field, it evaluates to an
[`artifact.Artifact` list](https://pkg.go.dev/github.com/goreleaser/goreleaser@main/internal/artifact#Artifact).
You should be able to use all its fields on each item:

- `.Name`
- `.Path`
- `.Goos`
- `.Goarch`
- `.Goarm`
- `.Gomips`
- `.Goamd64`
- `.Goarm64` (since v2.4)
- `.Gomips64` (since v2.4)
- `.Goppc64` (since v2.4)
- `.Goriscv64` (since v2.4)
- `.Go386` (since v2.4)
- `.Target` (Since v2.5)
- `.Type`
- `.Extra`

### Single-artifact extra fields

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

| Key             | Description                                   |
| --------------- | --------------------------------------------- |
| `.Os`           | `GOOS`                                        |
| `.Arch`         | `GOARCH`                                      |
| `.Arm`          | `GOARM`                                       |
| `.Mips`         | `GOMIPS`                                      |
| `.Amd64`        | `GOAMD64`                                     |
| `.Arm64`        | `GOARM64` (since v2.4)                        |
| `.Mips64`       | `GOMIPS64` (since v2.4)                       |
| `.Ppc64`        | `GOPPC64` (since v2.4)                        |
| `.Riscv64`      | `GORISCV64` (since v2.4)                      |
| `.I386`         | `GO386` (since v2.4)                          |
| `.Target`       | the whole target (since v2.5)                 |
| `.Binary`       | artifact name                                 |
| `.ArtifactID`   | artifact id (since v2.3[^pro])                |
| `.ArtifactName` | artifact name                                 |
| `.ArtifactPath` | absolute path to artifact                     |
| `.ArtifactExt`  | artifact extension (e.g. `.exe`, `.dmg`, etc) |

### nFPM extra fields

In the nFPM name template field, you can use those extra fields:

| Key                      | Description                                                     |
| ------------------------ | --------------------------------------------------------------- |
| `.Release`               | release from the nfpm config                                    |
| `.Epoch`                 | epoch from the nfpm config                                      |
| `.PackageName`           | package the name. Same as `ProjectName` if not overridden.      |
| `.ConventionalFileName`  | conventional package file name as provided by nFPM.[^arm-names] |
| `.ConventionalExtension` | conventional package extension as provided by nFPM              |
| `.Format`                | package format                                                  |

[^arm-names]:
    Please beware: some OSs might have the same names for different
    ARM versions, for example, for Debian both ARMv6 and ARMv7 are called `armhf`.
    Make sure that's not your case otherwise you might end up with colliding
    names. It also does not handle multiple GOAMD64 versions.

### Release body extra fields

In the `release.body` field, you can use these extra fields:

| Key          | Description                                                                                                                               |
| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `.Checksums` | the current checksum file contents, or a map of filename/checksum contents if `checksum.split` is set. Only available in the release body |

### Functions

On all fields, you have these available functions:

| Usage                             | Description                                                                                                                |
| --------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `replace "v1.2" "v" ""`           | replaces all matches. See [ReplaceAll](https://pkg.go.dev/strings#ReplaceAll).                                             |
| `split "1.2" "."`                 | split string at separator. See [Split](https://pkg.go.dev/strings#Split)                                                   |
| `time "01/02/2006"`               | current UTC time in the specified format (this is not deterministic, a new time for every call).                           |
| `contains "foobar" "foo"`         | checks whether the first string contains the second. See [ToLower](https://pkg.go.dev/strings#Contains)                    |
| `tolower "V1.2"`                  | makes input string lowercase. See [ToLower](https://pkg.go.dev/strings#ToLower).                                           |
| `toupper "v1.2"`                  | makes input string uppercase. See [ToUpper](https://pkg.go.dev/strings#ToUpper).                                           |
| `trim " v1.2  "`                  | removes all leading and trailing white space. See [TrimSpace](https://pkg.go.dev/strings#TrimSpace).                       |
| `trimprefix "v1.2" "v"`           | removes provided leading prefix string, if present. See [TrimPrefix](https://pkg.go.dev/strings#TrimPrefix).               |
| `trimsuffix "1.2v" "v"`           | removes provided trailing suffix string, if present. See [TrimSuffix](https://pkg.go.dev/strings#TrimSuffix).              |
| `dir .Path`                       | returns all but the last element of path, typically the path's directory. See [Dir](https://pkg.go.dev/path/filepath#Dir). |
| `base .Path`                      | returns the last element of path. See [Base](https://pkg.go.dev/path/filepath#Base)                                        |
| `abs .ArtifactPath`               | returns an absolute representation of path. See [Abs](https://pkg.go.dev/path/filepath#Abs).                               |
| `filter "text" "regex"`           | keeps only the lines matching the given regex, analogous to `grep -E`                                                      |
| `reverseFilter "text" "regex"`    | keeps only the lines **not** matching the given regex, analogous to `grep -vE`                                             |
| `title "foo"`                     | "titlenize" the string using english as language. See [Title](https://pkg.go.dev/golang.org/x/text/cases#Title)            |
| `mdv2escape "foo"`                | escape characters according to MarkdownV2, especially useful in the Telegram integration                                   |
| `envOrDefault "NAME" "value"`     | either gets the value of the given environment variable, or the given default                                              |
| `isEnvSet "NAME"`                 | returns true if the env is set and not empty, false otherwise                                                              |
| `$m := map "KEY" "VALUE"`         | creates a map from a list of key and value pairs. Both keys and values must be of type `string`                            |
| `indexOrDefault $m "KEY" "value"` | either gets the value of the given key or the given default value from the given map                                       |
| `incpatch "v1.2.4"`               | increments the patch of the given version[^panic-if-not-semver]                                                            |
| `incminor "v1.2.4"`               | increments the minor of the given version[^panic-if-not-semver]                                                            |
| `incmajor "v1.2.4"`               | increments the major of the given version[^panic-if-not-semver]                                                            |
| `list "a" "b" "c"`                | makes a list of strings[^pro]                                                                                              |
| `in (list "a" "b" "c") "b"`       | checks if a slice contains a value[^pro]                                                                                   |
| `urlPathEscape "foo/bar"`         | escapes URL paths. See [PathEscape](https://pkg.go.dev/net/url#PathEscape) (since v2.5)                                    |

[^panic-if-not-semver]: Will panic if not a semantic version.

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

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

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

```yaml
foo_template: "foo_{{ .Env.GOVERSION }}"
```

And then you can run:

```sh
GOVERSION=$(go version | awk '{print $3;}') goreleaser
```

!!! warning

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

### Custom variables

<!-- md:featpro -->

You can also declare custom variables. This feature is specially useful with
[includes](includes.md), so you can have more generic configuration
files.

Usage is as simple as you would expect:

```yaml title=".goreleaser.yaml"
variables:
  description: my project description
  somethingElse: yada yada yada
  empty: ""
```

And then you can use those fields as `{{ .Var.description }}`, for example.

---

- https://goreleaser.com/customization/env/

## Environment Variables

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

If you have an environment variable named `FOOBAR` set to `on`, your
`.goreleaser.yaml` file could use it like this:

```yaml title=".goreleaser.yaml"
env:
  - FOO={{ .Env.FOOBAR }}
  - ENV_WITH_DEFAULT={{ if index .Env "ENV_WITH_DEFAULT"  }}{{ .Env.ENV_WITH_DEFAULT }}{{ else }}default_value{{ end }}
before:
  hooks:
    - go mod tidy
builds:
  - binary: program
```

This way, both your before hooks (in this example, `go mod tidy`) and the
underlying builds (using `go build`) will have `FOO` set to `on`.

The root `env` section also accepts templates.

<!-- md:templates -->

---

- https://goreleaser.com/customization/dist/

## Dist folder

By default, GoReleaser will create its artifacts in the `./dist` folder.
If you must, you can change it by setting it in the `.goreleaser.yaml` file:

```yaml title=".goreleaser.yaml"
#
# Default: './dist'.
dist: another-folder-that-is-not-dist
```

More often than not, you won't need to change this.

!!! warning

    If you change this value, and use
    [`goreleaser continue`](../cmd/goreleaser_continue.md),
    you'll need to specify `--dist` when running it.

---

- https://goreleaser.com/customization/project/

## 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 GitHub, GitLab, or
Gitea release.

```yaml title=".goreleaser.yaml"
project_name: myproject
```

---

- https://goreleaser.com/customization/git/

## Git

This allows you to change the behavior of some Git commands.

```yaml title=".goreleaser.yaml"
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.
  prerelease_suffix: "-"

  # Tags to be ignored by GoReleaser.
  # This means that GoReleaser will not pick up tags that match any of the
  # provided values as either previous or current tags.
  #
  # Templates: allowed.
  ignore_tags:
    - nightly
    - "{{.Env.IGNORE_TAG}}"

  # Tags that begin with these prefixes will be ignored.
  #
  # This feature is only available in GoReleaser Pro.
  # Templates: allowed.
  ignore_tag_prefixes:
    - foo/
    - "{{.Env.IGNORE_TAG_PREFIX}}/bar"
```

### Semver sorting

<!-- md:featpro -->

This allows you to sort tags by semver:

```yaml title=".goreleaser.yaml"
git:
  tag_sort: semver
```

It'll parse all tags, ignoring non-semver-compatible tags, and sort from newest
to oldest, so the latest tag is returned.

This has the effect of sorting non-pre-release tags before pre-release ones,
which is different from what other git sorting options might give you.
…easer

The `before` section is used to define global hooks that are executed before the release process begins.
These hooks are invaluable for ensuring the project is in a clean and consistent state, thereby preventing errors caused by stale files, misconfigurations, or uncommitted changes.

## Example Configuration:

```yaml
before:
  hooks:
    - go generate ./...
    - go mod tidy
    - git --no-pager diff --exit-code go.mod go.sum
```

By executing these commands, the configuration ensures consistent builds and minimizes the risk of errors during the release process.

### Key Points

- **Consistency**: Prevents unexpected behaviors caused by stale files or uncommitted changes.
- **Reproducibility**: Guarantees that the same build can be reproduced reliably in the future.
- **Error Prevention**: Stops the release process if the project state is not clean or consistent.

## `hooks` Option

The `hooks` option specifies a list of shell commands to be executed in sequence before the release process starts.

### `go generate ./...`

This command runs Go's code generation tools, such as `stringer` or protobuf generators, to produce any autogenerated files required by the project.
It ensures all generated code is up-to-date before the release.

### `go mod tidy`

Cleans up the `go.mod` and `go.sum` files by removing unused dependencies and adding any missing ones.
This ensures the project's dependency files are accurate and consistent.

### `git --no-pager diff --exit-code go.mod go.sum`

Verifies that no changes were introduced to `go.mod` or `go.sum` after running the previous commands.
If changes are detected, the release process will stop, prompting you to commit the updates before proceeding.

### Important Note

If any of the hooks fail, the release process is immediately aborted. For instance:

- If `git --no-pager diff` detects uncommitted changes in `go.mod` or `go.sum`, you will need to manually resolve and commit them before continuing.
- This safeguard ensures that all builds remain clean, predictable, and free from unexpected issues.

---

# Quoting the GoReleaser documentation:

- https://goreleaser.com/customization/hooks/

## Global Hooks

Some release cycles may need to run something before or after everything else.

GoReleaser allows this with the global hooks feature.

=== "OSS"

    The `before` section allows for global hooks that will be executed
    **before** the release is started.

    The configuration is straightforward, here is an example will all possible
    options:

    ```yaml title=".goreleaser.yaml"
    before:
      # Templates for the commands to be ran.
      hooks:
      - make clean
      - go generate ./...
      - go mod tidy
      - touch {{ .Env.FILE_TO_TOUCH }}
    ```

=== "Pro"

    <!-- md:pro -->

    The `before` section allows for global hooks that will be executed
    **before** the release is started. Likewise, the `after` section allows for
    global hooks that will be executed **after** the release is started.

    The configuration is straightforward, here is an example will all possible
    options:

    ```yaml title=".goreleaser.yaml"
    # global before hooks
    before:
      # Commands to be ran.
      #
      # Templates: allowed.
      hooks:
      - make clean # simple string
      - cmd: go generate ./... # specify cmd
      - cmd: go mod tidy
        # Always prints command output.
        output: true
        dir: ./submodule # specify command working directory
      - cmd: touch {{ .Env.FILE_TO_TOUCH }}
        env:
        - 'FILE_TO_TOUCH=something-{{ .ProjectName }}' # specify hook level environment variables

    # global after hooks
    after:
      # Commands to be ran.
      #
      # Templates: allowed.
      hooks:
      - make clean
      - cmd: cat *.yaml
        dir: ./submodule
      - cmd: touch {{ .Env.RELEASE_DONE }}
        env:
        - 'RELEASE_DONE=something-{{ .ProjectName }}' # specify hook level environment variables
    ```

Note that if any of the hooks fails the release process is aborted.

### Complex commands

If you need to do anything more complex, it is recommended to create a shell
script and call it instead. You can also go crazy with `sh -c "my commands"`,
but it gets ugly really fast.

<!-- md:templates -->
The `gomod` section is used to enable the creation of **verifiable builds**—builds that can be reproduced and trusted by anyone.

## Example Configuration:

```yaml
gomod:
  proxy: true
```

## What Are Verifiable Builds?

A verifiable build ensures that the exact same build process can be repeated, thanks to sufficient information being recorded about dependencies and the build environment. This is achieved through the following mechanisms:
1. **Dependency Download via Go Proxy**: All modules are fetched through `proxy.golang.org` to ensure reliability and security.
2. **Checksum Validation**: Dependencies are verified against the Go checksum database, `sum.golang.org`, to guarantee their authenticity.
3. **Module Metadata in Binaries**: Information about the Go modules used in the build is embedded into the binary. This metadata can later be inspected using the `go version -m` command.

```shell
go version -m <binary-name>
```

This level of transparency and reproducibility helps developers and end-users trust the released artifacts.

## `proxy` option

The `proxy` option, when set to `true`, ensures that all Go modules are downloaded via the Go proxy (`proxy.golang.org`), enhancing reliability, performance, and security during the build process.

```yaml
proxy: true
```

### Key Benefits of Enabling the Proxy

1. **Faster and More Reliable Dependency Resolution**
   The Go proxy caches modules, significantly reducing build times and the risk of errors caused by unavailable or slow upstream repositories.

2. **Checksum Verification**
   All dependencies are validated against the Go checksum database (`sum.golang.org`). This ensures that only authentic and untampered modules are used, protecting against malicious changes.

3. **Reproducible Builds**
   By centralizing dependency retrieval through the Go proxy, builds become predictable and consistent, even when executed in different environments or at different times.

4. **Reduced Risk of Dependency Outages**
   The proxy acts as an intermediary, mitigating risks from upstream repository outages or unexpected changes in module versions.

### Why Verifiable Builds Matter

Enabling verifiable builds with GoReleaser ensures that:
- **Trust is Established**: Anyone inspecting the binary can confirm that it was built with the intended dependencies.
- **Reproducibility is Guaranteed**: Builds can be repeated reliably, ensuring consistency across environments and time.
- **Security is Strengthened**: Dependency tampering is prevented through checksum validation.
- **Builds Are Future-Proof**: Even if upstream dependencies are removed or altered, the Go proxy ensures they remain accessible.

---

By enabling the `gomod.proxy` option in GoReleaser, you enhance the integrity, transparency, and reliability of your builds—features that are critical for professional software distribution and environments where security and reproducibility are paramount.

---

# Quoting the GoReleaser documentation:

- https://goreleaser.com/customization/hooks/

## Verifiable Builds

GoReleaser has support for creating verifiable builds. A [verifiable build][vgo]
is one that records enough information to be precise about exactly how to repeat
it. All dependencies are loaded via `proxy.golang.org`, and verified against the
checksum database `sum.golang.org`. A GoReleaser-created verifiable build will
include module information in the resulting binary, which can be printed using
`go version -m mybinary`.

Configuration options available are described below.

```yaml
# goreleaser.yaml

gomod:
  # Proxy a module from proxy.golang.org, making the builds verifiable.
  # This will only be effective if running against a tag. Snapshots will ignore
  # this setting.
  # Notice: for this to work your `build.main` must be a package, not a `.go` file.
  proxy: true

  # If proxy is true, use these environment variables when running `go mod`
  # commands (namely, `go mod tidy`).
  #
  # Default: `os.Environ()` merged with what you set the root `env` section.
  env:
    - GOPROXY=https://proxy.golang.org,direct
    - GOSUMDB=sum.golang.org
    - GOPRIVATE=example.com/blah

  # Sets the `-mod` flag value.
  mod: mod

  # Which Go binary to use.
  #
  # Default: `go`.
  gobinary: go1.17

  # Directory in which the go.mod file is.
  #
  # Default: ''.
  dir: ./src
```

!!! tip

    You can use `debug.ReadBuildInfo()` to get the version/checksum/dependencies
    of the module.

!!! warning

    VCS Info will not be embedded in the binary, as in practice it is not being
    built from the source, but from the Go Mod Proxy.

!!! warning

    If you have a `go.work` file, make sure to run `go work sync`, so the main
    module (`.`) is the first line inside the `use` block.

[vgo]: https://research.swtch.com/vgo-repro
The `builds` section is used to define how binaries are built for multiple platforms.
It enables cross-platform compatibility, optimized builds, and embedding metadata for versioning and debugging.

## Example Configuration:

```yaml
builds:
  - main: ./cmd/{{ .ProjectName }}
    goos:
      - linux
      - windows
      - darwin
    goarch:
      - amd64
      - arm64
    env:
      - CGO_ENABLED=0
    flags:
      - -trimpath
    ldflags:
      - -s -w
      - -X main.name={{ .ProjectName }}
      - -X main.version={{ .Version }}
      - -X main.commit={{ .FullCommit }}
      - -X main.date={{ .CommitDate }}
      - -X main.url={{ .GitURL }}
    mod_timestamp: "{{ .CommitTimestamp }}"
```

This configuration generates efficient, cross-platform binaries while embedding metadata for traceability, reducing binary size, and ensuring reproducibility.

## Ensuring Reproducible Builds

Reproducible builds allow any party to recreate bit-for-bit identical binaries using the same source code, environment, and build instructions.

To achieve reproducibility in GoReleaser:

1. **Use Consistent Timestamps**
   - Set `mod_timestamp` to `{{ .CommitTimestamp }}` to tie the binary timestamp to the Git commit.
   - Avoid using dynamic timestamps (e.g., `{{ .Date }}`) in `ldflags`.

2. **Enable `-trimpath`**
   - This removes build environment paths from binaries, ensuring reproducibility across different directory structures.

3. **Use Verified Dependencies**
   - Enable the Go module proxy (`gomod.proxy: true`) to ensure dependencies are downloaded from verified sources with consistent checksums.

4. **Avoid Non-Deterministic Values**
   - Refrain from using dynamic template functions like `time` in the build configuration.

By following these practices, your binaries will be traceable, reproducible, and trustworthy.

## Configuration Options

### `main` option

The `main` option specifies the entry point for the Go application:

```yaml
main: ./cmd/{{ .ProjectName }}
```

The `.ProjectName` field is inferred from the repository name (e.g., from GitHub), making the configuration adaptable to different projects.

### `goos` option

The `goos` option specifies the target operating systems:

```yaml
goos:
  - linux
  - windows
  - darwin
```

This configuration builds binaries for Linux, Windows, and macOS.
For a complete list of supported values, see [Installing Go from source: Optional environment variables](https://go.dev/doc/install/source#environment).

### `goarch` option

The `goarch` option specifies the target CPU architectures:

```yaml
goarch:
  - amd64
  - arm64
```

This example generates binaries for 64-bit x86 (`amd64`) and 64-bit ARM (`arm64`) architectures.
For a complete list of supported values, see [Installing Go from source: Optional environment variables](https://go.dev/doc/install/source#environment).

### `env` option

The `env` option allows customization of environment variables during the build:

```yaml
env:
  - CGO_ENABLED=0
```

- **`CGO_ENABLED=0`**: Disables CGO (C bindings), producing fully static binaries. This improves portability, especially when distributing binaries for diverse environments.

### `flags` option

The `flags` option defines additional build flags for `go build`:

```yaml
flags:
  - -trimpath
```

Explanation of flags:

- **`-trimpath`**: Removes file system paths from the resulting executable. This makes builds more reproducible by removing references to the build environment's directory structure. Learn more: [Reproducible Builds](https://reproducible-builds.org/docs/definition/).

### `ldflags` option

The `ldflags` option specifies linker flags for `go tool link`:

```yaml
ldflags:
  - -s -w
  - -X main.name={{ .ProjectName }}
  - -X main.version={{ .Version }}
  - -X main.commit={{ .FullCommit }}
  - -X main.date={{ .CommitDate }}
  - -X main.url={{ .GitURL }}
```

Explanation of flags:

- **`-s`**: Strips the symbol table to reduce binary size.
- **`-w`**: Disables DWARF debugging information to further shrink the binary.
- **`-X`**: Injects values into variables at build time:
  - **`main.name`**: The project name.
  - **`main.version`**: The release version.
  - **`main.commit`**: The full Git commit hash.
  - **`main.date`**: The commit date.
  - **`main.url`**: The repository URL.

Embedding these values improves debugging, versioning, and traceability.

### `mod_timestamp` option

The `mod_timestamp` option specifies the modification timestamp of the binary:

```yaml
mod_timestamp: "{{ .CommitTimestamp }}"
```

This ties the binary's timestamp to the Git commit's timestamp, ensuring reproducibility and traceability of the build.

---

With the `builds` section properly configured, GoReleaser streamlines cross-platform binary creation, embeds essential metadata, and ensures that your builds are optimized, portable, and reproducible. This process greatly simplifies distribution while providing a high level of reliability for end-users.

---

# Quoting the GoReleaser documentation:

- https://goreleaser.com/customization/builds/

## Builds (Go)

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 change
the name of the binary, flags, environment variables, hooks and more.

Here is a commented `builds` section with all fields specified:

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

    # Path to main.go file or main package.
    # Notice: when used with `gomod.proxy`, this must be a package.
    #
    # Default: `.`.
    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`
    # - `pie`
    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.
    env:
      - CGO_ENABLED=0
      # complex, templated envs:
      - >-
        {{- 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://go.dev/doc/install/source#environment
    #
    # Default: [ 'darwin', 'linux', 'windows' ].
    goos:
      - freebsd
      - windows

    # GOARCH to build for.
    # For more info refer to: https://go.dev/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://go.dev/doc/install/source#environment
    #
    # Default: [ 6 ].
    goarm:
      - 6
      - 7

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

    # GOARM64 to build when GOARCH is arm64.
    # For more info refer to: https://go.dev/doc/install/source#environment
    #
    # Default: [ 'v8.0' ].
    # <!-- md:inline_version v2.4 -->.
    goarm64:
      - v9.0

    # GOMIPS and GOMIPS64 to build when GOARCH is mips, mips64, mipsle or mips64le.
    # For more info refer to: https://go.dev/doc/install/source#environment
    #
    # Default: [ 'hardfloat' ].
    # <!-- md:inline_version v2.4 -->.
    gomips:
      - hardfloat
      - softfloat

    # GO386 to build when GOARCH is 386.
    # For more info refer to: https://go.dev/doc/install/source#environment
    #
    # Default: [ 'sse2' ].
    # <!-- md:inline_version v2.4 -->.
    go386:
      - sse2
      - softfloat

    # GOPPC64 to build when GOARCH is PPC64.
    # For more info refer to: https://go.dev/doc/install/source#environment
    #
    # Default: [ 'power8' ].
    # <!-- md:inline_version v2.4 -->.
    goppc64:
      - power8
      - power9

    # GORISCV64 to build when GOARCH is RISCV64.
    # For more info refer to: https://go.dev/doc/install/source#environment
    #
    # Default: [ 'rva20u64' ].
    # <!-- md:inline_version v2.4 -->.
    goriscv64:
      - rva22u64

    # 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}`, `_{go386}`,
    #             `_{goriscv64}`, `_{goarm64}`, `_{goppc64}`.
    #
    # 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`, `go386`,
    #                `goriscv64`, `goarm64`, `goppc64`, and `ignores`.
    targets:
      - go_first_class
      - 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: "go".
    # Templates: allowed.
    # <!-- md:inline_version v2.5 -->.
    tool: "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.
    command: test

    # Set the modified timestamp on the output binary, typically
    # you would do this to ensure a build was reproducible.
    # Pass an 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.
    #
    # Templates: allowed (<!-- md:inline_version v2.3 -->).
    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 directory 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.
    #
    # Templates: allowed (<!-- md:inline_version v2.3 -->).
    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.
    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.
    # Valid options are: `go`, `rust`, `zig`, and `prebuilt` (pro-only).
    #
    # Default: 'go'.
    builder: prebuilt

    # Overrides allows to override some fields for specific targets.
    # This can be specially useful when using CGO.
    #
    # Attention: you need to set at least goos and goarch, otherwise it won't
    # match anything.
    overrides:
      - goos: darwin
        goarch: amd64
        goamd64: v1
        goarm: ""
        goarm64: ""
        gomips: ""
        go386: ""
        goriscv64: ""
        goppc64: ""
        ldflags:
          - foo
        tags:
          - bar
        asmflags:
          - foobar
        gcflags:
          - foobaz
        env:
          - CGO_ENABLED=1

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

!!! warning "GOAMD64, GORISCV64, GOPPC64, GO386, GOARM, GOARM64"

    You usually will need to specify the complete target in places like
    `targets` and `overrides`.
    This includes the `_{goamd64}` suffix, as well as the other
    GOARCH-specific values.

<!-- md:templates -->

!!! info

    First-class build targets are gathered by running:
    ```sh
    go tool dist list -json | jq -r '.[] | select(.FirstClass) | [.GOOS, .GOARCH] | @TSV'
    ```
    We also recommend reading the [official wiki about Go ports](https://go.dev/wiki/PortingPolicy#first-class-ports).

Here is an example with multiple binaries:

```yaml title=".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
```

The binary name field supports [templating](templates.md). The
following build details are exposed:

<!-- to format the tables, use: https://tabletomarkdown.com/format-markdown-table/ -->

| Key     | Description                       |
| ------- | --------------------------------- |
| .Os     | `GOOS`                            |
| .Arch   | `GOARCH`                          |
| .Arm    | `GOARM`                           |
| .Ext    | Extension, e.g. `.exe`            |
| .Target | Build target, e.g. `darwin_amd64` |

### Passing environment variables to ldflags

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

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

Then you can run:

```sh
GOVERSION=$(go version) goreleaser
```

### Build Hooks

Both pre and post hooks run **for each build target**, regardless of whether
these targets are generated via a matrix of OSes and architectures or defined
explicitly.

In addition to simple declarations as shown above _multiple_ hooks can be
declared to help retaining reusability of config between different build
environments.

```yaml title=".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 work directory and environment variables:

```yaml title=".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.
          output: true
          env:
            - HOOK_SPECIFIC_VAR={{ .Env.GLOBAL_VAR }}
        - second-script.sh
```

All properties of a hook (`cmd`, `dir` and `env`) support
[templating](templates.md) with `post` hooks having binary artifact
available (as these run _after_ the build).
Additionally the following build details are exposed to both `pre` and `post`
hooks:

<!-- to format the tables, use: https://tabletomarkdown.com/format-markdown-table/ -->

| Key     | Description                            |
| ------- | -------------------------------------- |
| .Name   | Filename of the binary, e.g. `bin.exe` |
| .Ext    | Extension, e.g. `.exe`                 |
| .Path   | Absolute path to the binary            |
| .Target | Build target, e.g. `darwin_amd64`      |

Environment variables are inherited and overridden in the following order:

- global (`env`)
- build (`builds[].env`)
- hook (`builds[].hooks.pre[].env` and `builds[].hooks.post[].env`)

### 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 tidy` before calling `goreleaser` or
by adding a [hook][] doing that on your `.goreleaser.yaml` file:

```yaml title=".goreleaser.yaml"
before:
  hooks:
    - go mod tidy
# rest of the file...
```

[hook]: hooks.md

### Define Build Tag

GoReleaser uses `git describe` to get the build tag. You can set
a different build tag using the environment variable `GORELEASER_CURRENT_TAG`.
This is useful in scenarios where two tags point to the same commit.

### Reproducible Builds

To make your releases, checksums and signatures reproducible, you will need to
make some (if not all) of the following modifications to the build defaults in
GoReleaser:

- Modify `ldflags`: by default `main.Date` is set to the time GoReleaser is run
  (`{{.Date}}`), you can set this to `{{.CommitDate}}` or just not pass the
  variable.
- Modify `mod_timestamp`: by default this is empty string — which means it'll be
  the compilation time, set to `{{.CommitTimestamp}}` or a constant value
  instead.
- If you do not run your builds from a consistent directory structure, pass
  `-trimpath` to `flags`.
- Remove uses of the `time` template function. This function returns a new value
  on every call and is not deterministic.

### A note about directory names inside `dist`

By default, GoReleaser will create your binaries inside
`dist/${BuildID}_${BuildTarget}`, which is a unique directory per build target
in the matrix.

Those names have no guarantees of remaining the same from one version to
another. If you really need to access them from outside GoReleaser, you should
be able to consistently get the path of a binary by parsing
`dist/artifacts.json`.

You can also set `builds.no_unique_dist_dir` (as documented earlier in this
page), but in that case you are responsible for preventing name conflicts.

#### Why is there a `_v1` suffix on `amd64` builds?

Go 1.18 introduced the `GOAMD64` option, and `v1` is the default value for that
option.

Since you can have GoReleaser build for multiple different `GOAMD64` targets, it
adds that suffix to prevent name conflicts. The same thing happens for `arm` and
`GOARM`, `mips` and `GOMIPS` and others.

### Go's first class ports

The `targets` option can take a `go_first_class` special value as target, which
will evaluate to the list of first class ports as defined in the Go wiki.

You can read more about it
[here](https://go.dev/wiki/PortingPolicy#first-class-ports).

### Building shared or static libraries

GoReleaser supports compiling and releasing C shared or static libraries, by
configuring the [Go build mode](https://pkg.go.dev/cmd/go#hdr-Build_modes).

This can be set with `buildmode` in your build.
It now supports `c-shared` and `c-archive`. Other values will transparently be
applied to the build line (via the `-buildmode` flag), but GoReleaser will not
attempt to configure any additional logic.

GoReleaser will:

- set the correct file extension for the target OS.
- package the generated header file (`.h`) in the release bundle.

Example usage:

```yaml title=".goreleaser.yaml"
builds:
  - id: "my-library"

    # Configure the buildmode flag to output a shared library
    buildmode: "c-shared" # or "c-archive" for a static library
```

### Complex template environment variables

Builds environment variables accept templates.

You can leverage that to have a single build configuration with different
environment variables for each platform, for example.

A common example of this is the variables `CC` and `CXX`.

Here are two different examples:

#### Using multiple envs

This example creates once `CC_` and `CXX_` variable for each platform, and then
set `CC` and `CXX` to the right one:

```yaml title=".goreleaser.yaml"
builds:
  - id: mybin
    binary: mybin
    main: .
    goos:
      - linux
      - darwin
      - windows
    goarch:
      - amd64
      - arm64
    env:
      - CGO_ENABLED=0
      - CC_darwin_amd64=o64-clang
      - CXX_darwin_amd64=o64-clang+
      - CC_darwin_arm64=aarch64-apple-darwin20.2-clang
      - CXX_darwin_arm64=aarch64-apple-darwin20.2-clang++
      - CC_windows_amd64=x86_64-w64-mingw32-gc
      - CXX_windows_amd64=x86_64-w64-mingw32-g++
      - 'CC={{ index .Env (print "CC_" .Os "_" .Arch) }}'
      - 'CXX={{ index .Env (print "CXX_" .Os "_" .Arch) }}'
```

#### Using `if` statements

This example uses `if` statements to set `CC` and `CXX`:

```yaml title=".goreleaser.yaml"
builds:
  - id: mybin
    binary: mybin
    main: .
    goos:
      - linux
      - darwin
      - windows
    goarch:
      - amd64
      - arm64
    env:
      - CGO_ENABLED=0
      - >-
        {{- 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 }}
      - >-
        {{- if eq .Os "darwin" }}
          {{- if eq .Arch "amd64"}}CXX=o64-clang+{{- end }}
          {{- if eq .Arch "arm64"}}CXX=aarch64-apple-darwin20.2-clang++{{- end }}
        {{- end }}
        {{- if eq .Os "windows" }}
          {{- if eq .Arch "amd64" }}CXX=x86_64-w64-mingw32-g++{{- end }}
        {{- end }}
```
The `archives` section defines how the output files are packaged and named. This configuration is crucial for producing platform-specific artifacts with consistent naming and metadata.

## Example Configuration:

```yaml
archives:
  - format: binary
    name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
    builds_info:
      mtime: "{{ .CommitDate }}"
```

## Key Points

This configuration ensures the creation of platform-specific artifacts with consistent naming and metadata.

- **Predictable filenames** simplify artifact distribution and usage.
- **Consistent timestamps** (e.g., commit dates) align binaries with the Git history, enhancing reproducibility.

## Configuration Options

### `format` Option

The `format` option specifies the type of output file to generate:

```yaml
format: binary
```

- `binary`: Outputs raw binary files without creating archives (e.g., `.tar.gz` or `.zip`).

### `name_template` Option

The `name_template` option customizes the naming convention for the output files:

```yaml
name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
```

#### Explanation of Template Variables:

- `{{ .ProjectName }}`: The name of the project.
- `{{ .Version }}`: The version being released.
- `{{ .Os }}`: The operating system target (e.g., `linux`, `windows`, `darwin`).
- `{{ .Arch }}`: The architecture target (e.g., `amd64`, `arm64`).

#### Example Output:

For a project named `example` with version `1.0.0` built for Linux and AMD64, the resulting binary would be:

```plaintext
example_1.0.0_linux_amd64
```

This naming convention makes artifacts easy to identify and use based on platform and version.

### `builds_info` Option

The `builds_info` option defines metadata for the binaries included from the `builds` section:

```yaml
builds_info:
  mtime: "{{ .CommitDate }}"
```

#### Key Field:

- `mtime`: Sets the modification time of the output binary files to match the Git commit date.

#### Why Use `mtime`?

Setting the modification time to the Git commit date ensures:

- **Consistency across builds.**
- **Alignment of binary metadata with the project's version history.**

This is crucial for achieving reproducible builds and maintaining a clear connection between the binary and its source.

---

# Quoting the GoReleaser documentation:

- https://goreleaser.com/customization/archive/

## Archives

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:

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

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

    # Archive format.
    #
    # If format is `binary`, no archives are created and the binaries are instead
    # uploaded directly.
    #
    # Valid options are:
    # - `tar.gz`
    # - `tgz`
    # - `tar.xz`
    # - `txz`
    # - `tar.zst`
    # - `tzst` # <!-- md:inline_version v2.1 -->.
    # - `tar`
    # - `gz`
    # - `zip`
    # - `binary`
    #
    # Default: 'tar.gz'.
    format: zip

    # This will create an archive without any binaries, only the files are there.
    # The name template must not contain any references to `Os`, `Arch` and etc, since the archive will be meta.
    #
    # Templates: allowed.
    meta: true

    # 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.
    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 directory 'goreleaser_Linux_arm64'.
    # If set to false, all files are extracted separately.
    # You can also set it to a custom directory 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 sub-directory
    # for some reason, but do no want that sub-directory inside the archive.
    strip_binary_directory: true

    # This will make the destination paths be relative to the longest common
    # path prefix between all the files matched and the source glob.
    # Enabling this essentially mimic the behavior of nfpm's contents section.
    # It will be the default by June 2023.
    rlcp: 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:
      - # Which GOOS to override the format for.
        goos: windows

        # The format to use for the given GOOS.
        #
        # Valid options are `tar.gz`, `tgz`, `tar.xz`, `txz`, tar`, `gz`, `zip`, `binary`, and `none`.
        format: 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 directories 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.
          owner: root

          # Templates: allowed.
          group: root

          # Must be in time.RFC3339Nano format.
          #
          # Templates: allowed.
          mtime: "{{ .CommitDate }}"

          # File mode.
          mode: 0644

    # 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.
    #
    # 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:
          # Templates: allowed.
          owner: root

          # Templates: allowed.
          group: root

          # Must be in time.RFC3339Nano format.
          #
          # Templates: allowed.
          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

    # Disables the binary count check.
    allow_different_binary_count: true
```

<!-- md:pro -->

<!-- md:templates -->

!!! tip

    You can add entire directories, its sub-directories and files by using the
    glob notation, for example: `mydirectory/**/*`.

!!! warning

    The `files` and `wrap_in_directory` options are ignored if `format` is `binary`.

!!! warning

    The `name_template` option will not reflect the filenames under the `dist`
    directory if `format` is `binary`.
    The template will be applied only where the binaries are uploaded (e.g.
    GitHub releases).

### Deep diving into the globbing options

We'll walk through what happens in each case using some examples.

```yaml
# ...
files:
  # Adds `README.md` at the root of the archive:
  - README.md

  # Adds all `md` files to the root of the archive:
  - "*.md"

  # Adds all `md` files to the root of the archive:
  - src: "*.md"

  # Adds all `md` files in the current directory to a `docs` directory in the
  # archive:
  - src: "*.md"
    dst: docs

  # Recursively adds all `go` files to a `source` directory in the archive.
  # in this case, `cmd/myapp/main.go` will be added as `source/cmd/myapp/main.go`
  - src: "**/*.go"
    dst: source

  # Recursively adds all `go` files to a `source` directory in the archive,
  # stripping their parent directory.
  # In this case, `cmd/myapp/main.go` will be added as `source/main.go`:
  - src: "**/*.go"
    dst: source
    strip_parent: true
# ...
```

### 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:

```yaml title=".goreleaser.yaml"
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](goreleaser/goreleaser#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:

```yaml title=".goreleaser.yaml"
archives:
  - format: gz
    files:
      - none*
```

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

!!! warning

    You won't be able to package multiple builds in a single archive either.
    The alternative is to declare multiple archives filtering by build ID.

### Disable archiving

You can do that by setting `format` to `binary`:

```yaml title=".goreleaser.yaml"
archives:
  - format: binary
```

Make sure to check the rest of the documentation above, as doing this has some
implications.

If you have customization that might rely on archives, for instance,
`brews.install`, make sure to fix them too.
The `checksum` section is used to generate a checksum file for all output binaries. This file allows users to cryptographically verify the integrity of the binaries, ensuring they have not been tampered with.

## Example Configuration:

```yaml
checksum:
  name_template: "{{ .ProjectName }}_{{ .Version }}_checksums.txt"
  algorithm: sha256
```

## Key Points

- **Integrity Verification**: Ensures users can verify that the downloaded binaries match the original files produced during the release.
- **Tamper Detection**: Protects against malicious modifications during distribution.
- **Transparency**: Provides a simple way for users to independently validate the authenticity of the binaries.

## Configuration Options

### `name_template` Option

The `name_template` option defines the naming convention for the checksum file:

```yaml
name_template: "{{ .ProjectName }}_{{ .Version }}_checksums.txt"
```

This naming convention ensures consistency and makes the checksum file easy to locate and reference.

#### Explanation of Template Variables:

- `{{ .ProjectName }}`: The name of the project.
- `{{ .Version }}`: The version being released.

#### Example Output:

For a project named `example` with version `1.0.0`, the resulting checksum file will be named:

```plaintext
example_1.0.0_checksums.txt
```

### `algorithm` Option

The `algorithm` option specifies the hash algorithm used to compute the checksums:

```yaml
algorithm: sha256
```

#### Why `sha256`?

- **Secure Hash Algorithm (SHA) 256-bit**: Produces a unique, fixed-length 256-bit hash value for each binary.
- **Irreversible**: Cryptographic hash functions like SHA256 are designed to prevent reverse engineering of the original data.
- **Widely Used**: SHA256 is a standard for cryptographic security, commonly used to verify file integrity.

---

# Quoting the GoReleaser documentation:

- https://goreleaser.com/customization/checksum/

## Checksums

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:

```yaml title=".goreleaser.yaml"
checksum:
  # You can change the name of the checksums file.
  #
  # Default: '{{ .ProjectName }}_{{ .Version }}_checksums.txt', or,
  #   when split is set: '{{ .ArtifactName }}.{{ .Algorithm }}'.
  # Templates: allowed.
  name_template: "{{ .ProjectName }}_checksums.txt"

  # Algorithm to be used.
  #
  # Accepted options are:
  # - sha256
  # - sha512
  # - sha1
  # - crc32
  # - md5
  # - sha224
  # - sha384
  # - sha3-256
  # - sha3-512
  # - sha3-224
  # - sha3-384
  # - blake2s
  # - blake2b
  #
  # Default: 'sha256'.
  algorithm: sha256

  # If true, will create one checksum file for each artifact.
  split: true

  # 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.
  #
  # This feature is only available in GoReleaser Pro.
  # Templates: allowed.
  templated_extra_files:
    - src: LICENSE.tpl
      dst: LICENSE.txt
```

<!-- md:templates -->
The `dockers` section simplifies the creation and publishing of multi-architecture container images, such as `amd64` and `arm64`.
These images are metadata-rich, lightweight, and compatible with container registries like the GitHub Container Registry (GHCR).

---

#### Example Configuration

```yaml
dockers:
  - image_templates:
      - "ghcr.io/{{ .Env.GITHUB_REPOSITORY_OWNER }}/{{ .ProjectName }}:{{ .Tag }}-amd64"
    use: buildx
    goos: linux
    goarch: amd64
    skip_push: false
    dockerfile: Dockerfile
    build_flag_templates:
      - "--pull"
      - "--label=org.opencontainers.image.title={{ .ProjectName }}"
      - "--label=org.opencontainers.image.description={{ .ProjectName }} {{ .Version }}"
      - "--label=org.opencontainers.image.created={{ .CommitDate }}"
      - "--label=org.opencontainers.image.revision={{ .FullCommit }}"
      - "--label=org.opencontainers.image.version={{ .Version }}"
      - "--label=org.opencontainers.image.url={{ .ReleaseURL }}"
      - "--label=org.opencontainers.image.source={{ .GitURL }}"
      - "--label=org.opencontainers.image.documentation={{ .GitURL }}/blob/main/README.md"
      - "--label=org.opencontainers.image.licenses=Apache-2.0"
      - "--platform=linux/amd64"
  - image_templates:
      - "ghcr.io/{{ .Env.GITHUB_REPOSITORY_OWNER }}/{{ .ProjectName }}:{{ .Tag }}-arm64"
    use: buildx
    goos: linux
    goarch: arm64
    skip_push: false
    dockerfile: Dockerfile
    build_flag_templates:
      - "--pull"
      - "--label=org.opencontainers.image.title={{ .ProjectName }}"
      - "--label=org.opencontainers.image.description={{ .ProjectName }} {{ .Version }}"
      - "--label=org.opencontainers.image.created={{ .CommitDate }}"
      - "--label=org.opencontainers.image.revision={{ .FullCommit }}"
      - "--label=org.opencontainers.image.version={{ .Version }}"
      - "--label=org.opencontainers.image.url={{ .ReleaseURL }}"
      - "--label=org.opencontainers.image.source={{ .GitURL }}"
      - "--label=org.opencontainers.image.documentation={{ .GitURL }}/blob/main/README.md"
      - "--label=org.opencontainers.image.licenses=Apache-2.0"
      - "--platform=linux/arm64"
```

---

#### Key Benefits

1. **Cross-Platform Compatibility**
   Creates container images for multiple architectures (`amd64`, `arm64`) using Docker's Buildx tool, expanding your application's accessibility across various platforms.

2. **Enhanced Transparency**
   Embeds OCI-compliant metadata in the images, ensuring traceability and clarity for users.

3. **Streamlined Distribution**
   Automates image creation and publishing to registries, reducing manual effort while maintaining quality.

---

### Configuration Options

#### `image_templates`

Specifies the naming convention for container images, incorporating metadata like repository owner, project name, version, and architecture:

```yaml
image_templates:
  - "ghcr.io/{{ .Env.GITHUB_REPOSITORY_OWNER }}/{{ .ProjectName }}:{{ .Tag }}-{{ .Arch }}"
```

**Example Output**:
For a project named `example` with version `v1.0.0` targeting `amd64`, the image will be named:
`ghcr.io/owner/example:v1.0.0-amd64`.

---

#### `use`

Defines the backend used for building Docker images:

```yaml
use: buildx
```

The Buildx tool enables cross-platform builds, ensuring compatibility with various architectures like `amd64` and `arm64`.

---

#### `goos` and `goarch`

Specifies the operating system and CPU architecture for the image:

```yaml
goos: linux
goarch: amd64
```

These options ensure the image is compatible with the target environment.

---

#### `dockerfile`

Indicates the Dockerfile used for the build process:

```yaml
dockerfile: Dockerfile
```

This allows you to customize the containerization process fully, tailoring the image content to your needs.

---

#### `skip_push`

Determines whether the built image is pushed to the registry:

```yaml
skip_push: false
```

When set to `false`, the image is pushed to the configured container registry after being built.

---

#### `build_flag_templates`

Specifies additional flags used during the build process, embedding essential metadata into the image:

```yaml
build_flag_templates:
  - "--pull"
  - "--label=org.opencontainers.image.title={{ .ProjectName }}"
  - "--label=org.opencontainers.image.description={{ .ProjectName }} {{ .Version }}"
  - "--label=org.opencontainers.image.created={{ .CommitDate }}"
  - "--label=org.opencontainers.image.revision={{ .FullCommit }}"
  - "--label=org.opencontainers.image.version={{ .Version }}"
  - "--label=org.opencontainers.image.url={{ .ReleaseURL }}"
  - "--label=org.opencontainers.image.source={{ .GitURL }}"
  - "--label=org.opencontainers.image.documentation={{ .GitURL }}/blob/main/README.md"
  - "--label=org.opencontainers.image.licenses=Apache-2.0"
  - "--platform=linux/{{ .Arch }}"
```

**Key Flags**:
- **`--pull`**: Ensures the base image is updated by pulling the latest version from the registry before building.
- **`--label`**: Adds OCI-compliant metadata, including:
  - **Title**: Project name.
  - **Description**: Project name and version.
  - **Created**: Commit date.
  - **Revision**: Git commit hash.
  - **Version**: Project version.
  - **URL**: Release URL.
  - **Source**: Git repository URL.
  - **Documentation**: Link to the README file.
  - **Licenses**: Project license (e.g., Apache-2.0).
- **`--platform`**: Specifies the target platform, such as `linux/amd64`.

---

# Quoting the GoReleaser documentation:

- https://goreleaser.com/customization/docker/

## Docker Images

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

### How it works

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

If you have only one item in the `builds` list,
the configuration can be as easy as adding the
name of your image to your `.goreleaser.yaml` file:

```yaml
dockers:
  - image_templates:
      - user/repo
```

<!-- md:templates -->

You also need to create a `Dockerfile` in your project's root directory:

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

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

#### The Docker build context

Note that we 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`.

The idea is that you reuse the previously built binaries instead of building
them again when creating the Docker image.

The build context itself is a temporary directory which contains the binaries
and packages for the current platform, which you can `COPY` into your image.

A corollary of that is that **the context does not contain the source files**.
If you need to add some other file that is in your source directory, you'll need
to add it to the `extra_files` property, so it'll get copied into the context.

All that being said, your Docker build context will usually look like this:

```sh
temp-context-dir
├── Dockerfile
├── myprogram     # the binary
├── myprogram.rpm # linux package
├── myprogram.apk # linux package
└── myprogram.deb # linux package
```

`myprogram` would actually be your binary name, and the Linux package names
would follow their respective configuration's `name_templates`.

### Customization

Of course, you can customize a lot of things:

```yaml title=".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.
    #
    # Make sure to only include the IDs of binaries you want to `COPY` in your
    # Dockerfile.
    #
    # If you include IDs that don't exist or are not available for the current
    # architecture being built, the build of the image will be skipped.
    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.
    #
    # This option is only available on GoReleaser Pro.
    # Templates: allowed.
    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.
    skip_push: false

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

    # Use this instead of `dockerfile` if the contents of your Dockerfile are
    # supposed to go through the template engine as well.
    #
    # `dockerfile` is ignored when this is set.
    #
    # This feature is only available in GoReleaser Pro.
    # Templates: allowed.
    templated_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
    # directory, 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 directory in which
    # GoReleaser is being run (usually the repository root directory).
    # This field does not support wildcards, you can add an entire directory 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.
    #
    # This feature is only available in GoReleaser Pro.
    # Templates: allowed.
    templated_extra_files:
      - src: LICENSE.tpl
        dst: LICENSE.txt
        mode: 0644
```

!!! warning

    Note that you will have to manually login into the Docker registries you
    want to push to — GoReleaser does not login by itself.

<!-- md:templates -->

!!! tip

    You can also create multi-platform images using the [docker_manifests](docker_manifest.md) config.

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 or one image with multiple binaries, as well as
install the generated packages instead of copying the binary and configs manually.

### 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:

```yaml title=".goreleaser.yaml"
project_name: foo
dockers:
  - image_templates:
      - "myuser/{{.ProjectName}}"
```

This will build and publish the following images:

- `myuser/foo`

<!-- md:templates -->

### Keeping docker images updated for current major

Some users might want 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`:

```yaml title=".goreleaser.yaml"
dockers:
  - 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 Docker images
with multiple tags.

<!-- md:templates -->

### 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`:

```yaml title=".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 will build and publish the following images 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

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

```yaml title=".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:

```bash
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
```

<!-- md:templates -->

### Use a specific builder with Docker buildx

If `buildx` is enabled, the `default` context builder will be used when building
the image. This builder is always available and backed by BuildKit in the
Docker engine. If you want to use a different builder, you can specify it using
the `build_flag_templates` field:

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

!!! tip

    Learn more about the [buildx builder instances](https://docs.docker.com/buildx/working-with-buildx/#work-with-builder-instances).

### Using Podman

<!-- md:pro -->

You can use [`podman`](https://podman.io) instead of `docker` by setting `use` to `podman` on your config:

```yaml title=".goreleaser.yaml"
dockers:
  - image_templates:
      - "myuser/myimage"
    use: podman
```

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

If you want to use it rootless, make sure to follow
[this guide](https://github.com/containers/podman/blob/main/docs/tutorials/rootless_tutorial.md).
The `docker_manifests` section in GoReleaser combines architecture-specific container images into a single multi-architecture manifest.
This allows users to pull the appropriate image automatically based on their system architecture, offering a seamless experience across platforms such as `amd64` and `arm64`.

---

### Example Configuration

```yaml
docker_manifests:
  - name_template: "ghcr.io/{{ .Env.GITHUB_REPOSITORY_OWNER }}/{{ .ProjectName }}:{{ .Tag }}"
    image_templates:
      - "ghcr.io/{{ .Env.GITHUB_REPOSITORY_OWNER }}/{{ .ProjectName }}:{{ .Tag }}-amd64"
      - "ghcr.io/{{ .Env.GITHUB_REPOSITORY_OWNER }}/{{ .ProjectName }}:{{ .Tag }}-arm64"
  - name_template: "ghcr.io/{{ .Env.GITHUB_REPOSITORY_OWNER }}/{{ .ProjectName }}:latest"
    image_templates:
      - "ghcr.io/{{ .Env.GITHUB_REPOSITORY_OWNER }}/{{ .ProjectName }}:{{ .Tag }}-amd64"
      - "ghcr.io/{{ .Env.GITHUB_REPOSITORY_OWNER }}/{{ .ProjectName }}:{{ .Tag }}-arm64"
```

---

### Key Benefits

1. **Unified Access Across Architectures**
   Combines architecture-specific images (e.g., `amd64`, `arm64`) into a single reference, simplifying the user experience.

2. **Streamlined Automation**
   Automatically builds and updates manifests, making cross-platform distribution straightforward and efficient.

---

### Configuration Options

#### **`name_template`**

The `name_template` option defines the naming pattern for the multi-architecture manifest.

```yaml
name_template: "ghcr.io/{{ .Env.GITHUB_REPOSITORY_OWNER }}/{{ .ProjectName }}:{{ .Tag }}"
```

**Explanation of Variables**:
- `{{ .Env.GITHUB_REPOSITORY_OWNER }}`: The GitHub repository owner (e.g., username or organization).
- `{{ .ProjectName }}`: The project's name.
- `{{ .Tag }}`: The image tag, typically the release version (e.g., `v1.0.0`).

**Example Output**:
For a project named `example` owned by `owner` and version `v1.0.0`, the manifest name would be:
`ghcr.io/owner/example:v1.0.0`

---

#### **`image_templates`**

The `image_templates` option specifies the architecture-specific images that the manifest will include:

```yaml
image_templates:
  - "ghcr.io/{{ .Env.GITHUB_REPOSITORY_OWNER }}/{{ .ProjectName }}:{{ .Tag }}-amd64"
  - "ghcr.io/{{ .Env.GITHUB_REPOSITORY_OWNER }}/{{ .ProjectName }}:{{ .Tag }}-arm64"
```

These templates represent the images for specific architectures, such as `amd64` and `arm64`.

**How It Works**:
1. GoReleaser ensures the listed architecture-specific images exist.
2. The tool bundles these images into a unified manifest.

**Example**:
For `example:v1.0.0`, the following architecture-specific images would be included:
- `ghcr.io/owner/example:v1.0.0-amd64`
- `ghcr.io/owner/example:v1.0.0-arm64`

The resulting multi-architecture manifest:
`ghcr.io/owner/example:v1.0.0`

This allows users to pull the appropriate image for their platform without specifying the architecture.

---

# Quoting the GoReleaser documentation:

- https://goreleaser.com/customization/docker_manifest/

## Docker Manifests

GoReleaser can also create and push Docker multi-platform images using the
`docker manifest` tool.

For it to work, it needs to be enabled in the
[client's configuration](https://github.com/docker/cli/blob/master/experimental/README.md).

Please make sure `docker manifest` works before opening issues.

Notice that if you have something in the `docker_manifests` section in your
config file, GoReleaser will add the manifest's to the release notes instead of
the Docker images names.

!!! warning

    Notice that the images used in the manifest **need to be pushed** for this
    to work. This is a limitation of how `docker manifest create` works. For
    more info, check
    [this issue](goreleaser/goreleaser#2606).

### Customization

You can create several manifests in a single GoReleaser run, here are all the
options available:

```yaml title=".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.
    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
```

<!-- md:templates -->

### How it works

We basically build and push our images as usual, but we also add a new
section to our configuration defining, which images are part of which manifests.

GoReleaser will create and publish the manifest in its publishing phase.

!!! warning

    Unfortunately, the manifest tool needs the images to be pushed to create
    the manifest, that's why we both create and push it in the publishing phase.

### Example config

In this example we will use Docker's `--platform` option to specify the target platform.
This way we can use the same `Dockerfile` for both the `amd64`, and the `arm64`
images (and possibly others):

```dockerfile
# Dockerfile
FROM alpine
ENTRYPOINT ["/usr/bin/mybin"]
COPY mybin /usr/bin/mybin
```

Then, on our GoReleaser configuration file, we need to define both the
`dockers`, and the `docker_manifests` section:

```yaml title=".goreleaser.yaml"
builds:
  - env:
      - CGO_ENABLED=0
    binary: mybin
    goos:
      - linux
    goarch:
      - amd64
      - arm64
dockers:
  - image_templates:
      - "foo/bar:{{ .Version }}-amd64"
    use: buildx
    dockerfile: Dockerfile
    build_flag_templates:
      - "--platform=linux/amd64"
  - image_templates:
      - "foo/bar:{{ .Version }}-arm64v8"
    use: buildx
    goarch: arm64
    dockerfile: Dockerfile
    build_flag_templates:
      - "--platform=linux/arm64/v8"
docker_manifests:
  - name_template: "foo/bar:{{ .Version }}"
    image_templates:
      - "foo/bar:{{ .Version }}-amd64"
      - "foo/bar:{{ .Version }}-arm64v8"
```

!!! warning

    Notice that `--platform` needs to be in the Docker platform format, not Go's.

That config will build the 2 Docker images defined, as well as the manifest,
and push everything to Docker Hub.

### Using Podman

<!-- md:pro -->

You can use [`podman`](https://podman.io) instead of `docker` by setting `use`
to `podman` on your configuration:

```yaml title=".goreleaser.yaml"
docker_manifests:
  - name_template: "foo/bar:{{ .Version }}"
    image_templates:
      - "foo/bar:{{ .Version }}-amd64"
      - "foo/bar:{{ .Version }}-arm64v8"
    use: podman
```

Note that GoReleaser will not install Podman for you, nor change any of its
configuration.
The `changelog` section automates the creation of release notes by leveraging GitHub's native release notes feature. This integration simplifies the release process, ensuring your documentation accurately reflects all changes made in each release.

## Example Configuration

```yaml
changelog:
  use: github-native
```

## Key Benefits

- **Time-Saving**
   Automates the process of generating changelogs, eliminating manual effort and minimizing errors or omissions.

- **Consistency**
   Aligns the changelog with GitHub's commit and tag history, creating a reliable record of project updates.

- **Enhanced Workflow**
   Integrates seamlessly into the release pipeline, simplifying the process of generating and publishing changelogs.

## Configuration Options

### `use` Option

The `use` option defines how the changelog is generated.

```yaml
use: github-native
```

- **`github-native`**: Leverages GitHub’s release notes to automatically create changelogs.
- It collects details from GitHub tags and commit messages to summarize changes for each release.
- This approach ensures consistency and reduces the effort needed to maintain accurate documentation.

---

# Quoting the GoReleaser documentation:

- https://goreleaser.com/customization/changelog/

## Changelog

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

```yaml title=".goreleaser.yaml"
changelog:
  # Set this to true if you don't want any changelog at all.
  #
  # Warning: this will also ignore any changelog files passed via `--release-notes`,
  # and will render an empty changelog.
  #
  # This may result in an empty release notes on GitHub/GitLab/Gitea.
  #
  # Templates: allowed.
  disable: "{{ .Env.CREATE_CHANGELOG }}"

  # Changelog generation implementation to use.
  #
  # Valid options are:
  # - `git`: uses `git log`;
  # - `github`: uses the compare GitHub API, appending the author username to the changelog.
  # - `gitlab`: uses the compare GitLab API, appending the author name and email to the changelog (requires a personal access token).
  # - `gitea`: uses the compare Gitea API, appending the author username to the changelog.
  # - `github-native`: uses the GitHub release notes generation API, disables the groups feature.
  #
  # Default: 'git'.
  use: github

  # Format to use for commit formatting.
  # Only available when use is one of `github`, `gitea`, or `gitlab`.
  #
  # Default: '{{ .SHA }}: {{ .Message }} ({{ with .AuthorUsername }}@{{ . }}{{ else }}{{ .AuthorName }} <{{ .AuthorEmail }}>{{ end }})'.
  # Extra template fields: `SHA`, `Message`, `AuthorName`, `AuthorEmail`, and
  # `AuthorUsername`.
  format: "{{.SHA}}: {{.Message}} (@{{.AuthorUsername}})"

  # Sorts the changelog by the commit's messages.
  # Could either be asc, desc or empty
  # Empty means 'no sorting', it'll use the output of `git log` as is.
  sort: asc

  # Max commit hash length to use in the changelog.
  #
  # 0: use whatever the changelog implementation gives you
  # -1: remove the commit hash from the changelog
  # any other number: max length.
  abbrev: -1

  # Paths to filter the commits for.
  # Only works when `use: git`, otherwise ignored.
  #
  # This feature is only available in GoReleaser Pro.
  # Default: monorepo.dir value, or empty if no monorepo.
  paths:
    - foo/
    - bar/

  # Group commits messages by given regex and title.
  # Order value defines the order of the groups.
  # Providing no regex means all commits will be grouped under the default group.
  #
  # Matches are performed against the first line of the commit message only,
  # prefixed with the commit SHA1, usually in the form of
  # `<abbrev-commit>[:] <title-commit>`.
  # Groups are disabled when using github-native, as it already groups things by itself.
  # Regex use RE2 syntax as defined here: https://github.com/google/re2/wiki/Syntax.
  groups:
    - title: Features
      regexp: '^.*?feat(\([[:word:]]+\))??!?:.+$'
      order: 0
    - title: "Bug fixes"
      regexp: '^.*?bug(\([[:word:]]+\))??!?:.+$'
      order: 1
    - title: Others
      order: 999

      # A group can have subgroups.
      # If you use this, all the commits that match the parent group will also
      # be checked against its subgroups. If some of them matches, it'll be
      # grouped there, otherwise they'll remain not grouped.
      #
      # The title is optional - you can think of groups as a way to order
      # commits within a group.
      #
      # There can only be one level of subgroups, i.e.: a subgroup can't have
      # subgroups within it.
      #
      # This feature is only available in GoReleaser Pro.
      groups:
        - title: "Docs"
          regex: ".*docs.*"
          order: 1
        - title: "CI"
          regex: ".*build.*"
          order: 2

  # Divider to use between groups.
  #
  # This feature is only available in GoReleaser Pro.
  divider: "---"

  filters:
    # Commit messages matching the regexp listed here will be removed from
    # the changelog
    #
    # Matches are performed against the first line of the commit message only,
    # prefixed with the commit SHA1, usually in the form of
    # `<abbrev-commit>[:] <title-commit>`.
    exclude:
      - "^docs:"
      - typo
      - (?i)foo

    # Commit messages matching the regexp listed here will be the only ones
    # added to the changelog
    #
    # If include is not-empty, exclude will be ignored.
    #
    # Matches are performed against the first line of the commit message only,
    # prefixed with the commit SHA1, usually in the form of
    # `<abbrev-commit>[:] <title-commit>`.
    include:
      - "^feat:"
```

!!! warning

    Some things to keep an eye on:

    * The `github-native` changelog does not support `sort` and `filter`.
    * When releasing a [nightly][], `use` will fallback to `git`.
    * The `github` changelog will only work if both tags exist in GitHub.

[nightly]: ./nightlies.md
The `release` section automates the generation and publication of release notes, appending additional information to the changelog created by the `changelog` section. It creates a draft release on GitHub with customizable details, streamlining the release process and ensuring consistency in documentation.

## Example Configuration

```yaml
release:
  mode: append
  draft: true
  footer: |
    ---
    ## Installation

    Packages downloaded from {{ .Env.GITHUB_SERVER_URL }}/{{ .Env.GITHUB_REPOSITORY }}/releases/ are considered official binaries.
```

## Key Features

- **Automated Release Notes**
   Simplifies the release process by automatically generating and appending release notes.

- **Consistency and Customization**
   Ensures alignment with the changelog while allowing custom details, such as security instructions or installation steps.

- **Controlled Publishing**
   Supports draft releases, enabling verification before publication.

## Configuration Options

### `mode` Option

```yaml
mode: append
```

- Defines how release notes interact with the existing changelog.
- **`append`**: Adds additional release-specific details to the changelog, maintaining a consistent and enriched record.

### `draft` Option

```yaml
draft: true
```

- When set to `true`, the release is created as a draft on GitHub, allowing for manual review and edits before publishing.

### `footer` Option

```yaml
footer: |
  ...
```

- Adds custom information at the bottom of the release notes.
- Use it to include instructions for installation, binary verification, and security guidelines, ensuring users have all essential information.

---

# Quoting the GoReleaser documentation:

- https://goreleaser.com/customization/release/

## Release

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

### GitHub

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

```yaml title=".goreleaser.yaml"
release:
  # Repo in which the release will be created.
  # Default: 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.
  # Note: all GitHub releases start as drafts while artifacts are uploaded.
  # Available only for GitHub and Gitea.
  draft: true

  # 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.
  replace_existing_draft: true

  # Whether to use an existing draft release as the target release.
  #
  # Available only for GitHub.
  # Since: v2.5.
  use_existing_draft: true

  # Whether to remove an artifact that already exists.
  #
  # Available only for GitHub.
  # This might be a bit expensive (rate-limiting speaking), so it is only done
  # when the upload of an artifact fails with a 422 (which means it already
  # exists in the release).
  # We then grab the list of artifacts from the release, and delete the file
  # that matches the one we're trying to upload.
  # GoReleaser will then retry its upload.
  replace_existing_artifacts: true

  # 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: ''.
  # 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.
  #
  # This feature is only available in GoReleaser Pro.
  # Default: '{{ .PrefixedCurrentTag }}'.
  # 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 goreleaser/goreleaser#2304 for more info.
  #
  # Default: ''.
  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: 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: true.
  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: `keep-existing`.
  mode: append

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

    Welcome to this new release!

  # Header for the release body.
  #
  # This feature is only available in GoReleaser Pro.
  header:
    # Loads from an URL.
    from_url:
      # Templates: allowed.
      url: https://foo.bar/header.md
      headers:
        x-api-token: "${MYCOMPANY_TOKEN}"

    # Loads from a local file.
    # Overrides `from_url`.
    from_file:
      # Templates: allowed.
      path: ./header.md

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

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

  # Footer for the release body.
  #
  # This feature is only available in GoReleaser Pro.
  footer:
    # Loads from an URL.
    from_url:
      # Templates: allowed.
      url: https://foo.bar/footer.md
      footers:
        x-api-token: "${MYCOMPANY_TOKEN}"

    # Loads from a local file.
    # Overrides `from_url`.
    from_file:
      # Templates: allowed.
      path: ./footer.md

  # 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.
  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.
  #
  # Templates: allowed.
  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.
  #
  # This feature is only available in GoReleaser Pro.
  # Templates: allowed.
  templated_extra_files:
    - src: LICENSE.tpl
      dst: LICENSE.txt

  # Upload metadata.json and artifacts.json to the release as well.
  include_meta: true

```

!!! tip

    [Learn how to set up an API token, GitHub Enterprise, etc](../scm/github.md).

<!-- md:pro -->

### GitLab

Let's see what can be customized in the `release` section for GitLab.

```yaml title=".goreleaser.yaml"
release:
  # Default: extracted from the origin remote URL or empty if its private
  #  hosted.
  # You can also use Gitlab's internal project id by setting it in the name
  #  field and leaving the owner field empty.
  gitlab:
    owner: user
    name: repo

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

  # 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 upload any artifacts.
  disable: 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: 'keep-existing'.
  mode: append

  # 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
```

!!! tip

    [Learn how to set up an API token, self-hosted GitLab, etc](../scm/gitlab.md).

!!! tip

    If you use GitLab subgroups, you need to specify it in the `owner` field,
    e.g. `mygroup/mysubgroup`.

!!! warning

    Only GitLab `v12.9+` is supported for releases.

### Gitea

You can also configure the `release` section to upload to a [Gitea](https://gitea.io) instance:

```yaml title=".goreleaser.yaml"
release:
  gitea:
    owner: user
    name: repo

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

  # 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 upload any artifacts.
  disable: 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: 'keep-existing'.
  mode: append

  # 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
```

To enable uploading `tar.gz` and `checksums.txt` files you need to add the
following to your Gitea config in `app.ini`:

```ini
[attachment]
ALLOWED_TYPES = application/gzip|application/x-gzip|application/x-gtar|application/x-tgz|application/x-compressed-tar|text/plain
```

!!! tip

    [Learn how to set up an API token](../scm/gitea.md).

<!-- md:templates -->

!!! warning

    Gitea versions earlier than 1.9.2 do not support uploading `checksums.txt`
    files because of a [bug](go-gitea/gitea#7882),
    so you will have to enable all file types with `*/*`.

!!! warning

    `draft` and `prerelease` are only supported by GitHub and Gitea.

#### Define Previous Tag

GoReleaser uses `git describe` to get the previous tag used for generating the
Changelog. You can set a different build tag using the environment variable
`GORELEASER_PREVIOUS_TAG`. This is useful in scenarios where two tags point to
the same commit.

The [Nightly](nightlies.md) is automatically ignored, even if set
via the environment variables above.

### 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](https://en.wikipedia.org/wiki/Process_substitution). To
list all commits since the last tag, but skip ones starting with `Merge` or
`docs`, you could run this command:

```sh
goreleaser release --release-notes <(some_changelog_generator)
```

Some changelog generators you can use:

- [buchanae/github-release-notes](https://github.com/buchanae/github-release-notes)
- [miniscruff/changie](https://github.com/miniscruff/changie)

!!! info

    If you create the release before running GoReleaser, and the said release
    has some text in its body, GoReleaser will not override it with its release
    notes.
@github-actions github-actions bot added the enhancement New feature or request label Dec 23, 2024
@tmknom tmknom merged commit c3db52e into main Dec 23, 2024
@tmknom tmknom deleted the feat/add-goreleaser-config-for-default branch December 23, 2024 10:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant