Repository: goreleaser/goreleaser
Pull request #2236 (2021-05-21 03:49:32)

feat: allow to template signs[].signature 
closes  #2195

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/goreleaser/7wtuUM5ZArsh5N715DFufzsM9VRz](https://vercel.com/goreleaser/goreleaser/7wtuUM5ZArsh5N715DFufzsM9VRz)  
✅ Preview: *In Progress*


codecov[bot]: # [Codecov](https://codecov.io/gh/goreleaser/goreleaser/pull/2236?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser) Report
> Merging [#2236](https://codecov.io/gh/goreleaser/goreleaser/pull/2236?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser) (58c6195) into [sign](https://codecov.io/gh/goreleaser/goreleaser/commit/3b77bfe286192d67352d082f9eba492e690b8271?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser) (3b77bfe) will **decrease** coverage by `0.07%`.
> The diff coverage is `50.00%`.

[![Impacted file tree graph](https://codecov.io/gh/goreleaser/goreleaser/pull/2236/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/2236?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser)

```diff
@@            Coverage Diff             @@
##             sign    #2236      +/-   ##
==========================================
- Coverage   82.72%   82.64%   -0.08%     
==========================================
  Files          76       76              
  Lines        4186     4190       +4     
==========================================
  Hits         3463     3463              
- Misses        587      589       +2     
- Partials      136      138       +2     
```


| [Impacted Files](https://codecov.io/gh/goreleaser/goreleaser/pull/2236?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser) | Coverage Δ | |
|---|---|---|
| [internal/pipe/sign/sign.go](https://codecov.io/gh/goreleaser/goreleaser/pull/2236/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser#diff-aW50ZXJuYWwvcGlwZS9zaWduL3NpZ24uZ28=) | `94.11% <50.00%> (-3.85%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/goreleaser/goreleaser/pull/2236?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/2236?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goreleaser). Last update [3b77bfe...58c6195](https://codecov.io/gh/goreleaser/goreleaser/pull/2236?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/internal/pipe/sign/sign.go b/internal/pipe/sign/sign.go
index ff85e6a3..8867b2e7 100644
--- a/internal/pipe/sign/sign.go
+++ b/internal/pipe/sign/sign.go
@@ -116,13 +116,17 @@ func sign(ctx *context.Context, cfg config.Sign, artifacts []*artifact.Artifact)
 func signone(ctx *context.Context, cfg config.Sign, a *artifact.Artifact) (*artifact.Artifact, error) {
 	env := ctx.Env.Copy()
 	env["artifact"] = a.Path
-	env["signature"] = expand(cfg.Signature, env)
+
+	name, err := tmpl.New(ctx).WithEnv(env).Apply(expand(cfg.Signature, env))
+	if err != nil {
+		return nil, fmt.Errorf("sign failed: %s: invalid template: %w", a, err)
+	}
+	env["signature"] = name
 
 	// nolint:prealloc
 	var args []string
 	for _, a := range cfg.Args {
-		arg := expand(a, env)
-		arg, err := tmpl.New(ctx).WithEnv(env).Apply(arg)
+		arg, err := tmpl.New(ctx).WithEnv(env).Apply(expand(a, env))
 		if err != nil {
 			return nil, fmt.Errorf("sign failed: %s: invalid template: %w", a, err)
 		}
@@ -160,7 +164,10 @@ func signone(ctx *context.Context, cfg config.Sign, a *artifact.Artifact) (*arti
 	artifactPathBase, _ := filepath.Split(a.Path)
 
 	env["artifact"] = a.Name
-	name := expand(cfg.Signature, env)
+	name, err = tmpl.New(ctx).WithEnv(env).Apply(expand(cfg.Signature, env))
+	if err != nil {
+		return nil, fmt.Errorf("sign failed: %s: invalid template: %w", a, err)
+	}
 
 	sigFilename := filepath.Base(env["signature"])
 	return &artifact.Artifact{
diff --git a/www/docs/customization/sign.md b/www/docs/customization/sign.md
index 40837b06..6dc594d6 100644
--- a/www/docs/customization/sign.md
+++ b/www/docs/customization/sign.md
@@ -33,7 +33,7 @@ signs:
     # Defaults to "default".
     id: foo
 
-    # name of the signature file.
+    # name/template of the signature file.
     # '${artifact}' is the path to the artifact that should be signed.
     #
     # defaults to `${artifact}.sig`


Test patch:
diff --git a/internal/pipe/sign/sign_test.go b/internal/pipe/sign/sign_test.go
index ce674bd9..69b35399 100644
--- a/internal/pipe/sign/sign_test.go
+++ b/internal/pipe/sign/sign_test.go
@@ -26,6 +26,7 @@ var (
 const (
 	user         = "nopass"
 	passwordUser = "password"
+	fakeGPGKeyID = "23E7505E"
 )
 
 func TestMain(m *testing.M) {
@@ -199,6 +200,9 @@ func TestSignArtifacts(t *testing.T) {
 			desc: "multiple sign configs",
 			ctx: context.New(
 				config.Project{
+					Env: []string{
+						"GPG_KEY_ID=" + fakeGPGKeyID,
+					},
 					Signs: []config.Sign{
 						{
 							ID:        "s1",
@@ -206,23 +210,23 @@ func TestSignArtifacts(t *testing.T) {
 						},
 						{
 							ID:        "s2",
-							Artifacts: "checksum",
-							Signature: "${artifact}.sog",
+							Artifacts: "archive",
+							Signature: "${artifact}.{{ .Env.GPG_KEY_ID }}.sig",
 						},
 					},
 				},
 			),
 			signaturePaths: []string{
+				"artifact1." + fakeGPGKeyID + ".sig",
+				"artifact2." + fakeGPGKeyID + ".sig",
 				"checksum.sig",
 				"checksum2.sig",
-				"checksum.sog",
-				"checksum2.sog",
 			},
 			signatureNames: []string{
+				"artifact1." + fakeGPGKeyID + ".sig",
+				"artifact2." + fakeGPGKeyID + ".sig",
 				"checksum.sig",
 				"checksum2.sig",
-				"checksum.sog",
-				"checksum2.sog",
 			},
 		},
 		{
@@ -560,12 +564,13 @@ func testSign(tb testing.TB, ctx *context.Context, signaturePaths []string, sign
 
 func verifySignature(tb testing.TB, ctx *context.Context, sig string, user string) {
 	tb.Helper()
-	artifact := strings.Replace(sig, filepath.Ext(sig), "", 1)
+	artifact := strings.TrimSuffix(sig, filepath.Ext(sig))
+	artifact = strings.TrimSuffix(artifact, "."+fakeGPGKeyID)
 
 	// verify signature was made with key for usesr 'nopass'
 	cmd := exec.Command("gpg", "--homedir", keyring, "--verify", filepath.Join(ctx.Config.Dist, sig), filepath.Join(ctx.Config.Dist, artifact))
 	out, err := cmd.CombinedOutput()
-	require.NoError(tb, err)
+	require.NoError(tb, err, string(out))
 
 	// check if the signature matches the user we expect to do this properly we
 	// might need to have either separate keyrings or export the key from the
diff --git a/internal/pipe/sign/testdata/README.md b/internal/pipe/sign/testdata/README.md
index 362fec5b..1d295d95 100644
--- a/internal/pipe/sign/testdata/README.md
+++ b/internal/pipe/sign/testdata/README.md
@@ -8,73 +8,84 @@ key works.
 This uses the `--homedir .` option to create the test keys so that we do not touch
 the local keyring file.
 
-1.  Create signing keys
+## 1.  Create signing keys
 
-    cd $GOPATH/src/github.com/goreleaser/goreleaser/internal/pipeline/sign/testdata/gnupg
-    gpg --homedir . --quick-generate-key --batch --passphrase '' nopass default default 10y
+```sh
+cd $GOPATH/src/github.com/goreleaser/goreleaser/internal/pipeline/sign/testdata/gnupg
+gpg --homedir . --quick-generate-key --batch --passphrase '' nopass default default 10y
+```
 
-1.  Check that the key exists
+## 2. Check that the key exists
 
-    ## $ gpg --homedir . --list-keys
+```sh
+gpg --homedir . --list-keys
+pub rsa2048 2017-12-13 [SC][expires: 2027-12-11]
+FB6BEDFCECE1761EDD68BF32EF2D274B0EDAAE12
+uid [ultimate] nopass
+sub rsa2048 2017-12-13 [E]
+```
 
-    pub rsa2048 2017-12-13 [SC][expires: 2027-12-11]
-    FB6BEDFCECE1761EDD68BF32EF2D274B0EDAAE12
-    uid [ultimate] nopass
-    sub rsa2048 2017-12-13 [E]
+## 3. Check that signing works
 
-1)  Check that signing works
+### 3.1 create a test file
 
-    # create a test file
+```sh
+echo "bar" > foo
+```
 
-    echo "bar" > foo
+### 3.2. sign and verfiy
 
-    # sign and verfiy
+```sh
+gpg --homedir . --detach-sign foo
+gpg --homedir . --verify foo.sig foo
 
-    gpg --homedir . --detach-sign foo
-    gpg --homedir . --verify foo.sig foo
+gpg: Signature made Wed Dec 13 22:02:49 2017 CET
+gpg: using RSA key FB6BEDFCECE1761EDD68BF32EF2D274B0EDAAE12
+gpg: Good signature from "nopass" [ultimate]
+```
 
-    gpg: Signature made Wed Dec 13 22:02:49 2017 CET
-    gpg: using RSA key FB6BEDFCECE1761EDD68BF32EF2D274B0EDAAE12
-    gpg: Good signature from "nopass" [ultimate]
+### 3.3. cleanup
 
-    # cleanup
+```sh
+rm foo foo.sig
+```
 
-    rm foo foo.sig
+## 4. Make sure you have keyrings for both gpg1 and gpg2
 
-1)  Make sure you have keyrings for both gpg1 and gpg2
+travis-ci.org runs on an old Ubuntu installation which
+has gpg 1.4 installed. We need to provide keyrings that
+have the same keys and users for both formats.
 
-    travis-ci.org runs on an old Ubuntu installation which
-    has gpg 1.4 installed. We need to provide keyrings that
-    have the same keys and users for both formats.
+This demonstrates the conversion from gpg2 to gpg1
+format but should work the same the other way around.
 
-    This demonstrates the conversion from gpg2 to gpg1
-    format but should work the same the other way around.
+### 4.1. get gpg version
 
-    # get gpg version
+```sh
+gpg --version
+gpg (GnuPG) 2.2.3
+```
 
-    gpg --version
-    gpg (GnuPG) 2.2.3
-    ...
+### 4.2. install gpg1
 
-    # install gpg1
+```sh
+brew install gpg1
+# brew install gpg2 # if you have gpg1 installed
+```
 
-    brew install gpg1
+### 4.3. migrate the keys from gpg2 to gpg1
 
-    # brew install gpg2 # if you have gpg1 installed
+```sh
+gpg --homedir . --export nopass | gpg1 --homedir . --import
+gpg --homedir . --export-secret-key nopass | gpg1 --homedir . --import
+```
 
-    # migrate the keys from gpg2 to gpg1
+### 4.4. check keys are the same
 
-    gpg --homedir . --export nopass | gpg1 --homedir . --import
-    gpg --homedir . --export-secret-key nopass | gpg1 --homedir . --import
+```sh
+gpg --homedir . --list-keys --keyid-format LONG
+gpg1 --homedir . --list-keys --keyid-format LONG
 
-    # check keys are the same
-
-    gpg --homedir . --list-keys --keyid-format LONG
-    gpg1 --homedir . --list-keys --keyid-format LONG
-
-    gpg --homedir . --list-secret-keys --keyid-format LONG
-    gpg1 --homedir . --list-secret-keys --keyid-format LONG
-
-    ```
-
-    ```
+gpg --homedir . --list-secret-keys --keyid-format LONG
+gpg1 --homedir . --list-secret-keys --keyid-format LONG
+```