github.com/windmeup/goreleaser@v1.21.95/internal/pipe/before/before.go (about) 1 // Package before provides the pipe implementation that runs before all other pipes. 2 package before 3 4 import ( 5 "bytes" 6 "fmt" 7 "io" 8 "os/exec" 9 10 "github.com/caarlos0/go-shellwords" 11 "github.com/caarlos0/log" 12 "github.com/windmeup/goreleaser/internal/gio" 13 "github.com/windmeup/goreleaser/internal/logext" 14 "github.com/windmeup/goreleaser/internal/skips" 15 "github.com/windmeup/goreleaser/internal/tmpl" 16 "github.com/windmeup/goreleaser/pkg/context" 17 ) 18 19 // Pipe is a global hook pipe. 20 type Pipe struct{} 21 22 func (Pipe) String() string { return "running before hooks" } 23 24 func (Pipe) Skip(ctx *context.Context) bool { 25 return len(ctx.Config.Before.Hooks) == 0 || skips.Any(ctx, skips.Before) 26 } 27 28 // Run executes the hooks. 29 func (Pipe) Run(ctx *context.Context) error { 30 tmpl := tmpl.New(ctx) 31 /* #nosec */ 32 for _, step := range ctx.Config.Before.Hooks { 33 s, err := tmpl.Apply(step) 34 if err != nil { 35 return err 36 } 37 args, err := shellwords.Parse(s) 38 if err != nil { 39 return err 40 } 41 42 cmd := exec.Command(args[0], args[1:]...) 43 cmd.Env = ctx.Env.Strings() 44 45 var b bytes.Buffer 46 w := gio.Safe(&b) 47 cmd.Stderr = io.MultiWriter(logext.NewWriter(), w) 48 cmd.Stdout = io.MultiWriter(logext.NewWriter(), w) 49 50 log.WithField("hook", step).Info("running") 51 if err := cmd.Run(); err != nil { 52 return fmt.Errorf("hook failed: %s: %w; output: %s", step, err, b.String()) 53 } 54 } 55 return nil 56 }