Repository: goreleaser/nfpm (go)

Issue:
Mismatch in rpm package produced by nfpm and it's corresponding ConventionalFileName
### What happened?

Not sure if this should filed in nFPM instead of here, please let me know if it should be filed in nFPM issue tracker.

We use goreleaser to package our binary to deb and rpm packages, and finally these gets pushed to a packagecloud repository.

We don't have an explicit release value specified in the goreleaser [config](https://github.com/TykTechnologies/tyk/blob/e3e2abb8f8a241b39797857e1c25980f35e52cc5/ci/goreleaser/goreleaser.yml#L152C3-L152C3).
So the produced rpm package has the [default release value](https://github.com/goreleaser/nfpm/blob/b50fc3af8cd0ed1efc15ccaf6da9876b75103f12/rpm/rpm.go#L239) set(`1`)

But the [ConventionalFileName](https://github.com/goreleaser/nfpm/blob/b50fc3af8cd0ed1efc15ccaf6da9876b75103f12/rpm/rpm.go#L89) doesn't have this default release value included( gets named as `name-version.architecture.rpm`) instead of [name-version-release.architecture.rpm](http://ftp.rpm.org/max-rpm/ch-rpm-file-format.html) )

For us, when this package gets uploaded to packagecloud repository, the package gets named based on the rpm file naming [convention](http://ftp.rpm.org/max-rpm/ch-rpm-file-format.html) according to the rpm metadata, and the package gets named with the release value appended to the version(`name-version-1.architecture.rpm`)

So for any re-run of the same gorelaser run, if we have to remove an already uploaded package based on the ConventionalFileName, it's not possible as the package name based on the package metadata and the actual ConventionalFileName given by nFPM are different. 

### How can we reproduce this?

Create any rpm package without providing an explicit Release value, and look at the produced ConventionalFileName and the produced rpm file metadata. The ConventionalFileName wouldn't have the default release value(`1') 

### goreleaser version

```bash
____       ____      _
 / ___| ___ |  _ \ ___| | ___  __ _ ___  ___ _ __
| |  _ / _ \| |_) / _ \ |/ _ \/ _` / __|/ _ \ '__|
| |_| | (_) |  _ <  __/ |  __/ (_| \__ \  __/ |
 \____|\___/|_| \_\___|_|\___|\__,_|___/\___|_|
goreleaser: Deliver Go Binaries as fast and easily as possible
https://goreleaser.com

GitVersion:    v1.20.0
GitCommit:     unknown
GitTreeState:  unknown
BuildDate:     unknown
BuiltBy:       unknown
GoVersion:     go1.20.3
Compiler:      gc
ModuleSum:     h1:wvAbDqQwMX3PWPYc4VIeaWQB2V5HOETvDlyfTrk7NgQ=
Platform:      linux/amd64
```


### GoReleaser Check

- [X] goreleaser check shows no errors

### Search

- [X] I did search for other open and closed issues before opening this

### Supporter

- [x] I am a [sponsor](https://github.com/sponsors/caarlos0/) or a [Pro](https://goreleaser.com/pro) customer

### Code of Conduct

- [X] I agree to follow this project's Code of Conduct

### Additional context

_No response_

Pull request:
fix(rpm): conventional file name should always have the release
closes #700 

Patch:
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 3880ea6..5e4ebaf 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -43,7 +43,7 @@ jobs:
         os: [ubuntu-latest, macos-latest]
     runs-on: ${{ matrix.os }}
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - uses: actions/setup-go@v4
         with:
           go-version: stable
@@ -70,15 +70,15 @@ jobs:
       DOCKER_CLI_EXPERIMENTAL: "enabled"
       NO_TEST_PPC64LE: "true"
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - uses: actions/setup-go@v4
         with:
           go-version: stable
       - uses: arduino/setup-task@v1
         with:
           repo-token: ${{ secrets.GITHUB_TOKEN }}
-      - uses: docker/setup-qemu-action@v2
-      - uses: docker/setup-buildx-action@v2
+      - uses: docker/setup-qemu-action@v3
+      - uses: docker/setup-buildx-action@v3
       - run: task setup
       - name: setup-tparse
         run: go install github.com/mfridman/tparse@latest
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index f768824..e45c6bb 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -14,7 +14,7 @@ jobs:
       contents: read
 
     steps:
-    - uses: actions/checkout@v3
+    - uses: actions/checkout@v4
     - uses: github/codeql-action/init@v2
     - uses: github/codeql-action/autobuild@v2
     - uses: github/codeql-action/analyze@v2
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index f1d3801..f6bc909 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -15,7 +15,7 @@ jobs:
   htmltest:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - uses: arduino/setup-task@v1
         with:
           repo-token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/generate.yml b/.github/workflows/generate.yml
index db2e197..9bfce70 100644
--- a/.github/workflows/generate.yml
+++ b/.github/workflows/generate.yml
@@ -16,7 +16,7 @@ jobs:
   docs:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - uses: actions/setup-go@v4
         with:
           go-version: stable
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index a158973..12da909 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -14,7 +14,7 @@ jobs:
     name: lint
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - uses: actions/setup-go@v4
         with:
           go-version: stable
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 743819e..0f50408 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -25,7 +25,7 @@ jobs:
     env:
       DOCKER_CLI_EXPERIMENTAL: "enabled"
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           fetch-depth: 0
       - uses: actions/setup-go@v4
@@ -34,24 +34,24 @@ jobs:
       - uses: arduino/setup-task@v1
         with:
           repo-token: ${{ secrets.GITHUB_TOKEN }}
-      - uses: sigstore/cosign-installer@v3.1.1
+      - uses: sigstore/cosign-installer@v3.1.2
       - uses: anchore/sbom-action/download-syft@v0.14.3
-      - uses: docker/setup-qemu-action@v2
-      - uses: docker/setup-buildx-action@v2
+      - uses: docker/setup-qemu-action@v3
+      - uses: docker/setup-buildx-action@v3
       - run: task setup
       - run: task build
-      - uses: docker/login-action@v2
+      - uses: docker/login-action@v3
         if: startsWith(github.ref, 'refs/tags/v')
         with:
           username: ${{ secrets.DOCKER_USERNAME }}
           password: ${{ secrets.DOCKER_PASSWORD }}
-      - uses: docker/login-action@v2
+      - uses: docker/login-action@v3
         if: startsWith(github.ref, 'refs/tags/v')
         with:
           registry: ghcr.io
           username: ${{ github.repository_owner }}
           password: ${{ secrets.GITHUB_TOKEN }}
-      - uses: goreleaser/goreleaser-action@v4
+      - uses: goreleaser/goreleaser-action@v5
         if: success()
         with:
           version: latest
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 3ba9807..4b281ba 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -25,7 +25,7 @@ jobs:
   test:
     runs-on: windows-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - uses: actions/setup-go@v4
         with:
           go-version: stable
@@ -41,7 +41,7 @@ jobs:
   build-pkgs:
     runs-on: windows-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - uses: actions/setup-go@v4
         with:
           go-version: stable
@@ -51,7 +51,7 @@ jobs:
       - shell: bash
         run: |
           echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
-      - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3
+      - uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3
         with:
           path: dist/
           key: ${{ env.sha_short }}
@@ -61,15 +61,15 @@ jobs:
     runs-on: ubuntu-latest
     needs: [build-pkgs]
     steps:
-      - uses: docker/setup-qemu-action@v2
-      - uses: actions/checkout@v3
+      - uses: docker/setup-qemu-action@v3
+      - uses: actions/checkout@v4
       - uses: arduino/setup-task@v1
         with:
           repo-token: ${{ secrets.GITHUB_TOKEN }}
       - shell: bash
         run: |
           echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
-      - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3
+      - uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3
         with:
           path: dist/
           key: ${{ env.sha_short }}
diff --git a/go.mod b/go.mod
index 258d333..d352da4 100644
--- a/go.mod
+++ b/go.mod
@@ -14,7 +14,7 @@ require (
 	github.com/google/rpmpack v0.5.0
 	github.com/goreleaser/chglog v0.5.0
 	github.com/goreleaser/fileglob v1.3.0
-	github.com/invopop/jsonschema v0.7.0
+	github.com/invopop/jsonschema v0.8.0
 	github.com/klauspost/compress v1.16.7
 	github.com/klauspost/pgzip v1.2.6
 	github.com/muesli/mango-cobra v1.2.0
diff --git a/go.sum b/go.sum
index d37daaf..a8a986a 100644
--- a/go.sum
+++ b/go.sum
@@ -82,8 +82,8 @@ github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
 github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
 github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
-github.com/invopop/jsonschema v0.7.0 h1:2vgQcBz1n256N+FpX3Jq7Y17AjYt46Ig3zIWyy770So=
-github.com/invopop/jsonschema v0.7.0/go.mod h1:O9uiLokuu0+MGFlyiaqtWxwqJm41/+8Nj0lD7A36YH0=
+github.com/invopop/jsonschema v0.8.0 h1:9Vblm5uNqURXUSaX0QUYcI/Hcu5rrvOz5MbpWgw0VkM=
+github.com/invopop/jsonschema v0.8.0/go.mod h1:O9uiLokuu0+MGFlyiaqtWxwqJm41/+8Nj0lD7A36YH0=
 github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
 github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
 github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
diff --git a/rpm/rpm.go b/rpm/rpm.go
index 97953bf..311dce9 100644
--- a/rpm/rpm.go
+++ b/rpm/rpm.go
@@ -69,13 +69,15 @@ var archToRPM = map[string]string{
 	// TODO: other arches
 }
 
-func ensureValidArch(info *nfpm.Info) *nfpm.Info {
+func setDefaults(info *nfpm.Info) *nfpm.Info {
 	if info.RPM.Arch != "" {
 		info.Arch = info.RPM.Arch
 	} else if arch, ok := archToRPM[info.Arch]; ok {
 		info.Arch = arch
 	}
 
+	info.Release = defaultTo(info.Release, "1")
+
 	return info
 }
 
@@ -83,15 +85,10 @@ func ensureValidArch(info *nfpm.Info) *nfpm.Info {
 // to the conventions for RPM packages. See:
 // http://ftp.rpm.org/max-rpm/ch-rpm-file-format.html
 func (*RPM) ConventionalFileName(info *nfpm.Info) string {
-	info = ensureValidArch(info)
-
-	version := formatVersion(info)
-	if info.Release != "" {
-		version += "-" + info.Release
-	}
+	info = setDefaults(info)
 
 	// name-version-release.architecture.rpm
-	return fmt.Sprintf("%s-%s.%s.rpm", info.Name, version, info.Arch)
+	return fmt.Sprintf("%s-%s.%s.rpm", info.Name, formatVersion(info), info.Arch)
 }
 
 // ConventionalExtension returns the file name conventionally used for RPM packages
@@ -105,7 +102,7 @@ func (*RPM) Package(info *nfpm.Info, w io.Writer) (err error) {
 		meta *rpmpack.RPMMetaData
 		rpm  *rpmpack.RPM
 	)
-	info = ensureValidArch(info)
+	info = setDefaults(info)
 
 	err = nfpm.PrepareForPackager(info, packagerName)
 	if err != nil {
@@ -269,7 +266,7 @@ func formatVersion(info *nfpm.Info) string {
 		version += "+" + info.VersionMetadata
 	}
 
-	return version
+	return version + "-" + info.Release
 }
 
 func defaultTo(in, def string) string {


Test patch:
diff --git a/rpm/rpm_test.go b/rpm/rpm_test.go
index 314da90..07ac2e0 100644
--- a/rpm/rpm_test.go
+++ b/rpm/rpm_test.go
@@ -22,7 +22,7 @@ import (
 )
 
 func exampleInfo() *nfpm.Info {
-	return nfpm.WithDefaults(&nfpm.Info{
+	return setDefaults(nfpm.WithDefaults(&nfpm.Info{
 		Name:        "foo",
 		Arch:        "amd64",
 		Description: "Foo does things",
@@ -85,7 +85,7 @@ func exampleInfo() *nfpm.Info {
 				},
 			},
 		},
-	})
+	}))
 }
 
 func TestConventionalExtension(t *testing.T) {
@@ -118,7 +118,7 @@ func TestRPM(t *testing.T) {
 
 	version, err := rpm.Header.GetString(rpmutils.VERSION)
 	require.NoError(t, err)
-	require.Equal(t, "1.0.0", version)
+	require.Equal(t, "1.0.0-1", version)
 
 	release, err := rpm.Header.GetString(rpmutils.RELEASE)
 	require.NoError(t, err)
@@ -298,7 +298,7 @@ func TestWithRPMTags(t *testing.T) {
 
 	version, err := rpm.Header.GetString(rpmutils.VERSION)
 	require.NoError(t, err)
-	require.Equal(t, "1.0.0", version)
+	require.Equal(t, "1.0.0-3", version)
 
 	release, err := rpm.Header.GetString(rpmutils.RELEASE)
 	require.NoError(t, err)
@@ -329,7 +329,7 @@ func TestRPMVersion(t *testing.T) {
 	info.Version = "1.0.0" //nolint:golint,goconst
 	meta, err := buildRPMMeta(info)
 	require.NoError(t, err)
-	require.Equal(t, "1.0.0", meta.Version)
+	require.Equal(t, "1.0.0-1", meta.Version)
 	require.Equal(t, "1", meta.Release)
 }
 
@@ -339,7 +339,7 @@ func TestRPMVersionWithRelease(t *testing.T) {
 	info.Release = "2"
 	meta, err := buildRPMMeta(info)
 	require.NoError(t, err)
-	require.Equal(t, "1.0.0", meta.Version)
+	require.Equal(t, "1.0.0-2", meta.Version)
 	require.Equal(t, "2", meta.Release)
 }
 
@@ -351,14 +351,14 @@ func TestRPMVersionWithPrerelease(t *testing.T) {
 	info.Prerelease = "rc1" // nolint:goconst
 	meta, err := buildRPMMeta(info)
 	require.NoError(t, err)
-	require.Equal(t, "1.0.0~rc1", meta.Version)
+	require.Equal(t, "1.0.0~rc1-1", meta.Version)
 	require.Equal(t, "1", meta.Release)
 
 	info.Version = "1.0.0~rc1"
 	info.Prerelease = ""
 	meta, err = buildRPMMeta(info)
 	require.NoError(t, err)
-	require.Equal(t, "1.0.0~rc1", meta.Version)
+	require.Equal(t, "1.0.0~rc1-1", meta.Version)
 	require.Equal(t, "1", meta.Release)
 }
 
@@ -367,20 +367,20 @@ func TestRPMVersionWithReleaseAndPrerelease(t *testing.T) {
 	info := exampleInfo()
 
 	info.Version = "1.0.0"
-	info.Release = "0.2"
+	info.Release = "2"
 	info.Prerelease = "rc1"
 	meta, err := buildRPMMeta(info)
 	require.NoError(t, err)
-	require.Equal(t, "1.0.0~rc1", meta.Version)
-	require.Equal(t, "0.2", meta.Release)
+	require.Equal(t, "1.0.0~rc1-2", meta.Version)
+	require.Equal(t, "2", meta.Release)
 
 	info.Version = "1.0.0~rc1"
-	info.Release = "0.2"
+	info.Release = "3"
 	info.Prerelease = ""
 	meta, err = buildRPMMeta(info)
 	require.NoError(t, err)
-	require.Equal(t, "1.0.0~rc1", meta.Version)
-	require.Equal(t, "0.2", meta.Release)
+	require.Equal(t, "1.0.0~rc1-3", meta.Version)
+	require.Equal(t, "3", meta.Release)
 }
 
 func TestRPMVersionWithVersionMetadata(t *testing.T) {
@@ -389,15 +389,16 @@ func TestRPMVersionWithVersionMetadata(t *testing.T) {
 
 	info.Version = "1.0.0+meta"
 	info.VersionMetadata = ""
-	meta, err := buildRPMMeta(nfpm.WithDefaults(info))
+	meta, err := buildRPMMeta(info)
 	require.NoError(t, err)
-	require.Equal(t, "1.0.0+meta", meta.Version)
+	require.Equal(t, "1.0.0+meta-1", meta.Version)
 
 	info.Version = "1.0.0"
 	info.VersionMetadata = "meta"
+	info.Release = "10"
 	meta, err = buildRPMMeta(nfpm.WithDefaults(info))
 	require.NoError(t, err)
-	require.Equal(t, "1.0.0+meta", meta.Version)
+	require.Equal(t, "1.0.0+meta-10", meta.Version)
 }
 
 func TestWithInvalidEpoch(t *testing.T) {
@@ -504,7 +505,7 @@ func TestArches(t *testing.T) {
 		t.Run(k, func(t *testing.T) {
 			info := exampleInfo()
 			info.Arch = k
-			info = ensureValidArch(info)
+			info = setDefaults(info)
 			require.Equal(t, archToRPM[k], info.Arch)
 		})
 	}
@@ -512,7 +513,7 @@ func TestArches(t *testing.T) {
 	t.Run("override", func(t *testing.T) {
 		info := exampleInfo()
 		info.RPM.Arch = "foo64"
-		info = ensureValidArch(info)
+		info = setDefaults(info)
 		require.Equal(t, "foo64", info.Arch)
 	})
 }
@@ -569,7 +570,7 @@ func TestRPMConventionalFileName(t *testing.T) {
 	}{
 		{
 			Version: "1.2.3", Release: "", Prerelease: "", Metadata: "",
-			Expected: fmt.Sprintf("%s-1.2.3.%s.rpm", info.Name, info.Arch),
+			Expected: fmt.Sprintf("%s-1.2.3-1.%s.rpm", info.Name, info.Arch),
 		},
 		{
 			Version: "1.2.3", Release: "4", Prerelease: "", Metadata: "",
@@ -581,7 +582,7 @@ func TestRPMConventionalFileName(t *testing.T) {
 		},
 		{
 			Version: "1.2.3", Release: "", Prerelease: "5", Metadata: "",
-			Expected: fmt.Sprintf("%s-1.2.3~5.%s.rpm", info.Name, info.Arch),
+			Expected: fmt.Sprintf("%s-1.2.3~5-1.%s.rpm", info.Name, info.Arch),
 		},
 		{
 			Version: "1.2.3", Release: "1", Prerelease: "5", Metadata: "git",
diff --git a/testdata/acceptance/rpm.dockerfile b/testdata/acceptance/rpm.dockerfile
index 5f517f7..0efaed5 100644
--- a/testdata/acceptance/rpm.dockerfile
+++ b/testdata/acceptance/rpm.dockerfile
@@ -123,16 +123,16 @@ RUN command -v zsh
 
 # ---- env-var-version test ----
 FROM min AS env-var-version
-ENV EXPECTVER="Version : 1.0.0~0.1.b1+git.abcdefgh" \
-	EXPECTREL="Release : 1"
+ENV EXPECTVER="Version : 1.0.0~0.1.b1+git.abcdefgh-1" \
+  EXPECTREL="Release : 1"
 RUN rpm -qpi /tmp/foo.rpm | sed -e 's/ \+/ /g' | grep "Version" > found.ver
 RUN rpm -qpi /tmp/foo.rpm | sed -e 's/ \+/ /g' | grep "Release" > found.rel
 RUN export FOUND_VER="$(cat found.ver)" && \
-	echo "Expected: ${EXPECTVER}' :: Found: '${FOUND_VER}'" && \
-	test "${FOUND_VER}" = "${EXPECTVER}"
+  echo "Expected: ${EXPECTVER}' :: Found: '${FOUND_VER}'" && \
+  test "${FOUND_VER}" = "${EXPECTVER}"
 RUN export FOUND_REL="$(cat found.rel)" && \
-	echo "Expected: '${EXPECTREL}' :: Found: '${FOUND_REL}'" && \
-	test "${FOUND_REL}" = "${EXPECTREL}"
+  echo "Expected: '${EXPECTREL}' :: Found: '${FOUND_REL}'" && \
+  test "${FOUND_REL}" = "${EXPECTREL}"
 
 
 # ---- changelog test ----