github.phpd.cn/goreleaser/goreleaser@v0.92.0/internal/pipe/sign/sign_test.go (about) 1 package sign 2 3 import ( 4 "bytes" 5 "io/ioutil" 6 "os" 7 "os/exec" 8 "path/filepath" 9 "sort" 10 "testing" 11 12 "github.com/goreleaser/goreleaser/internal/artifact" 13 "github.com/goreleaser/goreleaser/pkg/config" 14 "github.com/goreleaser/goreleaser/pkg/context" 15 "github.com/stretchr/testify/assert" 16 ) 17 18 func TestDescription(t *testing.T) { 19 assert.NotEmpty(t, Pipe{}.String()) 20 } 21 22 func TestSignDefault(t *testing.T) { 23 ctx := &context.Context{} 24 Pipe{}.Default(ctx) 25 assert.Equal(t, ctx.Config.Sign.Cmd, "gpg") 26 assert.Equal(t, ctx.Config.Sign.Signature, "${artifact}.sig") 27 assert.Equal(t, ctx.Config.Sign.Args, []string{"--output", "$signature", "--detach-sig", "$artifact"}) 28 assert.Equal(t, ctx.Config.Sign.Artifacts, "none") 29 } 30 31 func TestSignDisabled(t *testing.T) { 32 ctx := &context.Context{} 33 ctx.Config.Sign.Artifacts = "none" 34 err := Pipe{}.Run(ctx) 35 assert.EqualError(t, err, "artifact signing is disabled") 36 } 37 38 func TestSignSkipped(t *testing.T) { 39 ctx := &context.Context{} 40 ctx.SkipSign = true 41 err := Pipe{}.Run(ctx) 42 assert.EqualError(t, err, "artifact signing is disabled") 43 } 44 45 func TestSignInvalidArtifacts(t *testing.T) { 46 ctx := &context.Context{} 47 ctx.Config.Sign.Artifacts = "foo" 48 err := Pipe{}.Run(ctx) 49 assert.EqualError(t, err, "invalid list of artifacts to sign: foo") 50 } 51 52 func TestSignArtifacts(t *testing.T) { 53 // fix permission on keyring dir to suppress warning about insecure permissions 54 assert.NoError(t, os.Chmod(keyring, 0700)) 55 56 tests := []struct { 57 desc string 58 ctx *context.Context 59 signatures []string 60 }{ 61 { 62 desc: "sign all artifacts", 63 ctx: context.New( 64 config.Project{ 65 Sign: config.Sign{Artifacts: "all"}, 66 }, 67 ), 68 signatures: []string{"artifact1.sig", "artifact2.sig", "checksum.sig"}, 69 }, 70 { 71 desc: "sign only checksums", 72 ctx: context.New( 73 config.Project{ 74 Sign: config.Sign{Artifacts: "checksum"}, 75 }, 76 ), 77 signatures: []string{"checksum.sig"}, 78 }, 79 } 80 81 for _, tt := range tests { 82 t.Run(tt.desc, func(t *testing.T) { 83 testSign(t, tt.ctx, tt.signatures) 84 }) 85 } 86 } 87 88 const keyring = "testdata/gnupg" 89 const user = "nopass" 90 91 func testSign(t *testing.T, ctx *context.Context, signatures []string) { 92 // create temp dir for file and signature 93 tmpdir, err := ioutil.TempDir("", "goreleaser") 94 assert.NoError(t, err) 95 defer os.RemoveAll(tmpdir) 96 97 ctx.Config.Dist = tmpdir 98 99 // create some fake artifacts 100 var artifacts = []string{"artifact1", "artifact2", "checksum"} 101 for _, f := range artifacts { 102 file := filepath.Join(tmpdir, f) 103 assert.NoError(t, ioutil.WriteFile(file, []byte("foo"), 0644)) 104 } 105 ctx.Artifacts.Add(artifact.Artifact{ 106 Name: "artifact1", 107 Path: filepath.Join(tmpdir, "artifact1"), 108 Type: artifact.UploadableArchive, 109 }) 110 ctx.Artifacts.Add(artifact.Artifact{ 111 Name: "artifact2", 112 Path: filepath.Join(tmpdir, "artifact2"), 113 Type: artifact.UploadableArchive, 114 }) 115 ctx.Artifacts.Add(artifact.Artifact{ 116 Name: "checksum", 117 Path: filepath.Join(tmpdir, "checksum"), 118 Type: artifact.Checksum, 119 }) 120 121 // configure the pipeline 122 // make sure we are using the test keyring 123 assert.NoError(t, Pipe{}.Default(ctx)) 124 ctx.Config.Sign.Args = append([]string{"--homedir", keyring}, ctx.Config.Sign.Args...) 125 126 // run the pipeline 127 assert.NoError(t, Pipe{}.Run(ctx)) 128 129 // verify that only the artifacts and the signatures are in the dist dir 130 files, err := ioutil.ReadDir(tmpdir) 131 assert.NoError(t, err) 132 gotFiles := []string{} 133 for _, f := range files { 134 gotFiles = append(gotFiles, f.Name()) 135 } 136 wantFiles := append(artifacts, signatures...) 137 sort.Strings(wantFiles) 138 assert.Equal(t, wantFiles, gotFiles) 139 140 // verify the signatures 141 for _, sig := range signatures { 142 verifySignature(t, ctx, sig) 143 } 144 145 var signArtifacts []string 146 for _, sig := range ctx.Artifacts.Filter(artifact.ByType(artifact.Signature)).List() { 147 signArtifacts = append(signArtifacts, sig.Name) 148 } 149 // check signature is an artifact 150 assert.Equal(t, signArtifacts, signatures) 151 } 152 153 func verifySignature(t *testing.T, ctx *context.Context, sig string) { 154 artifact := sig[:len(sig)-len(".sig")] 155 156 // verify signature was made with key for usesr 'nopass' 157 cmd := exec.Command("gpg", "--homedir", keyring, "--verify", filepath.Join(ctx.Config.Dist, sig), filepath.Join(ctx.Config.Dist, artifact)) 158 out, err := cmd.CombinedOutput() 159 assert.NoError(t, err) 160 161 // check if the signature matches the user we expect to do this properly we 162 // might need to have either separate keyrings or export the key from the 163 // keyring before we do the verification. For now we punt and look in the 164 // output. 165 if !bytes.Contains(out, []byte(user)) { 166 t.Fatalf("signature is not from %s", user) 167 } 168 }