github.com/ahmet2mir/goreleaser@v0.180.3-0.20210927151101-8e5ee5a9b8c5/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/apex/log" 11 "github.com/caarlos0/go-shellwords" 12 "github.com/goreleaser/goreleaser/internal/gio" 13 "github.com/goreleaser/goreleaser/internal/logext" 14 "github.com/goreleaser/goreleaser/internal/tmpl" 15 "github.com/goreleaser/goreleaser/pkg/context" 16 ) 17 18 // Pipe is a global hook pipe. 19 type Pipe struct{} 20 21 func (Pipe) String() string { return "running before hooks" } 22 func (Pipe) Skip(ctx *context.Context) bool { return len(ctx.Config.Before.Hooks) == 0 } 23 24 // Run executes the hooks. 25 func (Pipe) Run(ctx *context.Context) error { 26 tmpl := tmpl.New(ctx) 27 /* #nosec */ 28 for _, step := range ctx.Config.Before.Hooks { 29 s, err := tmpl.Apply(step) 30 if err != nil { 31 return err 32 } 33 args, err := shellwords.Parse(s) 34 if err != nil { 35 return err 36 } 37 38 cmd := exec.Command(args[0], args[1:]...) 39 cmd.Env = ctx.Env.Strings() 40 41 var b bytes.Buffer 42 w := gio.Safe(&b) 43 fields := log.Fields{"hook": step} 44 cmd.Stderr = io.MultiWriter(logext.NewWriter(fields, logext.Error), w) 45 cmd.Stdout = io.MultiWriter(logext.NewWriter(fields, logext.Info), w) 46 47 log.WithFields(fields).Info("running") 48 if err := cmd.Run(); err != nil { 49 return fmt.Errorf("hook failed: %s: %w; output: %s", step, err, b.String()) 50 } 51 } 52 return nil 53 }