Repository: goreleaser/goreleaser
Pull request #2820 (2022-01-10 08:02:17)

feat(deps): bump github.com/xanzy/go-gitlab from 0.52.2 to 0.54.3
Bumps [github.com/xanzy/go-gitlab](https://github.com/xanzy/go-gitlab) from 0.52.2 to 0.54.3.
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/xanzy/go-gitlab/commit/d909b32337c62d48b1bbbb49f829d6f4e943efae"><code>d909b32</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/xanzy/go-gitlab/issues/1337">#1337</a> from hensur/put-edit-project</li>
<li><a href="https://github.com/xanzy/go-gitlab/commit/37ded3f8523866fcf7a979d9126ac0e12dc247af"><code>37ded3f</code></a> use put for EditProject</li>
<li><a href="https://github.com/xanzy/go-gitlab/commit/3d128ad803dd28c9bbcb653da9593c08de1e9bd3"><code>3d128ad</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/xanzy/go-gitlab/issues/1335">#1335</a> from Bouwdie/assignee-id-merge-request-type</li>
<li><a href="https://github.com/xanzy/go-gitlab/commit/a5081d968c979aa768729061da8856d34308f7a6"><code>a5081d9</code></a> Make the user ID part a little mor generic</li>
<li><a href="https://github.com/xanzy/go-gitlab/commit/2ea307f936b341bc85ee5bc2c5d4a9b7738e283e"><code>2ea307f</code></a> Add None and Any options for AssigneeID for all merge request list functions.</li>
<li><a href="https://github.com/xanzy/go-gitlab/commit/c465c6c5ecc7b905eeb546383983580f2d4dff16"><code>c465c6c</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/xanzy/go-gitlab/issues/1334">#1334</a> from Bouwdie/update-go-querystring-dependency</li>
<li><a href="https://github.com/xanzy/go-gitlab/commit/49f1cf35ce834dbe77ffbd53ab4793b8f8760784"><code>49f1cf3</code></a> Update google/go-querystring dependency to v1.1.0</li>
<li><a href="https://github.com/xanzy/go-gitlab/commit/31a1f8a7b6af4c73e182d6ed4687e576ebc39b07"><code>31a1f8a</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/xanzy/go-gitlab/issues/1294">#1294</a> from xanzy/bugfix/slices</li>
<li><a href="https://github.com/xanzy/go-gitlab/commit/683eca87e23839b5ac6ac7e900e4ff706fae09ce"><code>683eca8</code></a> Make all option struct fields pointers</li>
<li><a href="https://github.com/xanzy/go-gitlab/commit/609ee71da5031ab4466ba064e3eef4df84440c15"><code>609ee71</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/xanzy/go-gitlab/issues/1318">#1318</a> from mitar/support-avatar</li>
<li>Additional commits viewable in <a href="https://github.com/xanzy/go-gitlab/compare/v0.52.2...v0.54.3">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/xanzy/go-gitlab&package-manager=go_modules&previous-version=0.52.2&new-version=0.54.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>

codecov[bot]: # [Codecov](https://codecov.io/gh/goreleaser/goreleaser/pull/2820?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser) Report
> Merging [#2820](https://codecov.io/gh/goreleaser/goreleaser/pull/2820?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser) (1225bb8) into [main](https://codecov.io/gh/goreleaser/goreleaser/commit/592e763f6b1a3f9658cae2f2310d2e32d25c8431?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser) (592e763) will **increase** coverage by `0.00%`.
> The diff coverage is `100.00%`.

> :exclamation: Current head 1225bb8 differs from pull request most recent head ac1ba60. Consider uploading reports for the commit ac1ba60 to get more accurate results
[![Impacted file tree graph](https://codecov.io/gh/goreleaser/goreleaser/pull/2820/graphs/tree.svg?width=650&height=150&src=pr&token=3bJvv6b7hN&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser)](https://codecov.io/gh/goreleaser/goreleaser/pull/2820?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser)

```diff
@@           Coverage Diff           @@
##             main    #2820   +/-   ##
=======================================
  Coverage   84.42%   84.42%           
=======================================
  Files         111      111           
  Lines        8783     8784    +1     
=======================================
+ Hits         7415     7416    +1     
  Misses       1101     1101           
  Partials      267      267           
```


| [Impacted Files](https://codecov.io/gh/goreleaser/goreleaser/pull/2820?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser) | Coverage Δ | |
|---|---|---|
| [internal/client/gitlab.go](https://codecov.io/gh/goreleaser/goreleaser/pull/2820/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser#diff-aW50ZXJuYWwvY2xpZW50L2dpdGxhYi5nbw==) | `77.46% <100.00%> (+0.05%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/goreleaser/goreleaser/pull/2820?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/goreleaser/goreleaser/pull/2820?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser). Last update [592e763...ac1ba60](https://codecov.io/gh/goreleaser/goreleaser/pull/2820?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser).


Patch:
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 2f4ed230..afc4592a 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -124,4 +124,5 @@ jobs:
           FURY_TOKEN: ${{ secrets.FURY_TOKEN }}
           DISCORD_WEBHOOK_ID: ${{ secrets.DISCORD_WEBHOOK_ID }}
           DISCORD_WEBHOOK_TOKEN: ${{ secrets.DISCORD_WEBHOOK_TOKEN }}
+          AUR_KEY: ${{ secrets.AUR_KEY }}
         run: task goreleaser
diff --git a/.goreleaser.yaml b/.goreleaser.yaml
index 2f3e0ada..f781b930 100644
--- a/.goreleaser.yaml
+++ b/.goreleaser.yaml
@@ -1,5 +1,7 @@
 env:
   - GO111MODULE=on
+  - DESCRIPTION="Deliver Go binaries as fast and easily as possible"
+  - README_URL="https://raw.githubusercontent.com/goreleaser/goreleaser/main/README.md"
 
 before:
   hooks:
@@ -69,6 +71,8 @@ dockers:
   use: buildx
   build_flag_templates:
   - "--pull"
+  - "--label=io.artifacthub.package.readme-url={{.Env.README_URL}}"
+  - "--label=org.opencontainers.image.description={{.Env.DESCRIPTION}}"
   - "--label=org.opencontainers.image.created={{.Date}}"
   - "--label=org.opencontainers.image.name={{.ProjectName}}"
   - "--label=org.opencontainers.image.revision={{.FullCommit}}"
@@ -84,6 +88,8 @@ dockers:
   use: buildx
   build_flag_templates:
   - "--pull"
+  - "--label=io.artifacthub.package.readme-url={{.Env.README_URL}}"
+  - "--label=org.opencontainers.image.description={{.Env.DESCRIPTION}}"
   - "--label=org.opencontainers.image.created={{.Date}}"
   - "--label=org.opencontainers.image.name={{.ProjectName}}"
   - "--label=org.opencontainers.image.revision={{.FullCommit}}"
diff --git a/cmd/release.go b/cmd/release.go
index 292ed753..bfc3844a 100644
--- a/cmd/release.go
+++ b/cmd/release.go
@@ -72,7 +72,7 @@ func newReleaseCmd() *releaseCmd {
 	}
 
 	cmd.Flags().StringVarP(&root.opts.config, "config", "f", "", "Load configuration from file")
-	cmd.Flags().StringVar(&root.opts.releaseNotesFile, "release-notes", "", "Load custom release notes from a markdown file")
+	cmd.Flags().StringVar(&root.opts.releaseNotesFile, "release-notes", "", "Load custom release notes from a markdown file (will skip GoReleaser changelog generation)")
 	cmd.Flags().StringVar(&root.opts.releaseHeaderFile, "release-header", "", "Load custom release notes header from a markdown file")
 	cmd.Flags().StringVar(&root.opts.releaseFooterFile, "release-footer", "", "Load custom release notes footer from a markdown file")
 	cmd.Flags().StringVar(&root.opts.releaseNotesTmpl, "release-notes-tmpl", "", "Load custom release notes from a templated markdown file (overrides --release-notes)")
diff --git a/go.mod b/go.mod
index eb45260d..1981e7d6 100644
--- a/go.mod
+++ b/go.mod
@@ -31,7 +31,7 @@ require (
 	github.com/spf13/cobra v1.3.0
 	github.com/stretchr/testify v1.7.0
 	github.com/ulikunitz/xz v0.5.10
-	github.com/xanzy/go-gitlab v0.52.2
+	github.com/xanzy/go-gitlab v0.54.3
 	gocloud.dev v0.24.0
 	golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3
 	golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
diff --git a/go.sum b/go.sum
index 74908bae..b1d1045f 100644
--- a/go.sum
+++ b/go.sum
@@ -784,8 +784,8 @@ github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oW
 github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
 github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8=
 github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
-github.com/xanzy/go-gitlab v0.52.2 h1:gkgg1z4ON70sphibtD86Bfmt1qV3mZ0pU0CBBCFAEvQ=
-github.com/xanzy/go-gitlab v0.52.2/go.mod h1:Q+hQhV508bDPoBijv7YjK/Lvlb4PhVhJdKqXVQrUoAE=
+github.com/xanzy/go-gitlab v0.54.3 h1:fPfZ3Jcu5dPc3xyIYtAALZsEgoyKNFNuULD+TdJ7Zvk=
+github.com/xanzy/go-gitlab v0.54.3/go.mod h1:F0QEXwmqiBUxCgJm8fE9S+1veX4XC9Z4cfaAbqwk4YM=
 github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
 github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
 github.com/xanzy/ssh-agent v0.3.1 h1:AmzO1SSWxw73zxFZPRwaMN1MohDw8UyHnmuxyceTEGo=
diff --git a/internal/artifact/artifact.go b/internal/artifact/artifact.go
index 8b8ce9a1..6050d5e8 100644
--- a/internal/artifact/artifact.go
+++ b/internal/artifact/artifact.go
@@ -256,6 +256,10 @@ func (artifacts Artifacts) List() []*Artifact {
 func (artifacts Artifacts) GroupByID() map[string][]*Artifact {
 	result := map[string][]*Artifact{}
 	for _, a := range artifacts.items {
+		id := a.ID()
+		if id == "" {
+			continue
+		}
 		result[a.ID()] = append(result[a.ID()], a)
 	}
 	return result
diff --git a/internal/client/gitlab.go b/internal/client/gitlab.go
index 1e25ef32..9fc0d29f 100644
--- a/internal/client/gitlab.go
+++ b/internal/client/gitlab.go
@@ -5,6 +5,7 @@ import (
 	"fmt"
 	"net/http"
 	"os"
+	"path/filepath"
 	"strings"
 
 	"github.com/apex/log"
@@ -406,7 +407,8 @@ func (c *gitlabClient) Upload(
 		log.WithField("file", file.Name()).Debug("uploading file as attachment")
 		projectFile, _, err := c.client.Projects.UploadFile(
 			projectID,
-			file.Name(),
+			file,
+			filepath.Base(file.Name()),
 			nil,
 		)
 		if err != nil {
diff --git a/internal/pipe/artifacts/artifacts.go b/internal/pipe/artifacts/artifacts.go
deleted file mode 100644
index 695558ce..00000000
--- a/internal/pipe/artifacts/artifacts.go
+++ /dev/null
@@ -1,28 +0,0 @@
-// Package artifacts provides the pipe implementation that creates a artifacts.json file in the dist folder.
-package artifacts
-
-import (
-	"encoding/json"
-	"os"
-	"path/filepath"
-
-	"github.com/apex/log"
-	"github.com/goreleaser/goreleaser/pkg/context"
-)
-
-// Pipe implementation.
-type Pipe struct{}
-
-func (Pipe) String() string                 { return "storing artifact list" }
-func (Pipe) Skip(ctx *context.Context) bool { return false }
-
-// Run the pipe.
-func (Pipe) Run(ctx *context.Context) error {
-	bts, err := json.Marshal(ctx.Artifacts.List())
-	if err != nil {
-		return err
-	}
-	path := filepath.Join(ctx.Config.Dist, "artifacts.json")
-	log.Log.WithField("file", path).Info("writing")
-	return os.WriteFile(path, bts, 0o644)
-}
diff --git a/internal/pipe/aur/aur.go b/internal/pipe/aur/aur.go
index f97e0fe7..e98049ae 100644
--- a/internal/pipe/aur/aur.go
+++ b/internal/pipe/aur/aur.go
@@ -25,7 +25,7 @@ import (
 
 const (
 	pkgBuildExtra     = "AURConfig"
-	defaultSSHCommand = "ssh -i {{ .KeyPath }} -F /dev/null"
+	defaultSSHCommand = "ssh -i {{ .KeyPath }} -o StrictHostKeyChecking=accept-new -F /dev/null"
 	defaultCommitMsg  = "Update to {{ .Tag }}"
 )
 
@@ -278,7 +278,7 @@ func dataFor(ctx *context.Context, cfg config.AUR, cl client.Client, artifacts [
 		Name:         cfg.Name,
 		Desc:         cfg.Description,
 		Homepage:     cfg.Homepage,
-		Version:      ctx.Version,
+		Version:      fmt.Sprintf("%d.%d.%d", ctx.Semver.Major, ctx.Semver.Minor, ctx.Semver.Patch),
 		License:      cfg.License,
 		Rel:          cfg.Rel,
 		Maintainers:  cfg.Maintainers,
diff --git a/internal/pipe/metadata/metadata.go b/internal/pipe/metadata/metadata.go
new file mode 100644
index 00000000..3dfb6de9
--- /dev/null
+++ b/internal/pipe/metadata/metadata.go
@@ -0,0 +1,60 @@
+// Package metadata provides the pipe implementation that creates a artifacts.json file in the dist folder.
+package metadata
+
+import (
+	"encoding/json"
+	"os"
+	"path/filepath"
+	"time"
+
+	"github.com/apex/log"
+	"github.com/goreleaser/goreleaser/pkg/context"
+)
+
+// Pipe implementation.
+type Pipe struct{}
+
+func (Pipe) String() string                 { return "storing release metadata" }
+func (Pipe) Skip(ctx *context.Context) bool { return false }
+
+// Run the pipe.
+func (Pipe) Run(ctx *context.Context) error {
+	if err := writeArtifacts(ctx); err != nil {
+		return err
+	}
+	return writeMetadata(ctx)
+}
+
+func writeMetadata(ctx *context.Context) error {
+	return writeJSON(ctx, metadata{
+		ProjectName: ctx.Config.ProjectName,
+		Tag:         ctx.Git.CurrentTag,
+		PreviousTag: ctx.Git.PreviousTag,
+		Version:     ctx.Version,
+		Commit:      ctx.Git.Commit,
+		Date:        ctx.Date,
+	}, "metadata.json")
+}
+
+func writeArtifacts(ctx *context.Context) error {
+	return writeJSON(ctx, ctx.Artifacts.List(), "artifacts.json")
+}
+
+func writeJSON(ctx *context.Context, j interface{}, name string) error {
+	bts, err := json.Marshal(j)
+	if err != nil {
+		return err
+	}
+	path := filepath.Join(ctx.Config.Dist, name)
+	log.Log.WithField("file", path).Info("writing")
+	return os.WriteFile(path, bts, 0o644)
+}
+
+type metadata struct {
+	ProjectName string    `json:"project_name"`
+	Tag         string    `json:"tag"`
+	PreviousTag string    `json:"previous_tag"`
+	Version     string    `json:"version"`
+	Commit      string    `json:"commit"`
+	Date        time.Time `json:"date"`
+}
diff --git a/internal/pipeline/pipeline.go b/internal/pipeline/pipeline.go
index 4d3f830d..e4c995d5 100644
--- a/internal/pipeline/pipeline.go
+++ b/internal/pipeline/pipeline.go
@@ -6,7 +6,6 @@ import (
 
 	"github.com/goreleaser/goreleaser/internal/pipe/announce"
 	"github.com/goreleaser/goreleaser/internal/pipe/archive"
-	"github.com/goreleaser/goreleaser/internal/pipe/artifacts"
 	"github.com/goreleaser/goreleaser/internal/pipe/aur"
 	"github.com/goreleaser/goreleaser/internal/pipe/before"
 	"github.com/goreleaser/goreleaser/internal/pipe/brew"
@@ -22,6 +21,7 @@ import (
 	"github.com/goreleaser/goreleaser/internal/pipe/gofish"
 	"github.com/goreleaser/goreleaser/internal/pipe/gomod"
 	"github.com/goreleaser/goreleaser/internal/pipe/krew"
+	"github.com/goreleaser/goreleaser/internal/pipe/metadata"
 	"github.com/goreleaser/goreleaser/internal/pipe/nfpm"
 	"github.com/goreleaser/goreleaser/internal/pipe/prebuild"
 	"github.com/goreleaser/goreleaser/internal/pipe/publish"
@@ -65,7 +65,7 @@ var BuildPipeline = []Piper{
 
 // BuildCmdPipeline is the pipeline run by goreleaser build.
 // nolint:gochecknoglobals
-var BuildCmdPipeline = append(BuildPipeline, artifacts.Pipe{})
+var BuildCmdPipeline = append(BuildPipeline, metadata.Pipe{})
 
 // Pipeline contains all pipe implementations in order.
 // nolint: gochecknoglobals
@@ -84,7 +84,7 @@ var Pipeline = append(
 	checksums.Pipe{},     // checksums of the files
 	sign.Pipe{},          // sign artifacts
 	docker.Pipe{},        // create and push docker images
-	artifacts.Pipe{},     // creates an artifacts.json in the dist folder
+	metadata.Pipe{},      // creates a metadata.json and an artifacts.json files in the dist folder
 	publish.Pipe{},       // publishes artifacts
 	announce.Pipe{},      // announce releases
 )
diff --git a/pkg/config/config.go b/pkg/config/config.go
index f5e23451..6ce409c5 100644
--- a/pkg/config/config.go
+++ b/pkg/config/config.go
@@ -521,7 +521,7 @@ type ExtraFile struct {
 
 // NFPM config.
 type NFPM struct {
-	NFPMOverridables `yaml:",inline"`
+	NFPMOverridables `yaml:",inline"`            // nolint: tagliatelle
 	Overrides        map[string]NFPMOverridables `yaml:"overrides,omitempty"`
 
 	ID          string   `yaml:"id,omitempty"`
diff --git a/scripts/pre-commit.sh b/scripts/pre-commit.sh
index aaf2b536..2c617023 100755
--- a/scripts/pre-commit.sh
+++ b/scripts/pre-commit.sh
@@ -1,7 +1,7 @@
 #!/bin/bash
 FILES=$(git diff --cached --name-only --diff-filter=ACMR)
 
-gofumpt -s -l -w .
+gofumpt -l -w .
 golangci-lint run --new --fix
 
 git add $FILES
diff --git a/www/docs/cmd/goreleaser_release.md b/www/docs/cmd/goreleaser_release.md
index 75e7882f..8506c855 100644
--- a/www/docs/cmd/goreleaser_release.md
+++ b/www/docs/cmd/goreleaser_release.md
@@ -19,7 +19,7 @@ goreleaser release [flags]
       --release-footer-tmpl string   Load custom release notes footer from a templated markdown file (overrides --release-footer)
       --release-header string        Load custom release notes header from a markdown file
       --release-header-tmpl string   Load custom release notes header from a templated markdown file (overrides --release-header)
-      --release-notes string         Load custom release notes from a markdown file
+      --release-notes string         Load custom release notes from a markdown file (will skip GoReleaser changelog generation)
       --release-notes-tmpl string    Load custom release notes from a templated markdown file (overrides --release-notes)
       --rm-dist                      Removes the dist folder
       --skip-announce                Skips announcing releases (implies --skip-validate)
diff --git a/www/docs/cookbooks/cgo-and-crosscompiling.md b/www/docs/cookbooks/cgo-and-crosscompiling.md
index 8030b5eb..6ab61949 100644
--- a/www/docs/cookbooks/cgo-and-crosscompiling.md
+++ b/www/docs/cookbooks/cgo-and-crosscompiling.md
@@ -1,5 +1,5 @@
 # Cross-compiling Go with CGO
 
 Best option to cross-compile Go project with CGO dependencies would be in using Docker image.
-[This project](https://github.com/troian/golang-cross) provides the [image](https://hub.docker.com/repository/docker/troian/golang-cross) with bunch of ready to use cross-compilers as well as how-to make sysroot.
-All that wrapped into [example](https://github.com/troian/golang-cross-example)
+[This project](https://github.com/goreleaser/goreleaser-cross) provides the docker [images](https://hub.docker.com/repository/docker/goreleaser/goreleaser-cross) with bunch of ready to use cross-compilers as well as how-to make sysroot.
+All that wrapped into [example](https://github.com/goreleaser/goreleaser-cross-example)
diff --git a/www/docs/customization/aur.md b/www/docs/customization/aur.md
index 58daa1f5..17c78dc1 100644
--- a/www/docs/customization/aur.md
+++ b/www/docs/customization/aur.md
@@ -137,7 +137,7 @@ aurs:
     # This is mainly used to specify the SSH private key used to pull/push to
     # the Git URL.
     #
-    # Defaults to `ssh -i {{ .KeyPath }} -F /dev/null`.
+    # Defaults to `ssh -i {{ .KeyPath }} -o StrictHostKeyChecking=accept-new -F /dev/null`.
     git_ssh_command: 'ssh -i {{ .Env.KEY }} -o SomeOption=yes'
 
     # Template for the url which is determined by the given Token
diff --git a/www/docs/customization/changelog.md b/www/docs/customization/changelog.md
index 468d1d65..65c6bc67 100644
--- a/www/docs/customization/changelog.md
+++ b/www/docs/customization/changelog.md
@@ -5,7 +5,9 @@ You can customize how the changelog is generated using the `changelog` section i
 ```yaml
 # .goreleaser.yml
 changelog:
-  # Set it to true if you wish to skip the changelog generation.
+  # 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.
   skip: true
 
diff --git a/www/docs/deprecations.md b/www/docs/deprecations.md
index 56ce6e43..c84fa88d 100644
--- a/www/docs/deprecations.md
+++ b/www/docs/deprecations.md
@@ -40,7 +40,7 @@ Description.
 
 > since 2022-01-20 (v1.4.0)
 
-On [GoReleaser PRO][pro], custom variables should now be prefixed with `.Var`.
+On [GoReleaser PRO](/pro/) custom variables should now be prefixed with `.Var`.
 
 === "Before"
 
diff --git a/www/docs/how-it-works.md b/www/docs/how-it-works.md
index edc39083..853bab2c 100644
--- a/www/docs/how-it-works.md
+++ b/www/docs/how-it-works.md
@@ -1,13 +1,15 @@
 # How it works
 
-GoReleaser goal is to automate most of the boring work you'll had while releasing software.
-Ideally, using sensible defaults and making the most common usecases easy.
+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) for more info)
+- a `.goreleaser.yaml` file with the configuration (see the
+  [customization section](/customization) for more info)
 - a clean working tree
-- a SemVer-compatible version (e.g. `10.21.34-something`)
+- a SemVer-compatible version (e.g. `10.21.34-prerelease+buildmeta`)
 
 And that's it.
 
@@ -17,9 +19,11 @@ 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...
+- **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-foo`-like flags (check the [command line docs](/cmd/goreleaser/) for details).
+Some steps might be skipped with `--skip-foo`-like flags (check the
+[command line docs](/cmd/goreleaser/) for details).
 
 If any of the previous steps fails, the next steps will not run.
diff --git a/www/docs/install.md b/www/docs/install.md
index 3b5c0f98..186922aa 100644
--- a/www/docs/install.md
+++ b/www/docs/install.md
@@ -104,6 +104,18 @@ Below you can find the steps for each of them.
     sudo yum install goreleaser-pro
     ```
 
+### aur
+
+=== "OSS"
+    ```sh
+    yay -S goreleaser-bin
+    ```
+
+=== "Pro"
+    ```sh
+    yay -S goreleaser-pro-bin
+    ```
+
 ### deb, rpm and apk packages
 
 


Test patch:
diff --git a/internal/artifact/artifact_test.go b/internal/artifact/artifact_test.go
index dcc35ef1..2a839203 100644
--- a/internal/artifact/artifact_test.go
+++ b/internal/artifact/artifact_test.go
@@ -181,6 +181,58 @@ func TestRemove(t *testing.T) {
 	})
 }
 
+func TestGroupByID(t *testing.T) {
+	data := []*Artifact{
+		{
+			Name: "foo",
+			Extra: map[string]interface{}{
+				ExtraID: "foo",
+			},
+		},
+		{
+			Name: "bar",
+			Extra: map[string]interface{}{
+				ExtraID: "foo",
+			},
+		},
+		{
+			Name: "foobar",
+			Goos: "linux",
+			Extra: map[string]interface{}{
+				ExtraID: "foovar",
+			},
+		},
+		{
+			Name: "foobar",
+			Goos: "linux",
+			Extra: map[string]interface{}{
+				ExtraID: "foovar",
+			},
+		},
+		{
+			Name: "foobar",
+			Goos: "linux",
+			Extra: map[string]interface{}{
+				ExtraID: "foobar",
+			},
+		},
+		{
+			Name: "check",
+			Type: Checksum,
+		},
+	}
+	artifacts := New()
+	for _, a := range data {
+		artifacts.Add(a)
+	}
+
+	groups := artifacts.GroupByID()
+	require.Len(t, groups["foo"], 2)
+	require.Len(t, groups["foobar"], 1)
+	require.Len(t, groups["foovar"], 2)
+	require.Len(t, groups, 3)
+}
+
 func TestGroupByPlatform(t *testing.T) {
 	data := []*Artifact{
 		{
diff --git a/internal/pipe/artifacts/artifacts_test.go b/internal/pipe/artifacts/artifacts_test.go
deleted file mode 100644
index c11a870d..00000000
--- a/internal/pipe/artifacts/artifacts_test.go
+++ /dev/null
@@ -1,40 +0,0 @@
-package artifacts
-
-import (
-	"os"
-	"path/filepath"
-	"testing"
-
-	"github.com/goreleaser/goreleaser/internal/artifact"
-	"github.com/goreleaser/goreleaser/internal/golden"
-	"github.com/goreleaser/goreleaser/pkg/config"
-	"github.com/goreleaser/goreleaser/pkg/context"
-	"github.com/stretchr/testify/require"
-)
-
-func TestArtifacts(t *testing.T) {
-	tmp := t.TempDir()
-	ctx := context.New(config.Project{
-		Dist: tmp,
-	})
-
-	ctx.Artifacts.Add(&artifact.Artifact{
-		Name:   "foo",
-		Path:   "foo.txt",
-		Type:   artifact.Binary,
-		Goos:   "darwin",
-		Goarch: "amd64",
-		Goarm:  "7",
-		Extra: map[string]interface{}{
-			"foo": "bar",
-		},
-	})
-
-	require.NoError(t, Pipe{}.Run(ctx))
-	path := filepath.Join(tmp, "artifacts.json")
-	golden.RequireEqualJSON(t, golden.RequireReadFile(t, path))
-
-	info, err := os.Stat(path)
-	require.NoError(t, err)
-	require.Equal(t, "-rw-r--r--", info.Mode().String())
-}
diff --git a/internal/pipe/aur/aur_test.go b/internal/pipe/aur/aur_test.go
index 6fcd05e4..605b918b 100644
--- a/internal/pipe/aur/aur_test.go
+++ b/internal/pipe/aur/aur_test.go
@@ -233,9 +233,15 @@ func TestFullPipe(t *testing.T) {
 			folder := t.TempDir()
 			ctx := &context.Context{
 				Git: context.GitInfo{
-					CurrentTag: "v1.0.1",
+					CurrentTag: "v1.0.1-foo",
 				},
-				Version:   "1.0.1",
+				Semver: context.Semver{
+					Major:      1,
+					Minor:      0,
+					Patch:      1,
+					Prerelease: "foo",
+				},
+				Version:   "1.0.1-foo",
 				Artifacts: artifact.New(),
 				Env: map[string]string{
 					"FOO": "foo_is_bar",
@@ -316,6 +322,11 @@ func TestRunPipe(t *testing.T) {
 		Git: context.GitInfo{
 			CurrentTag: "v1.0.1",
 		},
+		Semver: context.Semver{
+			Major: 1,
+			Minor: 0,
+			Patch: 1,
+		},
 		Version:   "1.0.1",
 		Artifacts: artifact.New(),
 		Env: map[string]string{
@@ -455,6 +466,11 @@ func TestRunPipeBinaryRelease(t *testing.T) {
 		Git: context.GitInfo{
 			CurrentTag: "v1.2.1",
 		},
+		Semver: context.Semver{
+			Major: 1,
+			Minor: 2,
+			Patch: 1,
+		},
 		Version:   "1.2.1",
 		Artifacts: artifact.New(),
 		Config: config.Project{
@@ -504,6 +520,12 @@ func TestRunPipeNoUpload(t *testing.T) {
 	})
 	ctx.TokenType = context.TokenTypeGitHub
 	ctx.Git = context.GitInfo{CurrentTag: "v1.0.1"}
+	ctx.Semver = context.Semver{
+		Major: 1,
+		Minor: 0,
+		Patch: 1,
+	}
+
 	path := filepath.Join(folder, "whatever.tar.gz")
 	f, err := os.Create(path)
 	require.NoError(t, err)
@@ -558,6 +580,11 @@ func TestRunEmptyTokenType(t *testing.T) {
 		},
 	})
 	ctx.Git = context.GitInfo{CurrentTag: "v1.0.1"}
+	ctx.Semver = context.Semver{
+		Major: 1,
+		Minor: 0,
+		Patch: 1,
+	}
 	path := filepath.Join(folder, "whatever.tar.gz")
 	f, err := os.Create(path)
 	require.NoError(t, err)
diff --git a/internal/pipe/aur/testdata/TestFullPipe/default-gitlab.pkgbuild.golden b/internal/pipe/aur/testdata/TestFullPipe/default-gitlab.pkgbuild.golden
index 7c19c2bd..10543e1f 100644
--- a/internal/pipe/aur/testdata/TestFullPipe/default-gitlab.pkgbuild.golden
+++ b/internal/pipe/aur/testdata/TestFullPipe/default-gitlab.pkgbuild.golden
@@ -10,7 +10,7 @@ license=('MIT')
 provides=('default-gitlab')
 conflicts=('default-gitlab')
 
-source_x86_64=('https://dummyhost/download/v1.0.1/bin.tar.gz')
+source_x86_64=('https://dummyhost/download/v1.0.1-foo/bin.tar.gz')
 sha256sums_x86_64=('e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855')
 
 package() {
diff --git a/internal/pipe/aur/testdata/TestFullPipe/default-gitlab.srcinfo.golden b/internal/pipe/aur/testdata/TestFullPipe/default-gitlab.srcinfo.golden
index 5dfd2637..311becea 100644
--- a/internal/pipe/aur/testdata/TestFullPipe/default-gitlab.srcinfo.golden
+++ b/internal/pipe/aur/testdata/TestFullPipe/default-gitlab.srcinfo.golden
@@ -7,7 +7,7 @@ pkgbase = default-gitlab-bin
 	conflicts = default-gitlab
 	provides = default-gitlab
 	arch = x86_64
-	source_x86_64 = https://dummyhost/download/v1.0.1/bin.tar.gz
+	source_x86_64 = https://dummyhost/download/v1.0.1-foo/bin.tar.gz
 	sha256sums_x86_64 = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
 	
 pkgname = default-gitlab-bin
diff --git a/internal/pipe/aur/testdata/TestFullPipe/default.pkgbuild.golden b/internal/pipe/aur/testdata/TestFullPipe/default.pkgbuild.golden
index 0d99bb19..ead70e19 100644
--- a/internal/pipe/aur/testdata/TestFullPipe/default.pkgbuild.golden
+++ b/internal/pipe/aur/testdata/TestFullPipe/default.pkgbuild.golden
@@ -10,7 +10,7 @@ license=('MIT')
 provides=('default')
 conflicts=('default')
 
-source_x86_64=('https://dummyhost/download/v1.0.1/bin.tar.gz')
+source_x86_64=('https://dummyhost/download/v1.0.1-foo/bin.tar.gz')
 sha256sums_x86_64=('e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855')
 
 package() {
diff --git a/internal/pipe/aur/testdata/TestFullPipe/default.srcinfo.golden b/internal/pipe/aur/testdata/TestFullPipe/default.srcinfo.golden
index f75f1dc8..7bd5861e 100644
--- a/internal/pipe/aur/testdata/TestFullPipe/default.srcinfo.golden
+++ b/internal/pipe/aur/testdata/TestFullPipe/default.srcinfo.golden
@@ -7,7 +7,7 @@ pkgbase = default-bin
 	conflicts = default
 	provides = default
 	arch = x86_64
-	source_x86_64 = https://dummyhost/download/v1.0.1/bin.tar.gz
+	source_x86_64 = https://dummyhost/download/v1.0.1-foo/bin.tar.gz
 	sha256sums_x86_64 = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
 	
 pkgname = default-bin
diff --git a/internal/pipe/aur/testdata/TestFullPipe/with-more-opts.pkgbuild.golden b/internal/pipe/aur/testdata/TestFullPipe/with-more-opts.pkgbuild.golden
index d4ef3315..c7a3348e 100644
--- a/internal/pipe/aur/testdata/TestFullPipe/with-more-opts.pkgbuild.golden
+++ b/internal/pipe/aur/testdata/TestFullPipe/with-more-opts.pkgbuild.golden
@@ -14,7 +14,7 @@ conflicts=('libcurl' 'cvs' 'blah')
 depends=('curl' 'bash')
 optdepends=('wget: stuff' 'foo: bar')
 
-source_x86_64=('https://dummyhost/download/v1.0.1/bin.tar.gz')
+source_x86_64=('https://dummyhost/download/v1.0.1-foo/bin.tar.gz')
 sha256sums_x86_64=('e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855')
 
 package() {
diff --git a/internal/pipe/aur/testdata/TestFullPipe/with-more-opts.srcinfo.golden b/internal/pipe/aur/testdata/TestFullPipe/with-more-opts.srcinfo.golden
index f946585d..ea1151a5 100644
--- a/internal/pipe/aur/testdata/TestFullPipe/with-more-opts.srcinfo.golden
+++ b/internal/pipe/aur/testdata/TestFullPipe/with-more-opts.srcinfo.golden
@@ -14,7 +14,7 @@ pkgbase = with-more-opts-bin
 	provides = git
 	provides = svn
 	arch = x86_64
-	source_x86_64 = https://dummyhost/download/v1.0.1/bin.tar.gz
+	source_x86_64 = https://dummyhost/download/v1.0.1-foo/bin.tar.gz
 	sha256sums_x86_64 = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
 	
 pkgname = with-more-opts-bin
diff --git a/internal/pipe/metadata/metadata_test.go b/internal/pipe/metadata/metadata_test.go
new file mode 100644
index 00000000..a9c49337
--- /dev/null
+++ b/internal/pipe/metadata/metadata_test.go
@@ -0,0 +1,66 @@
+package metadata
+
+import (
+	"os"
+	"path/filepath"
+	"testing"
+	"time"
+
+	"github.com/goreleaser/goreleaser/internal/artifact"
+	"github.com/goreleaser/goreleaser/internal/golden"
+	"github.com/goreleaser/goreleaser/pkg/config"
+	"github.com/goreleaser/goreleaser/pkg/context"
+	"github.com/stretchr/testify/require"
+)
+
+func TestRunWithError(t *testing.T) {
+	ctx := context.New(config.Project{
+		Dist:        "testadata/nope",
+		ProjectName: "foo",
+	})
+	require.EqualError(t, Pipe{}.Run(ctx), `open testadata/nope/artifacts.json: no such file or directory`)
+}
+
+func TestRun(t *testing.T) {
+	tmp := t.TempDir()
+	ctx := context.New(config.Project{
+		Dist:        tmp,
+		ProjectName: "name",
+	})
+	ctx.Version = "1.2.3"
+	ctx.Git = context.GitInfo{
+		CurrentTag:  "v1.2.3",
+		PreviousTag: "v1.2.2",
+		Commit:      "aef34a",
+	}
+	ctx.Date = time.Date(2022, 0o1, 22, 10, 12, 13, 0, time.UTC)
+	ctx.Artifacts.Add(&artifact.Artifact{
+		Name:   "foo",
+		Path:   "foo.txt",
+		Type:   artifact.Binary,
+		Goos:   "darwin",
+		Goarch: "amd64",
+		Goarm:  "7",
+		Extra: map[string]interface{}{
+			"foo": "bar",
+		},
+	})
+
+	require.NoError(t, Pipe{}.Run(ctx))
+	t.Run("artifacts", func(t *testing.T) {
+		requireEqualJSONFile(t, tmp, "artifacts.json")
+	})
+	t.Run("metadata", func(t *testing.T) {
+		requireEqualJSONFile(t, tmp, "metadata.json")
+	})
+}
+
+func requireEqualJSONFile(tb testing.TB, tmp, s string) {
+	tb.Helper()
+	path := filepath.Join(tmp, s)
+	golden.RequireEqualJSON(tb, golden.RequireReadFile(tb, path))
+
+	info, err := os.Stat(path)
+	require.NoError(tb, err)
+	require.Equal(tb, "-rw-r--r--", info.Mode().String())
+}
diff --git a/internal/pipe/artifacts/testdata/TestArtifacts.json.golden b/internal/pipe/metadata/testdata/TestRun/artifacts.json.golden
similarity index 100%
rename from internal/pipe/artifacts/testdata/TestArtifacts.json.golden
rename to internal/pipe/metadata/testdata/TestRun/artifacts.json.golden
diff --git a/internal/pipe/metadata/testdata/TestRun/metadata.json.golden b/internal/pipe/metadata/testdata/TestRun/metadata.json.golden
new file mode 100644
index 00000000..b02aa05f
--- /dev/null
+++ b/internal/pipe/metadata/testdata/TestRun/metadata.json.golden
@@ -0,0 +1,1 @@
+{"project_name":"name","tag":"v1.2.3","previous_tag":"v1.2.2","version":"1.2.3","commit":"aef34a","date":"2022-01-22T10:12:13Z"}
\ No newline at end of file
diff --git a/pkg/config/config_array_test.go b/pkg/config/config_array_test.go
index b1057b99..59753d31 100644
--- a/pkg/config/config_array_test.go
+++ b/pkg/config/config_array_test.go
@@ -8,8 +8,8 @@ import (
 )
 
 type Unmarshaled struct {
-	Strings StringArray `yaml:",omitempty"`
-	Flags   FlagArray   `yaml:",omitempty"`
+	Strings StringArray `yaml:"strings,omitempty"`
+	Flags   FlagArray   `yaml:"flags,omitempty"`
 }
 
 type yamlUnmarshalTestCase struct {