tilt
tilt copied to clipboard
`local` run-once option for `tilt up`
Describe the Feature You Want
local run once or some prerequisite phase that runs only once for a tiltfile.
Current Behavior
Tilt tries to generate files that trigger the k8s_yaml or any deps
field change and reload of tilt. This leads to an endless loop of local commands triggering k8s_yaml tilt reload. I don't want to ignore the files as these are regenerated with each save by a tilt state.
Why Do You Want This?
This phase can be used to pre-generate some files that will be loaded as resources by k8s_yaml without triggering an endless loop. I use kapitan go generate some files and would like to generate the files for each save. But to load these files in the first place I have to have them in the folder which requires me to do the first generation outside of Tilt.
Additional context Add any other context or screenshots about the feature request here.
I'm not sure if you have tried something like this (maybe you have), but you could do something like below to get this behavior:
if config.tilt_subcommand == "up":
did_once = os.getenv("DID_ONCE", False)
if not did_once:
print("Do once!")
os.putenv("DID_ONCE", "true")
Note that if you just use DID_ONCE
env var - it will run once during tilt up lifetime. If you want to run once per Tiltfile load, you can use smth like below:
ONCE_VARS_VAR='_TILT_ONCE_VARS'
def on_load():
os.putenv(ONCE_VARS_VAR, '')
def call_once(fn, *args, **kwargs):
desc = "fn={} args={}, kwargs={}".format(str(fn), args, kwargs)
desc_hash = str(hash(desc))
once_vars = os.getenv(ONCE_VARS_VAR, '')
did_once = desc_hash in once_vars.split()
if not did_once:
os.putenv(ONCE_VARS_VAR, once_vars + ' ' + desc_hash)
print("calling {}".format(desc))
fn(*args, **kwargs)
else:
print("already called {}".format(desc))
on_load()
Usage:
load('lib/functions.star',
'call_once',
)
call_once(print, "hello")
call_once(print, "hello")
call_once(print, "hello1")
call_once(print, "hello1")
Output will be:
Loading Tiltfile at: /home/me/tmp/tilt-test/Tiltfile
calling fn=<built-in function print> args=("hello",), kwargs={}
hello
already called fn=<built-in function print> args=("hello",), kwargs={}
calling fn=<built-in function print> args=("hello1",), kwargs={}
hello1
already called fn=<built-in function print> args=("hello1",), kwargs={}
These are good workarounds, but env vars are potentially not side effect safe. I am looking for a native lifecycle mechanism.
@Cyanopus I believe this is starlark limitation by design, see https://github.com/bazelbuild/starlark/blob/master/spec.md#freezing-a-value - so there are no synchronization primitives provided by the language.
Still, Tilt authors may decide to add this functionality with some built-in function.
I'm not sure if this helps, but I managed to break the infinite loop I had with my project - because I generate Kustomize YAML files with python-kustomize
- by using watch_settings
.