github.com/tilt-dev/tilt@v0.36.0/internal/tiltfile/local_resource.go (about)

     1  package tiltfile
     2  
     3  import (
     4  	"fmt"
     5  	"path/filepath"
     6  
     7  	"github.com/pkg/errors"
     8  	"go.starlark.net/starlark"
     9  
    10  	"github.com/tilt-dev/tilt/internal/tiltfile/links"
    11  	"github.com/tilt-dev/tilt/internal/tiltfile/probe"
    12  	"github.com/tilt-dev/tilt/internal/tiltfile/starkit"
    13  	"github.com/tilt-dev/tilt/internal/tiltfile/value"
    14  	"github.com/tilt-dev/tilt/pkg/apis/core/v1alpha1"
    15  	"github.com/tilt-dev/tilt/pkg/logger"
    16  	"github.com/tilt-dev/tilt/pkg/model"
    17  )
    18  
    19  const testDeprecationMsg = "test() is deprecated and will be removed in a future release.\n" +
    20  	"Change this call to use `local_resource(..., allow_parallel=True)`"
    21  
    22  type localResource struct {
    23  	name      string
    24  	updateCmd model.Cmd
    25  	serveCmd  model.Cmd
    26  	// The working directory of the execution thread where the local resource was created.
    27  	threadDir     string
    28  	deps          []string
    29  	triggerMode   triggerMode
    30  	autoInit      bool
    31  	resourceDeps  []string
    32  	ignores       []string
    33  	allowParallel bool
    34  	links         []model.Link
    35  	labels        map[string]string
    36  
    37  	readinessProbe *v1alpha1.Probe
    38  }
    39  
    40  func (s *tiltfileState) localResource(thread *starlark.Thread, fn *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
    41  	var name value.Name
    42  	var updateCmdVal, updateCmdBatVal, serveCmdVal, serveCmdBatVal starlark.Value
    43  	var updateEnv, serveEnv value.StringStringMap
    44  	var triggerMode triggerMode
    45  	var readinessProbe probe.Probe
    46  	var updateCmdDirVal, serveCmdDirVal starlark.Value
    47  
    48  	deps := value.NewLocalPathListUnpacker(thread)
    49  
    50  	var resourceDepsVal starlark.Sequence
    51  	var ignoresVal starlark.Value
    52  	var allowParallel bool
    53  	var links links.LinkList
    54  	var labels value.LabelSet
    55  	autoInit := true
    56  	if fn.Name() == testN {
    57  		// If we're initializing a test, by default parallelism is on
    58  		allowParallel = true
    59  		logger.Get(s.ctx).Warnf("%s", testDeprecationMsg)
    60  	}
    61  
    62  	if err := s.unpackArgs(fn.Name(), args, kwargs,
    63  		"name", &name,
    64  		"cmd?", &updateCmdVal,
    65  		"deps?", &deps,
    66  		"trigger_mode?", &triggerMode,
    67  		"resource_deps?", &resourceDepsVal,
    68  		"ignore?", &ignoresVal,
    69  		"auto_init?", &autoInit,
    70  		"serve_cmd?", &serveCmdVal,
    71  		"cmd_bat?", &updateCmdBatVal,
    72  		"serve_cmd_bat?", &serveCmdBatVal,
    73  		"allow_parallel?", &allowParallel,
    74  		"links?", &links,
    75  		"labels?", &labels,
    76  		"env?", &updateEnv,
    77  		"serve_env?", &serveEnv,
    78  		"readiness_probe?", &readinessProbe,
    79  		"dir?", &updateCmdDirVal,
    80  		"serve_dir?", &serveCmdDirVal,
    81  	); err != nil {
    82  		return nil, err
    83  	}
    84  
    85  	resourceDeps, err := value.SequenceToStringSlice(resourceDepsVal)
    86  	if err != nil {
    87  		return nil, errors.Wrapf(err, "%s: resource_deps", fn.Name())
    88  	}
    89  
    90  	ignores, err := parseValuesToStrings(ignoresVal, "ignore")
    91  	if err != nil {
    92  		return nil, err
    93  	}
    94  
    95  	updateCmd, err := value.ValueGroupToCmdHelper(thread, updateCmdVal, updateCmdBatVal, updateCmdDirVal, updateEnv)
    96  	if err != nil {
    97  		return nil, err
    98  	}
    99  	serveCmd, err := value.ValueGroupToCmdHelper(thread, serveCmdVal, serveCmdBatVal, serveCmdDirVal, serveEnv)
   100  	if err != nil {
   101  		return nil, err
   102  	}
   103  
   104  	// Validate dir/cmd combinations to prevent common mistakes
   105  	if updateCmdDirVal != nil && updateCmd.Empty() {
   106  		if !serveCmd.Empty() {
   107  			return nil, fmt.Errorf("local_resource: 'dir' only affects 'cmd', not 'serve_cmd'. Did you mean to use 'serve_dir' instead?")
   108  		}
   109  		return nil, fmt.Errorf("local_resource: 'dir' specified but 'cmd' is empty")
   110  	}
   111  
   112  	if serveCmdDirVal != nil && serveCmd.Empty() {
   113  		return nil, fmt.Errorf("local_resource: 'serve_dir' specified but 'serve_cmd' is empty")
   114  	}
   115  
   116  	if updateCmd.Empty() && serveCmd.Empty() {
   117  		return nil, fmt.Errorf("local_resource must have a cmd and/or a serve_cmd, but both were empty")
   118  	}
   119  
   120  	probeSpec := readinessProbe.Spec()
   121  	if probeSpec != nil && serveCmd.Empty() {
   122  		s.logger.Warnf("Ignoring readiness probe for local resource %q (no serve_cmd was defined)", name)
   123  		probeSpec = nil
   124  	}
   125  
   126  	res := &localResource{
   127  		name:           string(name),
   128  		updateCmd:      updateCmd,
   129  		serveCmd:       serveCmd,
   130  		threadDir:      filepath.Dir(starkit.CurrentExecPath(thread)),
   131  		deps:           deps.Value,
   132  		triggerMode:    triggerMode,
   133  		autoInit:       autoInit,
   134  		resourceDeps:   resourceDeps,
   135  		ignores:        ignores,
   136  		allowParallel:  allowParallel,
   137  		links:          links.Links,
   138  		labels:         labels.Values,
   139  		readinessProbe: probeSpec,
   140  	}
   141  
   142  	// check for duplicate resources by name and throw error if found
   143  	err = s.checkResourceConflict(res.name)
   144  	if err != nil {
   145  		return nil, err
   146  	}
   147  	s.localResources = append(s.localResources, res)
   148  	s.localByName[res.name] = res
   149  
   150  	return starlark.None, nil
   151  }