github.com/goreleaser/goreleaser@v1.25.1/internal/pipe/docker/api.go (about)

     1  package docker
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  	"os/exec"
     8  	"sync"
     9  
    10  	"github.com/caarlos0/log"
    11  	"github.com/goreleaser/goreleaser/internal/gio"
    12  	"github.com/goreleaser/goreleaser/internal/logext"
    13  	"github.com/goreleaser/goreleaser/pkg/context"
    14  )
    15  
    16  var (
    17  	manifesters = map[string]manifester{}
    18  	imagers     = map[string]imager{}
    19  	lock        sync.Mutex
    20  )
    21  
    22  func registerManifester(use string, impl manifester) {
    23  	lock.Lock()
    24  	defer lock.Unlock()
    25  	manifesters[use] = impl
    26  }
    27  
    28  func registerImager(use string, impl imager) {
    29  	lock.Lock()
    30  	defer lock.Unlock()
    31  	imagers[use] = impl
    32  }
    33  
    34  // imager is something that can build and push docker images.
    35  type imager interface {
    36  	Build(ctx *context.Context, root string, images, flags []string) error
    37  	Push(ctx *context.Context, image string, flags []string) (digest string, err error)
    38  }
    39  
    40  // manifester is something that can create and push docker manifests.
    41  type manifester interface {
    42  	Create(ctx *context.Context, manifest string, images, flags []string) error
    43  	Push(ctx *context.Context, manifest string, flags []string) (digest string, err error)
    44  }
    45  
    46  // nolint: unparam
    47  func runCommand(ctx *context.Context, dir, binary string, args ...string) error {
    48  	/* #nosec */
    49  	cmd := exec.CommandContext(ctx, binary, args...)
    50  	cmd.Dir = dir
    51  	cmd.Env = append(ctx.Env.Strings(), cmd.Environ()...)
    52  
    53  	var b bytes.Buffer
    54  	w := gio.Safe(&b)
    55  	cmd.Stderr = io.MultiWriter(logext.NewWriter(), w)
    56  	cmd.Stdout = io.MultiWriter(logext.NewWriter(), w)
    57  
    58  	log.
    59  		WithField("cmd", append([]string{binary}, args[0])).
    60  		WithField("cwd", dir).
    61  		WithField("args", args[1:]).Debug("running")
    62  	if err := cmd.Run(); err != nil {
    63  		return fmt.Errorf("%w: %s", err, b.String())
    64  	}
    65  	return nil
    66  }
    67  
    68  func runCommandWithOutput(ctx *context.Context, dir, binary string, args ...string) ([]byte, error) {
    69  	/* #nosec */
    70  	cmd := exec.CommandContext(ctx, binary, args...)
    71  	cmd.Dir = dir
    72  	cmd.Env = append(ctx.Env.Strings(), cmd.Environ()...)
    73  
    74  	var b bytes.Buffer
    75  	w := gio.Safe(&b)
    76  	cmd.Stderr = io.MultiWriter(logext.NewWriter(), w)
    77  
    78  	log.
    79  		WithField("cmd", append([]string{binary}, args[0])).
    80  		WithField("cwd", dir).
    81  		WithField("args", args[1:]).
    82  		Debug("running")
    83  	out, err := cmd.Output()
    84  	if out != nil {
    85  		// regardless of command success, always print stdout for backward-compatibility with runCommand()
    86  		_, _ = io.MultiWriter(logext.NewWriter(), w).Write(out)
    87  	}
    88  	if err != nil {
    89  		return nil, fmt.Errorf("%w: %s", err, b.String())
    90  	}
    91  
    92  	return out, nil
    93  }