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  }