diff --git a/restart_process/CONTRIBUTING.md b/restart_process/CONTRIBUTING.md new file mode 100644 index 000000000..927e2d601 --- /dev/null +++ b/restart_process/CONTRIBUTING.md @@ -0,0 +1,7 @@ +# Contributing + +## Releasing + +If you have push access to the `tiltdev` repository on DockerHub, you can release a new version of the binaries used by this extension like so: +1. run `release.sh` (builds `tilt-restart-wrapper` from source, builds and pushes a Docker image with the new binary and a fresh binary of `entr` also installed from source) +2. update the image tag in the [Tiltfile](/restart_process/Tiltfile) with the tag you just pushed (you'll find the image referenced in the Dockerfile contents of the child image--look for "FROM tiltdev/restart-helper") diff --git a/restart_process/README.md b/restart_process/README.md index 882bbdb9a..b9ff79c1a 100644 --- a/restart_process/README.md +++ b/restart_process/README.md @@ -173,11 +173,10 @@ When specified as a `command` in Kubernetes or Docker Compose YAML (this is how ``` Any `args` specified in Kubernetes/Docker Compose are attached to the end of this call, and therefore in this case would apply TO THE `/bin/sh -c` CALL, rather than to the actual command run by `entr`; that is, any `args` specified by the user would be effectively ignored. -In order to make `entr` usable without a shell, this extension uses [a simple binary](/restart_process/tilt-restart-wrapper.go) that invokes `entr` and writes to its stdin. +In order to make `entr` usable without a shell, this extension uses [a simple binary](tilt-restart-wrapper.go) that invokes `entr` and writes to its stdin. Note: ideally `entr` could accept files-to-watch via flag instead of stdin, but (for a number of good reasons) this feature isn't likely to be added any time soon (see [entr#33](https://github.com/eradman/entr/issues/33)). -## For Maintainers: Releasing -If you have push access to the `tiltdev` repository on DockerHub, you can release a new version of the binaries used by this extension like so: -1. run `release.sh` (builds `tilt-restart-wrapper` from source, builds and pushes a Docker image with the new binary and a fresh binary of `entr` also installed from source) -2. update the image tag in the [Tiltfile](/restart_process/Tiltfile) with the tag you just pushed (you'll find the image referenced in the Dockerfile contents of the child image--look for "FROM tiltdev/restart-helper") +## Contributing + +[Update instructions](CONTRIBUTING.md) diff --git a/restart_process/Tiltfile b/restart_process/Tiltfile index 99e147266..d8584e1c3 100644 --- a/restart_process/Tiltfile +++ b/restart_process/Tiltfile @@ -45,7 +45,7 @@ def _helper(base_ref, ref, entrypoint, live_update, restart_file=RESTART_FILE, t # (which makes use of `entr` to watch files and restart processes) to the user's image # we also set the image's entrypoint to give k8s_custom_deploy a chance of working: https://github.com/tilt-dev/tilt-extensions/issues/391 df = ''' - FROM tiltdev/restart-helper:2021-11-03 as restart-helper + FROM tiltdev/restart-helper:2024-06-06 as restart-helper FROM {ref} RUN ["touch", "{file}"] diff --git a/restart_process/test/Tiltfile b/restart_process/test/Tiltfile index 9b0e1b9a7..b619a66be 100644 --- a/restart_process/test/Tiltfile +++ b/restart_process/test/Tiltfile @@ -1,5 +1,10 @@ load('../Tiltfile', 'docker_build_with_restart') -k8s_yaml('job.yaml') +k8s_yaml('test-job.yaml') +k8s_yaml('failing-job.yaml') + +docker_build_with_restart('test_job', '.', dockerfile='Dockerfile.test', entrypoint='/start.sh', + live_update=[sync('./start.sh', '/start.sh')]) + docker_build_with_restart('failing_job', '.', dockerfile='Dockerfile.failing', entrypoint='/fail.sh', live_update=[sync('./fail.sh', '/fail.sh')]) diff --git a/restart_process/test/custom.Tiltfile b/restart_process/test/custom.Tiltfile index ea383e874..5ed9195ed 100644 --- a/restart_process/test/custom.Tiltfile +++ b/restart_process/test/custom.Tiltfile @@ -1,9 +1,18 @@ load('../Tiltfile', 'custom_build_with_restart') -k8s_yaml('job.yaml') +k8s_yaml('failing-job.yaml') custom_build_with_restart( 'failing_job', command='docker build -t $EXPECTED_REF -f Dockerfile.failing .', deps=['fail.sh'], entrypoint='/fail.sh', live_update=[sync('./fail.sh', '/fail.sh')]) + + +k8s_yaml('test-job.yaml') +custom_build_with_restart( + 'test_job', + command='docker build -t $EXPECTED_REF -f Dockerfile.test .', + deps=['start.sh'], + entrypoint='/start.sh', + live_update=[sync('./start.sh', '/start.sh')]) diff --git a/restart_process/test/job.yaml b/restart_process/test/failing-job.yaml similarity index 100% rename from restart_process/test/job.yaml rename to restart_process/test/failing-job.yaml diff --git a/restart_process/test/start.sh b/restart_process/test/start.sh index 39b964d05..c9bc98143 100755 --- a/restart_process/test/start.sh +++ b/restart_process/test/start.sh @@ -4,6 +4,14 @@ RESTART_COUNT="$(cat restart_count.txt)" echo "RESTART_COUNT: $RESTART_COUNT" RESTART_COUNT=$((RESTART_COUNT+1)) echo $RESTART_COUNT > restart_count.txt + +handle_sigterm() { + echo "SIGTERM received" + sleep 1 +} + +trap handle_sigterm SIGTERM + while true do echo running diff --git a/restart_process/test/test-job.yaml b/restart_process/test/test-job.yaml new file mode 100644 index 000000000..a1ef89ba4 --- /dev/null +++ b/restart_process/test/test-job.yaml @@ -0,0 +1,12 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: test-job +spec: + template: + spec: + containers: + - name: test-job + image: test_job + restartPolicy: Never + backoffLimit: 4 diff --git a/restart_process/test/trigger_custom_deploy_live_update.sh b/restart_process/test/trigger_custom_deploy_live_update.sh index 252f3f647..a7547a095 100755 --- a/restart_process/test/trigger_custom_deploy_live_update.sh +++ b/restart_process/test/trigger_custom_deploy_live_update.sh @@ -7,7 +7,7 @@ set -u touch start.sh # seconds -TIMEOUT=5 +TIMEOUT=10 for ((i=0;i<=$TIMEOUT;++i)) do tilt logs | grep -v test_update | grep -q "RESTART_COUNT: 1" if [[ $? -eq 0 ]]; then @@ -15,6 +15,7 @@ for ((i=0;i<=$TIMEOUT;++i)) do exit 0 fi echo no restart detected + touch start.sh sleep 1 done exit 1 diff --git a/restart_process/tilt-restart-wrapper.go b/restart_process/tilt-restart-wrapper.go index ddc81b340..7aabbfadd 100644 --- a/restart_process/tilt-restart-wrapper.go +++ b/restart_process/tilt-restart-wrapper.go @@ -35,6 +35,7 @@ import ( "log" "os" "os/exec" + "os/signal" "strings" "syscall" ) @@ -42,6 +43,7 @@ import ( var watchFile = flag.String("watch_file", "/.restart-proc", "File that entr will watch for changes; changes to this file trigger `entr` to rerun the command(s) passed") var entrPath = flag.String("entr_path", "/entr", "Path to `entr` executable") var entrFlags = flag.String("entr_flags", "-rz", "Command line flags to pass to `entr` executable") +var verboseSignals = flag.Bool("verbose_signals", false, "Print signals received by `tilt-restart-wrapper`") func main() { flag.Parse() @@ -52,7 +54,25 @@ func main() { cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr - if err := cmd.Run(); err != nil { + if err := cmd.Start(); err != nil { + log.Fatalf("error starting command: %v", err) + } + + // Set up a signal forwarding handler + sigs := make(chan os.Signal, 10) + signal.Notify(sigs) + go func() { + for sig := range sigs { + if *verboseSignals { + log.Printf("Received signal: %s (%d), forwarding to pid %d", sig, sig.(syscall.Signal), cmd.Process.Pid) + } + if err := cmd.Process.Signal(sig); err != nil { + log.Println("Error forwarding signal:", err) + } + } + }() + + if err := cmd.Wait(); err != nil { if exiterr, ok := err.(*exec.ExitError); ok { // The program has exited with an exit code != 0 if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {