github.com/grahambrereton-form3/tilt@v0.10.18/internal/engine/build_and_deployer.go (about)

     1  package engine
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"strings"
     7  
     8  	"github.com/windmilleng/tilt/internal/container"
     9  	"github.com/windmilleng/tilt/internal/k8s"
    10  	"github.com/windmilleng/tilt/internal/store"
    11  
    12  	"github.com/windmilleng/tilt/pkg/logger"
    13  	"github.com/windmilleng/tilt/pkg/model"
    14  )
    15  
    16  type BuildAndDeployer interface {
    17  	// BuildAndDeploy builds and deployed the specified target specs.
    18  	//
    19  	// Returns a BuildResult that expresses the outputs(s) of the build.
    20  	//
    21  	// BuildResult can be used to construct a set of BuildStates, which contain
    22  	// the last successful builds of each target and the files changed since that build.
    23  	BuildAndDeploy(ctx context.Context, st store.RStore, specs []model.TargetSpec, currentState store.BuildStateSet) (store.BuildResultSet, error)
    24  }
    25  
    26  type BuildOrder []BuildAndDeployer
    27  
    28  func (bo BuildOrder) String() string {
    29  	var output strings.Builder
    30  	output.WriteString("BuildOrder{")
    31  
    32  	for _, b := range bo {
    33  		output.WriteString(fmt.Sprintf(" %T", b))
    34  	}
    35  
    36  	output.WriteString(" }")
    37  
    38  	return output.String()
    39  }
    40  
    41  type FallbackTester func(error) bool
    42  
    43  // CompositeBuildAndDeployer tries to run each builder in order.  If a builder
    44  // emits an error, it uses the FallbackTester to determine whether the error is
    45  // critical enough to stop the whole pipeline, or to fallback to the next
    46  // builder.
    47  type CompositeBuildAndDeployer struct {
    48  	builders BuildOrder
    49  }
    50  
    51  var _ BuildAndDeployer = &CompositeBuildAndDeployer{}
    52  
    53  func NewCompositeBuildAndDeployer(builders BuildOrder) *CompositeBuildAndDeployer {
    54  	return &CompositeBuildAndDeployer{builders: builders}
    55  }
    56  
    57  func (composite *CompositeBuildAndDeployer) BuildAndDeploy(ctx context.Context, st store.RStore, specs []model.TargetSpec, currentState store.BuildStateSet) (store.BuildResultSet, error) {
    58  	var lastErr, lastUnexpectedErr error
    59  	logger.Get(ctx).Debugf("Building with BuildOrder: %s", composite.builders.String())
    60  	for i, builder := range composite.builders {
    61  		logger.Get(ctx).Debugf("Trying to build and deploy with %T", builder)
    62  		br, err := builder.BuildAndDeploy(ctx, st, specs, currentState)
    63  		if err == nil {
    64  			return br, err
    65  		}
    66  
    67  		if !shouldFallBackForErr(err) {
    68  			return br, err
    69  		}
    70  
    71  		if redirectErr, ok := err.(RedirectToNextBuilder); ok {
    72  			s := fmt.Sprintf("falling back to next update method because: %v\n", err)
    73  			logger.Get(ctx).Write(redirectErr.level, s)
    74  		} else {
    75  			lastUnexpectedErr = err
    76  			if i+1 < len(composite.builders) {
    77  				logger.Get(ctx).Infof("got unexpected error during build/deploy: %v", err)
    78  			}
    79  		}
    80  		lastErr = err
    81  	}
    82  
    83  	if lastUnexpectedErr != nil {
    84  		// The most interesting error is the last UNEXPECTED error we got
    85  		return store.BuildResultSet{}, lastUnexpectedErr
    86  	}
    87  	return store.BuildResultSet{}, lastErr
    88  }
    89  
    90  func DefaultBuildOrder(lubad *LiveUpdateBuildAndDeployer, ibad *ImageBuildAndDeployer, dcbad *DockerComposeBuildAndDeployer,
    91  	ltbad *LocalTargetBuildAndDeployer, updMode UpdateMode, env k8s.Env, runtime container.Runtime) BuildOrder {
    92  	if updMode == UpdateModeImage || updMode == UpdateModeNaive {
    93  		return BuildOrder{dcbad, ibad, ltbad}
    94  	}
    95  
    96  	if updMode == UpdateModeSynclet || shouldUseSynclet(updMode, env, runtime) {
    97  		ibad.SetInjectSynclet(true)
    98  	}
    99  
   100  	return BuildOrder{lubad, dcbad, ibad, ltbad}
   101  }
   102  
   103  func shouldUseSynclet(updMode UpdateMode, env k8s.Env, runtime container.Runtime) bool {
   104  	return updMode == UpdateModeAuto && !env.UsesLocalDockerRegistry() && runtime == container.RuntimeDocker
   105  }