---
title: Announcing GoReleaser v2.12
date: 2025-08-03
slug: goreleaser-v2.12
tags: [announcements]
authors: [caarlos0]
---

This version introduces the new version of the Docker integration,
Docker image attestation,
Makeself packaging support,
Go 1.25,
and much more!

<!--more-->

## Docker v2

The `dockers` feature in GoReleaser is rather old:
it's from a time before multi-architecture Docker images (manifests).
Its configuration is also very verbose and repetitive.

These were problems we were aiming to solve for a while, and after a lot of
discussion, we arrived at what I think is a good solution.

It'll be in alpha stage for a while, and you can use it as `dockers_v2` in your
configuration.

Once we're set on the API, we'll deprecate `dockers` and `docker_manifests`.

Eventually, when we launch GoReleaser v3, the old features will be removed, and
`dockers_v2` will simply be `dockers`.

That all being said, let's dive in!

### How it works

Basically, we'll always use `docker buildx` to build the manifest.
This means:

- no more `dockers` + `docker_manifests` wiring
- no more tags with the architecture in them (i.e. no more intermediate images)
- no more docker image configuration repetition

Depending on how familiar you are with Docker manifests, you may be asking "how
does this work when I do a local build with `--snapshot`?" - and that's a great
question!
Manifests require us to push the images, so, to avoid doing that in snapshot
builds, when the build is a snapshot, GoReleaser will automatically "explode"
the build configuration by platform, and build local images with the
architecture in the tag.
This allows you to still test both the build process and correctness of the
images without having to push any images.

### How to use it?

A simple configuration would look like this:

```yaml {filename=".goreleaser.yaml"}
dockers_v2:
  - images:
      - user/repo
    tags:
      - "{{.Version}}"
      - latest
    platform:
      - linux/amd64
      - linux/arm64
```

And the `Dockerfile` might look like so:

```dockerfile {filename="Dockerfile"}
FROM scratch
ARG TARGETPLATFORM
ENTRYPOINT ["/usr/bin/myprogram"]
COPY $TARGETPLATFORM/myprogram /usr/bin/
```

You can add however many images and tags you want, and GoReleaser will build the
combination of all of them.
You can also set `annotations`, `labels`, Docker flags, etc.

Read the [documentation][docker-docs] for more information.

## Makeself

[Makeself][] allows to create packages that self-extract/run.
GoReleaser now supports creating them.

You basically only need to set the script that it'll run after extracting your
binary.

Here's an example:

```yaml {filename=".goreleaser.yaml"}
makeselfs:
  - script: ./run.sh
```

Your shell script can simply be:

```sh {filename="run.sh"}
#!/bin/sh
./myprogram $*
```

And it should work.
Read the [documentation][makeself-docs] for more information.

## Attestations

You can now also more easily attest your Docker images within GitHub actions.

Basically, GoReleaser will now automatically generate `./dist/digests.txt` file,
which you can then pass to the attest action:

```yaml {filename="./.github/workflows/release.yaml"}
# ...
permissions:
  # ...
  # Give the workflow permission to write attestations.
  id-token: write
  attestations: write

jobs:
  release:
    # ...
    steps:
      # ...
      - uses: goreleaser/goreleaser-action@v6
        with:
          # ...
      # After GoReleaser runs, attest all the files in ./dist/checksums.txt:
      - uses: actions/attest@v4
        with:
          subject-checksums: ./dist/checksums.txt
      # After GoReleaser runs, attest all the images in ./dist/digests.txt:
      - uses: actions/attest@v4
        with:
          subject-checksums: ./dist/digests.txt
```

This will create 2 attestations, one for binaries/archives/etc and another one
for your Docker images.

Read the [documentation][attest] for more information.

Thanks to [Brian DeHamer](https://github.com/bdehamer) from the GitHub team for
the help making this happen!

## Smarter semver tag sorting

{{< g_featpro >}}

If you do constant pre-releases, this is for you!

Imagine you have a history like this:

```
v0.1.0
v0.2.0-beta.1
v0.2.0-beta.2
v0.2.0-beta.3
v0.2.0
```

And you want to release `v0.2.0`.
Usually, GoReleaser would get `v0.2.0-beta.3` as previous version, but that's
likely not what most people would expect (`v0.1.0`).

Smart semver will ignore pre-release versions in these cases, making the release
notes more complete.

To use it, add this to your configuration:

```yaml {filename=".goreleaser.yaml"}
git:
  tag_sort: smartsemver
```

> [!NOTE]
> If you were to release `v0.2.0-beta.3`, though, it would still get
> `v0.2.0-beta.2` as previous version, which I think makes sense.

See the [documentation][smartsemver] for more details.

## Other highlights

- **pro**: create nightly releases as drafts (`nightly.draft`)
- **pro**: set custom body in pull requests
- **pro**: set the changelog title
- **pro**: `commit_author` can now be set globally in `metadata`
- **builds/bun**: allowing more targets
- **builds/go**: updated allowed targets
- **mcp**: can now give instructions to the LLM on how to fix deprecations
- **templates**: add `readFile` and `mustReadFile`
- **upload,artifactory**: allow to set `password`
- **upload,artifactory**: allow templates in `username`
- **docker**: retry configurations
- **brew**: uses `&&` instead of `and`
- **cask**: removes `conflicts_with` (deprecated by Homebrew)

## Other news

- GoReleaser now has ~15.1k stars and 440 contributors! Thanks, everyone!
- We often discuss new features in our Discord server. 
  [Join the conversation][discord]!
- nFPM had new releases as well, 
  [check it out](https://github.com/goreleaser/nfpm/releases).
- The GoReleaser Action had a new release,
  [check it out](https://github.com/goreleaser/goreleaser-action/releases)

## Download

You can install or upgrade using your favorite package manager, or see the
full release notes and download the pre-compiled binaries from GitHub:

{{< g_button href="https://goreleaser.com/install" label="Install" icon="download" primary="true" >}}
{{< g_button href="https://github.com/goreleaser/goreleaser/releases/tag/v2.12.0" label="v2.12.0 (OSS)" icon="github" primary="false" >}}
{{< g_button href="https://github.com/goreleaser/goreleaser-pro/releases/tag/v2.12.0" label="v2.12.0 (Pro)" icon="github" primary="false" >}}

## Helping out

You can help by reporting issues, contributing features, documentation
improvements, and bug fixes.
You can also sponsor the project, or get a GoReleaser Pro license.

{{< g_button href="https://goreleaser.com/pro" label="Get the Pro license" icon="pro" primary="true" >}}
{{< g_button href="https://goreleaser.com/sponsors" label="Sponsor the project" icon="sponsor" primary="false" >}}

[discord]: https://goreleaser.com/discord
[Makeself]: https://makeself.io/
[makeself-docs]: https://goreleaser.com/customization/makeself
[docker-docs]: https://goreleaser.com/customization/dockers_v2/
[attest]: https://goreleaser.com/customization/attestations/
[smartsemver]: https://goreleaser.com/customization/git/#smart-semver-sorting
