Repository: goreleaser/nfpm (go)

Issue:
Platform field variable expansion not happening
### What happened?

I was creating packages, using a template with some fields:

```
name: "nerdctld"
arch: "${GOARCH}"
platform: "${GOOS}"
version: "${VERSION}"
...
```

Everything looked fine, but it turns out the rpm was invalid:

```
package nerdctld-0:0.2.1-1.x86_64 is intended for a different operating system
```

rpm --xml shows why:
```xml
  <rpmTag name="Os">
	<string>${GOOS}</string>
  </rpmTag>
  <rpmTag name="Arch">
	<string>x86_64</string>
  </rpmTag>
```

The deb package is fine, seems like it doesn't even use platform ?

(it is supposed to go in the `Architecture` field for deb, like darwin-amd64, default is linux)

### How can we reproduce this?

Try to use environment variables for platform and arch...
See that they are only expanded for arch, not for platform.

### nfpm version

```bash
nfpm version nfpm version 2.23.0
```


### Search

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

### Code of Conduct

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

### Additional context

My workaround is to comment out the "platform", for now.

```
arch: "${GOARCH}"
#platform: "${GOOS}"
version: "${VERSION}"
```

Since the software I am packaging is linux-only, anyway...

But I can submit a test case and a patch, simple one-liner.

Pull request:
feat: expand variables in platform field
Surprising that GOARCH was expanded, but GOOS was not.
More consistent to expand both of them the same way ?

Implement platform for deb packager, goes into Architecture.    
Validate that the platform is "linux", for Alpine and Arch.

Closes #600 

Patch:
diff --git a/apk/apk.go b/apk/apk.go
index c280cfe..9fe97ec 100644
--- a/apk/apk.go
+++ b/apk/apk.go
@@ -108,6 +108,9 @@ func (*Apk) ConventionalExtension() string {
 
 // Package writes a new apk package to the given writer using the given info.
 func (*Apk) Package(info *nfpm.Info, apk io.Writer) (err error) {
+	if info.Platform != "linux" {
+		return fmt.Errorf("invalid platform: %s", info.Platform)
+	}
 	info = ensureValidArch(info)
 	if err = info.Validate(); err != nil {
 		return err
diff --git a/arch/arch.go b/arch/arch.go
index c24eae3..0f909fe 100644
--- a/arch/arch.go
+++ b/arch/arch.go
@@ -115,6 +115,10 @@ func isOneOf(r rune, rr ...rune) bool {
 
 // Package writes a new archlinux package to the given writer using the given info.
 func (ArchLinux) Package(info *nfpm.Info, w io.Writer) error {
+	if info.Platform != "linux" {
+		return fmt.Errorf("invalid platform: %s", info.Platform)
+	}
+	info = ensureValidArch(info)
 	if err := info.Validate(); err != nil {
 		return err
 	}
diff --git a/deb/deb.go b/deb/deb.go
index ad8f22d..8255ec8 100644
--- a/deb/deb.go
+++ b/deb/deb.go
@@ -779,7 +779,7 @@ Version: {{ if .Info.Epoch}}{{ .Info.Epoch }}:{{ end }}{{.Info.Version}}
          {{- if .Info.Release}}-{{ .Info.Release }}{{- end }}
 Section: {{.Info.Section}}
 Priority: {{.Info.Priority}}
-Architecture: {{.Info.Arch}}
+Architecture: {{ if ne .Info.Platform "linux"}}{{ .Info.Platform }}-{{ end }}{{.Info.Arch}}
 {{- /* Optional fields */ -}}
 {{- if .Info.Maintainer}}
 Maintainer: {{.Info.Maintainer}}
diff --git a/nfpm.go b/nfpm.go
index 30c0d4d..2331418 100644
--- a/nfpm.go
+++ b/nfpm.go
@@ -177,6 +177,7 @@ func (c *Config) expandEnvVars() {
 	c.Info.Release = os.Expand(c.Info.Release, c.envMappingFunc)
 	c.Info.Version = os.Expand(c.Info.Version, c.envMappingFunc)
 	c.Info.Prerelease = os.Expand(c.Info.Prerelease, c.envMappingFunc)
+	c.Info.Platform = os.Expand(c.Info.Platform, c.envMappingFunc)
 	c.Info.Arch = os.Expand(c.Info.Arch, c.envMappingFunc)
 	for or := range c.Overrides {
 		c.Overrides[or].Conflicts = c.expandEnvVarsStringSlice(c.Overrides[or].Conflicts)
diff --git a/www/docs/configuration.md b/www/docs/configuration.md
index 8324bfa..c521c65 100644
--- a/www/docs/configuration.md
+++ b/www/docs/configuration.md
@@ -18,7 +18,8 @@ name: foo
 arch: amd64
 
 # Platform.
-# This is only used by the rpm packager.
+# This will expand any env var you set in the field, e.g. version: ${GOOS}
+# This is only used by the rpm and deb packagers.
 # Examples: `linux` (default), `darwin`
 platform: linux
 


Test patch:
diff --git a/apk/apk_test.go b/apk/apk_test.go
index 1be84b5..b444e70 100644
--- a/apk/apk_test.go
+++ b/apk/apk_test.go
@@ -174,6 +174,15 @@ func TestDefaultWithArch(t *testing.T) {
 	}
 }
 
+func TestApkPlatform(t *testing.T) {
+	f, err := os.CreateTemp("", "test*.apk")
+	require.NoError(t, err)
+	info := exampleInfo()
+	info.Platform = "darwin"
+	err = Default.Package(info, f)
+	require.Error(t, err)
+}
+
 func TestNoInfo(t *testing.T) {
 	err := Default.Package(nfpm.WithDefaults(&nfpm.Info{}), io.Discard)
 	require.Error(t, err)
diff --git a/arch/arch_test.go b/arch/arch_test.go
index 85f371c..6ad6438 100644
--- a/arch/arch_test.go
+++ b/arch/arch_test.go
@@ -4,6 +4,7 @@ import (
 	"archive/tar"
 	"bytes"
 	"io"
+	"os"
 	"strings"
 	"testing"
 
@@ -99,6 +100,15 @@ func TestArch(t *testing.T) {
 	}
 }
 
+func TestArchPlatform(t *testing.T) {
+	f, err := os.CreateTemp("", "test*.pkg.tar.zstd")
+	require.NoError(t, err)
+	info := exampleInfo()
+	info.Platform = "darwin"
+	err = Default.Package(info, f)
+	require.Error(t, err)
+}
+
 func TestArchNoFiles(t *testing.T) {
 	info := exampleInfo()
 	info.Contents = nil
diff --git a/deb/deb_test.go b/deb/deb_test.go
index 4850280..a082dbd 100644
--- a/deb/deb_test.go
+++ b/deb/deb_test.go
@@ -107,6 +107,51 @@ func TestDeb(t *testing.T) {
 	}
 }
 
+func TestDebPlatform(t *testing.T) {
+	f, err := os.CreateTemp("", "test*.deb")
+	require.NoError(t, err)
+	info := exampleInfo()
+	info.Platform = "darwin"
+	err = Default.Package(info, f)
+	require.NoError(t, err)
+}
+
+func extractDebArchitecture(deb *bytes.Buffer) string {
+	for _, s := range strings.Split(deb.String(), "\n") {
+		if strings.Contains(s, "Architecture: ") {
+			return strings.TrimPrefix(s, "Architecture: ")
+		}
+	}
+	return ""
+}
+
+func splitDebArchitecture(deb *bytes.Buffer) (string, string) {
+	a := extractDebArchitecture(deb)
+	if strings.Contains(a, "-") {
+		f := strings.Split(a, "-")
+		return f[0], f[1]
+	}
+	return "linux", a
+}
+
+func TestDebOS(t *testing.T) {
+	info := exampleInfo()
+	var buf bytes.Buffer
+	err := writeControl(&buf, controlData{info, 0})
+	require.NoError(t, err)
+	o, _ := splitDebArchitecture(&buf)
+	require.Equal(t, "linux", o)
+}
+
+func TestDebArch(t *testing.T) {
+	info := exampleInfo()
+	var buf bytes.Buffer
+	err := writeControl(&buf, controlData{info, 0})
+	require.NoError(t, err)
+	_, a := splitDebArchitecture(&buf)
+	require.Equal(t, "amd64", a)
+}
+
 func extractDebVersion(deb *bytes.Buffer) string {
 	for _, s := range strings.Split(deb.String(), "\n") {
 		if strings.Contains(s, "Version: ") {
diff --git a/nfpm_test.go b/nfpm_test.go
index 68fce5c..18c31b0 100644
--- a/nfpm_test.go
+++ b/nfpm_test.go
@@ -244,6 +244,8 @@ func TestOptionsFromEnvironment(t *testing.T) {
 		debPass         = "password123"
 		rpmPass         = "secret"
 		apkPass         = "foobar"
+		platform        = "linux"
+		arch            = "amd64"
 		release         = "3"
 		version         = "1.0.0"
 		vendor          = "GoReleaser"
@@ -251,6 +253,20 @@ func TestOptionsFromEnvironment(t *testing.T) {
 		maintainerEmail = "nope@example.com"
 	)
 
+	t.Run("platform", func(t *testing.T) {
+		t.Setenv("OS", platform)
+		info, err := nfpm.Parse(strings.NewReader("name: foo\nplatform: $OS"))
+		require.NoError(t, err)
+		require.Equal(t, platform, info.Platform)
+	})
+
+	t.Run("arch", func(t *testing.T) {
+		t.Setenv("ARCH", arch)
+		info, err := nfpm.Parse(strings.NewReader("name: foo\narch: $ARCH"))
+		require.NoError(t, err)
+		require.Equal(t, arch, info.Arch)
+	})
+
 	t.Run("version", func(t *testing.T) {
 		os.Clearenv()
 		os.Setenv("VERSION", version)
diff --git a/rpm/rpm_test.go b/rpm/rpm_test.go
index 2176143..23f49dd 100644
--- a/rpm/rpm_test.go
+++ b/rpm/rpm_test.go
@@ -106,6 +106,14 @@ func TestRPM(t *testing.T) {
 	rpm, err := rpmutils.ReadRpm(file)
 	require.NoError(t, err)
 
+	os, err := rpm.Header.GetString(rpmutils.OS)
+	require.NoError(t, err)
+	require.Equal(t, "linux", os)
+
+	arch, err := rpm.Header.GetString(rpmutils.ARCH)
+	require.NoError(t, err)
+	require.Equal(t, archToRPM["amd64"], arch)
+
 	version, err := rpm.Header.GetString(rpmutils.VERSION)
 	require.NoError(t, err)
 	require.Equal(t, "1.0.0", version)
@@ -134,6 +142,14 @@ func TestRPM(t *testing.T) {
 	require.Equal(t, "Foo does things", description)
 }
 
+func TestRPMPlatform(t *testing.T) {
+	f, err := os.CreateTemp("", "test*.rpm")
+	require.NoError(t, err)
+	info := exampleInfo()
+	info.Platform = "darwin"
+	require.NoError(t, Default.Package(info, f))
+}
+
 func TestRPMGroup(t *testing.T) {
 	f, err := os.CreateTemp("", "test.rpm")
 	require.NoError(t, err)