github.phpd.cn/goreleaser/goreleaser@v0.92.0/internal/pipe/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/internal/artifact" 10 "github.com/goreleaser/goreleaser/internal/pipe" 11 "github.com/goreleaser/goreleaser/pkg/context" 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 if ctx.SkipSign { 42 return pipe.ErrSkipSignEnabled 43 } 44 45 switch ctx.Config.Sign.Artifacts { 46 case "checksum": 47 return sign(ctx, ctx.Artifacts.Filter(artifact.ByType(artifact.Checksum)).List()) 48 case "all": 49 return sign(ctx, ctx.Artifacts.Filter( 50 artifact.Or( 51 artifact.ByType(artifact.UploadableArchive), 52 artifact.ByType(artifact.UploadableBinary), 53 artifact.ByType(artifact.Checksum), 54 artifact.ByType(artifact.LinuxPackage), 55 )).List()) 56 case "none": 57 return pipe.ErrSkipSignEnabled 58 default: 59 return fmt.Errorf("invalid list of artifacts to sign: %s", ctx.Config.Sign.Artifacts) 60 } 61 } 62 63 func sign(ctx *context.Context, artifacts []artifact.Artifact) error { 64 // nolint:prealloc 65 var sigs []string 66 for _, a := range artifacts { 67 sig, err := signone(ctx, a) 68 if err != nil { 69 return err 70 } 71 sigs = append(sigs, sig) 72 } 73 for _, sig := range sigs { 74 ctx.Artifacts.Add(artifact.Artifact{ 75 Type: artifact.Signature, 76 Name: sig, 77 Path: filepath.Join(ctx.Config.Dist, sig), 78 }) 79 } 80 return nil 81 } 82 83 func signone(ctx *context.Context, artifact artifact.Artifact) (string, error) { 84 cfg := ctx.Config.Sign 85 86 env := map[string]string{ 87 "artifact": artifact.Path, 88 } 89 env["signature"] = expand(cfg.Signature, env) 90 91 // nolint:prealloc 92 var args []string 93 for _, a := range cfg.Args { 94 args = append(args, expand(a, env)) 95 } 96 97 // The GoASTScanner flags this as a security risk. 98 // However, this works as intended. The nosec annotation 99 // tells the scanner to ignore this. 100 // #nosec 101 cmd := exec.CommandContext(ctx, cfg.Cmd, args...) 102 output, err := cmd.CombinedOutput() 103 if err != nil { 104 return "", fmt.Errorf("sign: %s failed with %q", cfg.Cmd, string(output)) 105 } 106 return filepath.Base(env["signature"]), nil 107 } 108 109 func expand(s string, env map[string]string) string { 110 return os.Expand(s, func(key string) string { 111 return env[key] 112 }) 113 }