github.com/yourbase/yb@v0.7.1/cmd/yb/exec.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"os"
     7  
     8  	"github.com/spf13/cobra"
     9  	"github.com/yourbase/yb"
    10  	"github.com/yourbase/yb/internal/build"
    11  	"github.com/yourbase/yb/internal/ybdata"
    12  	"zombiezen.com/go/log"
    13  )
    14  
    15  type execCmd struct {
    16  	execEnvName string
    17  	env         []commandLineEnv
    18  	netrcFiles  []string
    19  	mode        executionMode
    20  }
    21  
    22  func newExecCmd() *cobra.Command {
    23  	b := new(execCmd)
    24  	c := &cobra.Command{
    25  		Use:   "exec",
    26  		Short: "Run the package",
    27  		Long: `Run the package using the instructions in the .yourbase.yml exec block.` +
    28  			"\n\n" +
    29  			`yb exec will search for the .yourbase.yml file in the current directory ` +
    30  			`and its parent directories. The exec block's commands will be run in the ` +
    31  			`directory the .yourbase.yml file appears in.`,
    32  		Args:          cobra.NoArgs,
    33  		SilenceErrors: true,
    34  		SilenceUsage:  true,
    35  		RunE: func(cmd *cobra.Command, args []string) error {
    36  			return b.run(cmd.Context())
    37  		},
    38  	}
    39  	envFlagsVar(c.Flags(), &b.env)
    40  	netrcFlagVar(c.Flags(), &b.netrcFiles)
    41  	executionModeVar(c.Flags(), &b.mode)
    42  	// TODO(light): Use a less confusing name for this flag when it is using targets.
    43  	c.Flags().StringVar(&b.execEnvName, "environment", yb.DefaultExecEnvironment, "Environment to run as")
    44  	return c
    45  }
    46  
    47  func (b *execCmd) run(ctx context.Context) error {
    48  	dataDirs, err := ybdata.DirsFromEnv()
    49  	if err != nil {
    50  		return err
    51  	}
    52  	downloader := ybdata.NewDownloader(dataDirs.Downloads())
    53  	baseEnv, err := envFromCommandLine(b.env)
    54  	if err != nil {
    55  		return err
    56  	}
    57  	const useDocker = true
    58  	dockerClient, err := connectDockerClient(b.mode)
    59  	if err != nil {
    60  		return err
    61  	}
    62  
    63  	ctx = withLogOutput(ctx, os.Stdout)
    64  	pkg, _, err := findPackage()
    65  	if err != nil {
    66  		return err
    67  	}
    68  	execTarget := pkg.ExecEnvironments[b.execEnvName]
    69  	if execTarget == nil {
    70  		return fmt.Errorf("exec %s: no such environment", b.execEnvName)
    71  	}
    72  	showDockerWarningsIfNeeded(ctx, b.mode, []*yb.Target{execTarget})
    73  	dockerNetworkID, removeNetwork, err := newDockerNetwork(ctx, dockerClient, b.mode, []*yb.Target{execTarget})
    74  	if err != nil {
    75  		return err
    76  	}
    77  	defer removeNetwork()
    78  	bio, err := newBiome(ctx, execTarget, newBiomeOptions{
    79  		packageDir:      pkg.Path,
    80  		dataDirs:        dataDirs,
    81  		downloader:      downloader,
    82  		baseEnv:         baseEnv,
    83  		netrcFiles:      b.netrcFiles,
    84  		executionMode:   b.mode,
    85  		dockerClient:    dockerClient,
    86  		dockerNetworkID: dockerNetworkID,
    87  	})
    88  	if err != nil {
    89  		return err
    90  	}
    91  	defer func() {
    92  		if err := bio.Close(); err != nil {
    93  			log.Warnf(ctx, "Clean up environment: %v", err)
    94  		}
    95  	}()
    96  	sys := build.Sys{
    97  		Biome:           bio,
    98  		Downloader:      downloader,
    99  		DockerClient:    dockerClient,
   100  		DockerNetworkID: dockerNetworkID,
   101  		Stdout:          os.Stdout,
   102  		Stderr:          os.Stderr,
   103  	}
   104  	execBiome, err := build.Setup(withLogPrefix(ctx, execTarget.Name+setupLogPrefix), sys, execTarget)
   105  	if err != nil {
   106  		return err
   107  	}
   108  	sys.Biome = execBiome
   109  	defer func() {
   110  		if err := execBiome.Close(); err != nil {
   111  			log.Errorf(ctx, "Clean up environment %s: %v", b.execEnvName, err)
   112  		}
   113  	}()
   114  	return build.Execute(ctx, sys, announceCommand(os.Stdout), execTarget)
   115  }