github.com/szyn/goreleaser@v0.76.1-0.20180517112710-333da09a1297/pipeline/sign/sign.go (about) 1 package sign 2 3 import ( 4 "fmt" 5 "os" 6 "os/exec" 7 "path/filepath" 8 9 "github.com/goreleaser/goreleaser/context" 10 "github.com/goreleaser/goreleaser/internal/artifact" 11 "github.com/goreleaser/goreleaser/pipeline" 12 ) 13 14 // Pipe for artifact signing. 15 type Pipe struct{} 16 17 func (Pipe) String() string { 18 return "signing artifacts" 19 } 20 21 // Default sets the Pipes defaults. 22 func (Pipe) Default(ctx *context.Context) error { 23 cfg := &ctx.Config.Sign 24 if cfg.Cmd == "" { 25 cfg.Cmd = "gpg" 26 } 27 if cfg.Signature == "" { 28 cfg.Signature = "${artifact}.sig" 29 } 30 if len(cfg.Args) == 0 { 31 cfg.Args = []string{"--output", "$signature", "--detach-sig", "$artifact"} 32 } 33 if cfg.Artifacts == "" { 34 cfg.Artifacts = "none" 35 } 36 return nil 37 } 38 39 // Run executes the Pipe. 40 func (Pipe) Run(ctx *context.Context) error { 41 switch ctx.Config.Sign.Artifacts { 42 case "checksum": 43 return sign(ctx, ctx.Artifacts.Filter(artifact.ByType(artifact.Checksum)).List()) 44 case "all": 45 return sign(ctx, ctx.Artifacts.Filter( 46 artifact.Or( 47 artifact.ByType(artifact.UploadableArchive), 48 artifact.ByType(artifact.UploadableBinary), 49 artifact.ByType(artifact.Checksum), 50 artifact.ByType(artifact.LinuxPackage), 51 )).List()) 52 case "none": 53 return pipeline.Skip("artifact signing disabled") 54 default: 55 return fmt.Errorf("invalid list of artifacts to sign: %s", ctx.Config.Sign.Artifacts) 56 } 57 } 58 59 func sign(ctx *context.Context, artifacts []artifact.Artifact) error { 60 var sigs []string 61 for _, a := range artifacts { 62 sig, err := signone(ctx, a) 63 if err != nil { 64 return err 65 } 66 sigs = append(sigs, sig) 67 } 68 for _, sig := range sigs { 69 ctx.Artifacts.Add(artifact.Artifact{ 70 Type: artifact.Signature, 71 Name: sig, 72 Path: filepath.Join(ctx.Config.Dist, sig), 73 }) 74 } 75 return nil 76 } 77 78 func signone(ctx *context.Context, artifact artifact.Artifact) (string, error) { 79 cfg := ctx.Config.Sign 80 81 env := map[string]string{ 82 "artifact": artifact.Path, 83 } 84 env["signature"] = expand(cfg.Signature, env) 85 86 var args []string 87 for _, a := range cfg.Args { 88 args = append(args, expand(a, env)) 89 } 90 91 // The GoASTScanner flags this as a security risk. 92 // However, this works as intended. The nosec annotation 93 // tells the scanner to ignore this. 94 // #nosec 95 cmd := exec.CommandContext(ctx, cfg.Cmd, args...) 96 output, err := cmd.CombinedOutput() 97 if err != nil { 98 return "", fmt.Errorf("sign: %s failed with %q", cfg.Cmd, string(output)) 99 } 100 return filepath.Base(env["signature"]), nil 101 } 102 103 func expand(s string, env map[string]string) string { 104 return os.Expand(s, func(key string) string { 105 return env[key] 106 }) 107 }