spawn/sh/shared/sprite-keep-running.sh
Ahmed Abushagur 66a1749b4b
Some checks are pending
CLI Release / Build and release CLI (push) Waiting to run
Lint / ShellCheck (push) Waiting to run
Lint / Biome Lint (push) Waiting to run
Lint / macOS Compatibility (push) Waiting to run
fix: add sprite-keep-running.sh, remove Hetzner from Packer, cleanup on cancel (#2869)
* fix: destroy orphaned Packer builder instances on workflow cancel

When a Packer Snapshots workflow is cancelled mid-build, Packer's process
is killed before it can clean up its temporary builder droplet/server.
This leaves orphaned packer-* instances running and costing money.

Add `if: cancelled()` cleanup steps for both DigitalOcean and Hetzner
that destroy any packer-* prefixed instances after cancellation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: remove Hetzner cleanup step — only DO needed

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: remove Hetzner from Packer snapshots, add cancel cleanup

Remove Hetzner from the Packer workflow entirely — only DigitalOcean
snapshots are built. Deletes packer/hetzner.pkr.hcl and simplifies the
workflow by removing all Hetzner-specific steps and cloud conditionals.

Also adds a cancelled() cleanup step that destroys orphaned packer-*
builder droplets when a workflow run is cancelled mid-build.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: add missing sprite-keep-running.sh script

The keep-alive install was 404ing because sh/shared/sprite-keep-running.sh
never existed in the repo. The TypeScript code downloaded it from the CDN
(which maps to sh/shared/) but the file was never created.

The script wraps a command and pings the sprite's own public URL every 30s
to prevent inactivity shutdown. It resolves the URL via sprite-env info
(available on all sprites) and falls back to exec without keep-alive if
the URL can't be determined.

Also removes Hetzner from the Packer snapshots workflow entirely — only
DigitalOcean snapshots are built.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address security review — scope cleanup filter, fix JSON injection

1. Add `spawn-packer` tag to DO builder droplets in Packer template and
   filter cleanup by tag instead of broad `packer-` name prefix. Prevents
   accidentally destroying builder instances from other concurrent builds.

2. Use `jq --arg` for SINGLE_AGENT_INPUT instead of string interpolation
   to prevent JSON injection via crafted agent names.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 18:13:38 +00:00

46 lines
1.2 KiB
Bash
Executable file

#!/bin/bash
set -eo pipefail
# sprite-keep-running — Wraps a command and keeps the sprite alive by pinging
# its own public URL every 30 seconds. Prevents inactivity shutdown while an
# agent session is running.
#
# Usage: sprite-keep-running <command> [args...]
#
# The keep-alive loop runs in the background and is killed when the wrapped
# command exits. Exit code is preserved from the wrapped command.
if [ $# -eq 0 ]; then
echo "Usage: sprite-keep-running <command> [args...]" >&2
exit 1
fi
# Resolve sprite's own public URL via sprite-env (available on all sprites)
SPRITE_URL=""
if command -v sprite-env >/dev/null 2>&1; then
SPRITE_URL=$(sprite-env info 2>/dev/null | grep -o '"sprite_url":"[^"]*"' | cut -d'"' -f4) || true
fi
if [ -z "${SPRITE_URL}" ]; then
# Can't determine URL — just run the command without keep-alive
exec "$@"
fi
# Start background keep-alive loop
(
while true; do
curl -sf "${SPRITE_URL}" >/dev/null 2>&1 || true
sleep 30
done
) &
KEEPALIVE_PID=$!
# Ensure keep-alive is killed on exit
cleanup() {
kill "${KEEPALIVE_PID}" 2>/dev/null || true
wait "${KEEPALIVE_PID}" 2>/dev/null || true
}
trap cleanup EXIT INT TERM
# Run the wrapped command
"$@"