Repository: goreleaser/nfpm
Pull request #282 (2021-01-14 17:56:17)

fix: allow using an env var in the signature.key_file field
I want to use the same config file for local builds that are not signed and pipeline builds that are signed so I need to be able to specify the key_file as an env var.

vercel[bot]: This pull request is being automatically deployed with Vercel ([learn more](https://vercel.link/github-learn-more)).  
To see the status of your deployment, click below or on the icon next to each commit.

🔍 Inspect: [https://vercel.com/goreleaser/nfpm/gesd2udgv](https://vercel.com/goreleaser/nfpm/gesd2udgv)  
✅ Preview: [https://nfpm-git-allow-keyfile-env-var.goreleaser.now.sh](https://nfpm-git-allow-keyfile-env-var.goreleaser.now.sh)


codecov[bot]: # [Codecov](https://codecov.io/gh/goreleaser/nfpm/pull/282?src=pr&el=h1) Report
> Merging [#282](https://codecov.io/gh/goreleaser/nfpm/pull/282?src=pr&el=desc) (8d9994e) into [master](https://codecov.io/gh/goreleaser/nfpm/commit/e16b06acc90a57fa89a59c0e1a077625d7ac07b7?el=desc) (e16b06a) will **increase** coverage by `0.08%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/goreleaser/nfpm/pull/282/graphs/tree.svg?width=650&height=150&src=pr&token=9QKGIxn7wg)](https://codecov.io/gh/goreleaser/nfpm/pull/282?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #282      +/-   ##
==========================================
+ Coverage   69.86%   69.94%   +0.08%     
==========================================
  Files           9        9              
  Lines        1085     1088       +3     
==========================================
+ Hits          758      761       +3     
  Misses        203      203              
  Partials      124      124              
```


| [Impacted Files](https://codecov.io/gh/goreleaser/nfpm/pull/282?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [nfpm.go](https://codecov.io/gh/goreleaser/nfpm/pull/282/diff?src=pr&el=tree#diff-bmZwbS5nbw==) | `85.71% <100.00%> (+0.45%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/goreleaser/nfpm/pull/282?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/goreleaser/nfpm/pull/282?src=pr&el=footer). Last update [e16b06a...a68a03d](https://codecov.io/gh/goreleaser/nfpm/pull/282?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/nfpm.go b/nfpm.go
index 312da36..77b51d3 100644
--- a/nfpm.go
+++ b/nfpm.go
@@ -64,32 +64,45 @@ func Parse(in io.Reader) (config Config, err error) {
 		return
 	}
 
-	config.Info.Release = os.ExpandEnv(config.Info.Release)
-	config.Info.Version = os.ExpandEnv(config.Info.Version)
+	config.expandEnvVars()
 
+	WithDefaults(&config.Info)
+
+	return config, config.Validate()
+}
+
+func (c *Config) expandEnvVars() {
+	// Version related fields
+	c.Info.Release = os.ExpandEnv(c.Info.Release)
+	c.Info.Version = os.ExpandEnv(c.Info.Version)
+	c.Info.Prerelease = os.ExpandEnv(c.Info.Prerelease)
+
+	// Package signing related fields
+	c.Info.Deb.Signature.KeyFile = os.ExpandEnv(c.Deb.Signature.KeyFile)
+	c.Info.RPM.Signature.KeyFile = os.ExpandEnv(c.RPM.Signature.KeyFile)
+	c.Info.APK.Signature.KeyFile = os.ExpandEnv(c.APK.Signature.KeyFile)
+
+	// Package signing passphrase
 	generalPassphrase := os.ExpandEnv("$NFPM_PASSPHRASE")
-	config.Deb.Signature.KeyPassphrase = generalPassphrase
-	config.RPM.Signature.KeyPassphrase = generalPassphrase
-	config.APK.Signature.KeyPassphrase = generalPassphrase
+	c.Info.Deb.Signature.KeyPassphrase = generalPassphrase
+	c.Info.RPM.Signature.KeyPassphrase = generalPassphrase
+	c.Info.APK.Signature.KeyPassphrase = generalPassphrase
+
 
 	debPassphrase := os.ExpandEnv("$NFPM_DEB_PASSPHRASE")
 	if debPassphrase != "" {
-		config.Deb.Signature.KeyPassphrase = debPassphrase
+		c.Info.Deb.Signature.KeyPassphrase = debPassphrase
 	}
 
 	rpmPassphrase := os.ExpandEnv("$NFPM_RPM_PASSPHRASE")
 	if rpmPassphrase != "" {
-		config.RPM.Signature.KeyPassphrase = rpmPassphrase
+		c.Info.RPM.Signature.KeyPassphrase = rpmPassphrase
 	}
 
 	apkPassphrase := os.ExpandEnv("$NFPM_APK_PASSPHRASE")
 	if apkPassphrase != "" {
-		config.APK.Signature.KeyPassphrase = apkPassphrase
+		c.Info.APK.Signature.KeyPassphrase = apkPassphrase
 	}
-
-	WithDefaults(&config.Info)
-
-	return config, config.Validate()
 }
 
 // ParseFile decodes YAML data from a file path into a configuration struct.
@@ -224,20 +237,22 @@ type RPM struct {
 	Signature   RPMSignature `yaml:"signature,omitempty"`
 }
 
-type RPMSignature struct {
+type PackageSignature struct {
 	// PGP secret key, can be ASCII-armored
 	KeyFile       string `yaml:"key_file,omitempty"`
 	KeyPassphrase string `yaml:"-"` // populated from environment variable
 }
 
+type RPMSignature struct {
+	PackageSignature    `yaml:",inline"`
+}
+
 type APK struct {
 	Signature APKSignature `yaml:"signature,omitempty"`
 }
 
 type APKSignature struct {
-	// RSA private key in PEM format
-	KeyFile       string `yaml:"key_file,omitempty"`
-	KeyPassphrase string `yaml:"-"` // populated from environment variable
+	PackageSignature    `yaml:",inline"`
 	// defaults to <maintainer email>.rsa.pub
 	KeyName string `yaml:"key_name,omitempty"`
 }
@@ -251,9 +266,7 @@ type Deb struct {
 }
 
 type DebSignature struct {
-	// PGP secret key, can be ASCII-armored
-	KeyFile       string `yaml:"key_file,omitempty"`
-	KeyPassphrase string `yaml:"-"` // populated from environment variable
+	PackageSignature    `yaml:",inline"`
 	// origin, maint or archive (defaults to origin)
 	Type string `yaml:"type,omitempty"`
 }
diff --git a/www/docs/configuration.md b/www/docs/configuration.md
index e28d000..6fe582d 100644
--- a/www/docs/configuration.md
+++ b/www/docs/configuration.md
@@ -16,6 +16,7 @@ arch: amd64
 platform: linux
 
 # Version. (required)
+# This will expand any env var you set in the field, eg version: v${SEMVER}
 version: v1.2.3
 
 # Version Epoch.
@@ -32,6 +33,7 @@ prerelease: beta1
 version_metadata: git
 
 # Version Release.
+# This will expand any env var you set in the field, eg release: ${VERSION_RELEASE}
 release: 1
 
 # Section.
@@ -197,6 +199,7 @@ rpm:
     # PGP secret key (can also be ASCII-armored), the passphrase is taken
     # from the environment variable $NFPM_RPM_PASSPHRASE with a fallback
     # to #NFPM_PASSPHRASE.
+    # This will expand any env var you set in the field, eg key_file: ${SIGNING_KEY_FILE}
     key_file: key.gpg
 
 # Custom configuration applied only to the Deb packager.
@@ -230,6 +233,7 @@ deb:
     # PGP secret key (can also be ASCII-armored). The passphrase is taken
     # from the environment variable $NFPM_DEB_PASSPHRASE with a fallback
     # to #NFPM_PASSPHRASE.
+    # This will expand any env var you set in the field, eg key_file: ${SIGNING_KEY_FILE}
     key_file: key.gpg
     # The type describes the signers role, possible values are "origin",
     # "maint" and "archive". If unset, the type defaults to "origin".
@@ -241,6 +245,7 @@ apk:
     # RSA private key in the PEM format. The passphrase is taken from
     # the environment variable $NFPM_APK_PASSPHRASE with a fallback
     # to #NFPM_PASSPHRASE.
+    # This will expand any env var you set in the field, eg key_file: ${SIGNING_KEY_FILE}
     key_file: key.gpg
     # The name of the signing key. When verifying a package, the signature
     # is matched to the public key store in /etc/apk/keys/<key_name>.rsa.pub.


Test patch:
diff --git a/nfpm_test.go b/nfpm_test.go
index 2d5676b..9c4eb10 100644
--- a/nfpm_test.go
+++ b/nfpm_test.go
@@ -153,9 +153,17 @@ func TestParseFile(t *testing.T) {
 	require.NoError(t, err)
 	_, err = nfpm.ParseFile("./testdata/doesnotexist.yaml")
 	require.Error(t, err)
-	config, err := nfpm.ParseFile("./testdata/versionenv.yaml")
+	os.Setenv("RPM_KEY_FILE", "my/rpm/key/file")
+	os.Setenv("TEST_RELEASE_ENV_VAR", "1234")
+	os.Setenv("TEST_PRERELEASE_ENV_VAR", "beta1")
+	config, err := nfpm.ParseFile("./testdata/env-fields.yaml")
 	require.NoError(t, err)
 	require.Equal(t, fmt.Sprintf("v%s", os.Getenv("GOROOT")), config.Version)
+	require.Equal(t, "1234", config.Release)
+	require.Equal(t, "beta1", config.Prerelease)
+	require.Equal(t, "my/rpm/key/file", config.RPM.Signature.KeyFile)
+	require.Equal(t, "hard/coded/file", config.Deb.Signature.KeyFile)
+	require.Equal(t, "", config.APK.Signature.KeyFile)
 }
 
 func TestParseEnhancedFile(t *testing.T) {
diff --git a/testdata/versionenv.yaml b/testdata/env-fields.yaml
similarity index 64%
rename from testdata/versionenv.yaml
rename to testdata/env-fields.yaml
index 3ac954d..46ee6ed 100644
--- a/testdata/versionenv.yaml
+++ b/testdata/env-fields.yaml
@@ -2,6 +2,8 @@
 name: "foo"
 arch: "amd64"
 version: "v$GOROOT"
+release: ${TEST_RELEASE_ENV_VAR}
+prerelease: ${TEST_PRERELEASE_ENV_VAR}
 contents:
 - src: ./testdata/whatever.conf
   dst: /etc/foo/regular.conf
@@ -14,6 +16,15 @@ contents:
   dst: /rpm/path
   type: config
   packager: rpm
+rpm:
+  signature:
+    key_file: ${RPM_KEY_FILE}
+deb:
+  signature:
+    key_file: hard/coded/file
+apk:
+  signature:
+    key_file: ${NO_ENV_VAR_SET_SO_SHOULD_BE_EMPTY}
 overrides:
   deb:
     depends: