github.com/triarius/goreleaser@v1.12.5/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/triarius/goreleaser/internal/gio"
    13  	"github.com/triarius/goreleaser/internal/logext"
    14  	"github.com/triarius/goreleaser/internal/tmpl"
    15  	"github.com/triarius/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 {
    23  	return len(ctx.Config.Before.Hooks) == 0 || ctx.SkipBefore
    24  }
    25  
    26  // Run executes the hooks.
    27  func (Pipe) Run(ctx *context.Context) error {
    28  	tmpl := tmpl.New(ctx)
    29  	/* #nosec */
    30  	for _, step := range ctx.Config.Before.Hooks {
    31  		s, err := tmpl.Apply(step)
    32  		if err != nil {
    33  			return err
    34  		}
    35  		args, err := shellwords.Parse(s)
    36  		if err != nil {
    37  			return err
    38  		}
    39  
    40  		cmd := exec.Command(args[0], args[1:]...)
    41  		cmd.Env = ctx.Env.Strings()
    42  
    43  		var b bytes.Buffer
    44  		w := gio.Safe(&b)
    45  		fields := log.Fields{"hook": step}
    46  		cmd.Stderr = io.MultiWriter(logext.NewWriter(fields, logext.Error), w)
    47  		cmd.Stdout = io.MultiWriter(logext.NewWriter(fields, logext.Info), w)
    48  
    49  		log.WithFields(fields).Info("running")
    50  		if err := cmd.Run(); err != nil {
    51  			return fmt.Errorf("hook failed: %s: %w; output: %s", step, err, b.String())
    52  		}
    53  	}
    54  	return nil
    55  }