github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/internal/cli/ci.go (about)

     1  package cli
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"log"
     7  	"time"
     8  
     9  	"github.com/fatih/color"
    10  	"github.com/mattn/go-colorable"
    11  	"github.com/spf13/cobra"
    12  
    13  	"github.com/tilt-dev/tilt/internal/analytics"
    14  	"github.com/tilt-dev/tilt/internal/hud/prompt"
    15  	"github.com/tilt-dev/tilt/internal/store"
    16  	"github.com/tilt-dev/tilt/pkg/logger"
    17  	"github.com/tilt-dev/tilt/pkg/model"
    18  )
    19  
    20  type ciCmd struct {
    21  	fileName             string
    22  	outputSnapshotOnExit string
    23  }
    24  
    25  func (c *ciCmd) name() model.TiltSubcommand { return "ci" }
    26  
    27  func (c *ciCmd) register() *cobra.Command {
    28  	cmd := &cobra.Command{
    29  		Use:                   "ci [<tilt flags>] [-- <Tiltfile args>]",
    30  		DisableFlagsInUseLine: true,
    31  		Short:                 "Start Tilt in CI/batch mode with the given Tiltfile args",
    32  		Long: fmt.Sprintf(`
    33  Starts Tilt and runs resources defined in the Tiltfile.
    34  
    35  Exits with failure if any build fails or any server crashes.
    36  
    37  Exits with success if all tasks have completed successfully
    38  and all servers are healthy.
    39  
    40  While Tilt is running, you can view the UI at %s:%d
    41  (configurable with --host and --port).
    42  
    43  See blog post for additional information: https://blog.tilt.dev/2020/04/16/how-to-not-break-server-startup.html
    44  `, defaultWebHost, defaultWebPort),
    45  	}
    46  
    47  	addStartServerFlags(cmd)
    48  	addDevServerFlags(cmd)
    49  	addTiltfileFlag(cmd, &c.fileName)
    50  	addKubeContextFlag(cmd)
    51  	addNamespaceFlag(cmd)
    52  
    53  	cmd.Flags().BoolVar(&logActionsFlag, "logactions", false, "log all actions and state changes")
    54  	cmd.Flags().Lookup("logactions").Hidden = true
    55  	cmd.Flags().StringVar(&c.outputSnapshotOnExit, "output-snapshot-on-exit", "",
    56  		"If specified, Tilt will dump a snapshot of its state to the specified path when it exits")
    57  	cmd.Flags().DurationVar(&ciTimeout, "timeout", model.CITimeoutDefault,
    58  		"Timeout to wait for CI to pass. Set to 0 for no timeout.")
    59  
    60  	return cmd
    61  }
    62  
    63  func (c *ciCmd) run(ctx context.Context, args []string) error {
    64  	a := analytics.Get(ctx)
    65  	a.Incr("cmd.ci", nil)
    66  	defer a.Flush(time.Second)
    67  
    68  	deferred := logger.NewDeferredLogger(ctx)
    69  	ctx = redirectLogs(ctx, deferred)
    70  
    71  	log.SetFlags(log.Flags() &^ (log.Ldate | log.Ltime))
    72  
    73  	webHost := provideWebHost()
    74  	webURL, _ := provideWebURL(webHost, provideWebPort())
    75  	startLine := prompt.StartStatusLine(webURL, webHost)
    76  	log.Print(startLine)
    77  	log.Print(buildStamp())
    78  
    79  	if ok, reason := analytics.IsAnalyticsDisabledFromEnv(); ok {
    80  		log.Printf("Tilt analytics disabled: %s", reason)
    81  	}
    82  
    83  	cmdCIDeps, err := wireCmdCI(ctx, a, "ci")
    84  	if err != nil {
    85  		deferred.SetOutput(deferred.Original())
    86  		return err
    87  	}
    88  
    89  	upper := cmdCIDeps.Upper
    90  
    91  	l := store.NewLogActionLogger(ctx, upper.Dispatch)
    92  	deferred.SetOutput(l)
    93  	ctx = redirectLogs(ctx, l)
    94  	if c.outputSnapshotOnExit != "" {
    95  		defer cmdCIDeps.Snapshotter.WriteSnapshot(ctx, c.outputSnapshotOnExit)
    96  	}
    97  
    98  	err = upper.Start(ctx, args, cmdCIDeps.TiltBuild,
    99  		c.fileName, store.TerminalModeStream, a.UserOpt(), cmdCIDeps.Token,
   100  		string(cmdCIDeps.CloudAddress))
   101  	if err == nil {
   102  		_, _ = fmt.Fprintln(colorable.NewColorableStdout(),
   103  			color.GreenString("SUCCESS. All workloads are healthy."))
   104  	}
   105  	return err
   106  }
   107  
   108  var ciTimeout time.Duration