feat(tracker-web): macOS LaunchAgent keep-alive for the fleet web tracker
Adds dashboards/tracker-web/launchd/ (boot script + install.sh + README) so tracker-web (:3003) auto-starts on login and restarts on crash/reboot, instead of dying silently between sessions. Mirrors agent-queue/launchd: boot script repairs PATH, loads JWT_SECRET from platform-service/.env (+ ~/.tracker-web.env overrides), points at the local platform-service, and execs `pnpm dev`. plist uses unconditional KeepAlive (restart on any exit, incl. a clean SIGTERM) + a 10s throttle; install.sh frees :3003 first to avoid a clash with deploy-gigafactory. Verified: killing the process respawns it and :3003 returns. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
e4c84acf29
commit
5ad521ad4c
37
dashboards/tracker-web/launchd/README.md
Normal file
37
dashboards/tracker-web/launchd/README.md
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# tracker-web LaunchAgent (keep-alive on :3003)
|
||||||
|
|
||||||
|
Auto-starts the fleet **web tracker** (`tracker-web`) on login and restarts it on
|
||||||
|
crash/reboot, so `http://localhost:3003` stays up without a babysitter. Mirrors
|
||||||
|
the `agent-queue/launchd/` pattern in `learning_ai_devops_tools`.
|
||||||
|
|
||||||
|
## Files
|
||||||
|
|
||||||
|
- `tracker-web-boot.sh` — boot entrypoint: repairs `PATH`, loads `JWT_SECRET` (+
|
||||||
|
co.) from `../../services/platform-service/.env` and optional
|
||||||
|
`~/.tracker-web.env` overrides, points the app at the local platform-service
|
||||||
|
(`PLATFORM_API_URL`, default `http://localhost:4003`), then `exec pnpm dev`.
|
||||||
|
- `install.sh` — renders `~/Library/LaunchAgents/com.bytelyst.tracker-web.plist`
|
||||||
|
(`RunAtLoad` + unconditional `KeepAlive` so it restarts on any exit, incl. a
|
||||||
|
clean SIGTERM, + a 10s crash-loop throttle), frees `:3003` if something else is
|
||||||
|
on it, then bootstraps + kickstarts it.
|
||||||
|
|
||||||
|
## Use
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash launchd/install.sh # install + start
|
||||||
|
bash launchd/install.sh --uninstall # stop + remove
|
||||||
|
|
||||||
|
tail -f ~/Library/Logs/tracker-web/tracker-web.out.log # logs
|
||||||
|
launchctl print gui/$(id -u)/com.bytelyst.tracker-web | sed -n '1,20p' # status
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- **Prereqs:** the platform-service backend on `:4003` (see
|
||||||
|
`learning_ai_devops_tools/scripts/deploy-gigafactory.sh`) and `pnpm` on `PATH`.
|
||||||
|
- **Don't double-manage the port:** while this LaunchAgent owns `:3003`, do not
|
||||||
|
also run `deploy-gigafactory.sh --with-tracker` / `--tracker-only` — they would
|
||||||
|
clash on `:3003`. Use one or the other.
|
||||||
|
- **Per-machine overrides:** drop env in `~/.tracker-web.env` (not tracked) to
|
||||||
|
override `PLATFORM_API_URL`, `DEFAULT_PRODUCT_ID`, etc.
|
||||||
|
- macOS only (LaunchAgents). On Linux use a `systemd --user` unit.
|
||||||
110
dashboards/tracker-web/launchd/install.sh
Executable file
110
dashboards/tracker-web/launchd/install.sh
Executable file
@ -0,0 +1,110 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# install.sh — install (or remove) the macOS LaunchAgent that auto-starts
|
||||||
|
# tracker-web (the fleet web tracker, :3003) on login and keeps it alive across
|
||||||
|
# reboot/crash.
|
||||||
|
#
|
||||||
|
# bash launchd/install.sh # render plist, load, and start now
|
||||||
|
# bash launchd/install.sh --uninstall # stop, unload, and remove the plist
|
||||||
|
#
|
||||||
|
# The plist is generated from the resolved repo path so it works on any clone.
|
||||||
|
# Logs land in ~/Library/Logs/tracker-web/.
|
||||||
|
#
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd -P)"
|
||||||
|
WEB_DIR="$(cd -- "$SCRIPT_DIR/.." >/dev/null 2>&1 && pwd -P)"
|
||||||
|
WRAPPER="$SCRIPT_DIR/tracker-web-boot.sh"
|
||||||
|
|
||||||
|
LABEL="com.bytelyst.tracker-web"
|
||||||
|
PLIST="$HOME/Library/LaunchAgents/$LABEL.plist"
|
||||||
|
LOG_DIR="$HOME/Library/Logs/tracker-web"
|
||||||
|
UID_NUM="$(id -u)"
|
||||||
|
DOMAIN="gui/$UID_NUM"
|
||||||
|
|
||||||
|
if [ "$(uname -s)" != "Darwin" ]; then
|
||||||
|
echo "install.sh: macOS only (LaunchAgents). On Linux use a systemd --user unit." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
uninstall() {
|
||||||
|
echo "[launchd] booting out $LABEL ..."
|
||||||
|
launchctl bootout "$DOMAIN/$LABEL" 2>/dev/null || true
|
||||||
|
rm -f "$PLIST"
|
||||||
|
echo "[launchd] removed $PLIST (tracker-web stopped)"
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ "${1:-}" = "--uninstall" ] || [ "${1:-}" = "-u" ]; then
|
||||||
|
uninstall
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ -f "$WRAPPER" ] || { echo "install.sh: missing $WRAPPER" >&2; exit 1; }
|
||||||
|
chmod +x "$WRAPPER" 2>/dev/null || true
|
||||||
|
mkdir -p "$HOME/Library/LaunchAgents" "$LOG_DIR"
|
||||||
|
|
||||||
|
# Avoid a port clash: if something else is already serving :3003 (e.g. a
|
||||||
|
# deploy-gigafactory.sh --tracker-only run), stop it so launchd owns the port.
|
||||||
|
if lsof -ti tcp:3003 >/dev/null 2>&1; then
|
||||||
|
echo "[launchd] freeing :3003 (an existing tracker is running) ..."
|
||||||
|
lsof -ti tcp:3003 | xargs kill 2>/dev/null || true
|
||||||
|
sleep 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[launchd] writing $PLIST"
|
||||||
|
cat > "$PLIST" <<EOF
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>Label</key>
|
||||||
|
<string>$LABEL</string>
|
||||||
|
|
||||||
|
<key>ProgramArguments</key>
|
||||||
|
<array>
|
||||||
|
<string>/bin/bash</string>
|
||||||
|
<string>$WRAPPER</string>
|
||||||
|
</array>
|
||||||
|
|
||||||
|
<!-- Start on login and ALWAYS restart it if it exits, for any reason
|
||||||
|
(crash, reboot, OOM, or a clean SIGTERM that exits 0 — a long-lived web
|
||||||
|
server should never just stay down). -->
|
||||||
|
<key>RunAtLoad</key>
|
||||||
|
<true/>
|
||||||
|
<key>KeepAlive</key>
|
||||||
|
<true/>
|
||||||
|
<!-- Guard against tight crash loops. -->
|
||||||
|
<key>ThrottleInterval</key>
|
||||||
|
<integer>10</integer>
|
||||||
|
|
||||||
|
<key>WorkingDirectory</key>
|
||||||
|
<string>$WEB_DIR</string>
|
||||||
|
|
||||||
|
<key>StandardOutPath</key>
|
||||||
|
<string>$LOG_DIR/tracker-web.out.log</string>
|
||||||
|
<key>StandardErrorPath</key>
|
||||||
|
<string>$LOG_DIR/tracker-web.err.log</string>
|
||||||
|
|
||||||
|
<!-- launchd's PATH is minimal; the wrapper also repairs PATH defensively. -->
|
||||||
|
<key>EnvironmentVariables</key>
|
||||||
|
<dict>
|
||||||
|
<key>PATH</key>
|
||||||
|
<string>$HOME/.local/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Reload cleanly (bootout first so a re-run picks up plist changes).
|
||||||
|
launchctl bootout "$DOMAIN/$LABEL" 2>/dev/null || true
|
||||||
|
launchctl bootstrap "$DOMAIN" "$PLIST"
|
||||||
|
launchctl enable "$DOMAIN/$LABEL"
|
||||||
|
launchctl kickstart -k "$DOMAIN/$LABEL"
|
||||||
|
|
||||||
|
echo "[launchd] installed + started: $LABEL (http://localhost:3003)"
|
||||||
|
echo "[launchd] status : launchctl print $DOMAIN/$LABEL | sed -n '1,20p'"
|
||||||
|
echo "[launchd] logs : tail -f $LOG_DIR/tracker-web.out.log"
|
||||||
|
echo "[launchd] stop : bash $SCRIPT_DIR/install.sh --uninstall"
|
||||||
|
echo
|
||||||
|
echo "NOTE: while this LaunchAgent owns :3003, do NOT also run"
|
||||||
|
echo " deploy-gigafactory.sh --with-tracker (it would clash on the port)."
|
||||||
44
dashboards/tracker-web/launchd/tracker-web-boot.sh
Executable file
44
dashboards/tracker-web/launchd/tracker-web-boot.sh
Executable file
@ -0,0 +1,44 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# tracker-web-boot.sh — boot/login entrypoint for the fleet web tracker.
|
||||||
|
#
|
||||||
|
# Launched by the macOS LaunchAgent (see ./install.sh) so tracker-web auto-starts
|
||||||
|
# on login and survives crash/reboot via KeepAlive — the supervision a bare
|
||||||
|
# `next dev` (or deploy-gigafactory.sh --tracker-only) doesn't provide.
|
||||||
|
#
|
||||||
|
# It does what launchd's minimal environment needs:
|
||||||
|
# 1. Repairs PATH so node/pnpm are found.
|
||||||
|
# 2. Loads JWT_SECRET + co. from platform-service/.env (and optional
|
||||||
|
# ~/.tracker-web.env overrides) so the telemetry/health proxies work.
|
||||||
|
# 3. Points the app at the local platform-service and execs `next dev`.
|
||||||
|
#
|
||||||
|
set -uo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd -P)"
|
||||||
|
WEB_DIR="$(cd -- "$SCRIPT_DIR/.." >/dev/null 2>&1 && pwd -P)" # dashboards/tracker-web
|
||||||
|
PS_ENV="$(cd -- "$WEB_DIR/../../services/platform-service" >/dev/null 2>&1 && pwd -P)/.env"
|
||||||
|
|
||||||
|
# launchd hands processes a bare PATH — prepend the usual node/pnpm locations.
|
||||||
|
export PATH="$HOME/.local/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:${PATH:-}"
|
||||||
|
|
||||||
|
# Backend secret + any other shared config from platform-service/.env, then
|
||||||
|
# per-machine overrides (~/.tracker-web.env, NOT tracked) which win.
|
||||||
|
set -a
|
||||||
|
[ -f "$PS_ENV" ] && . "$PS_ENV"
|
||||||
|
[ -f "$HOME/.tracker-web.env" ] && . "$HOME/.tracker-web.env"
|
||||||
|
set +a
|
||||||
|
|
||||||
|
# Where the app reaches the fleet backend + which product it scopes to by default.
|
||||||
|
: "${PLATFORM_API_URL:=http://localhost:4003}"
|
||||||
|
: "${PLATFORM_SERVICE_URL:=$PLATFORM_API_URL}"
|
||||||
|
: "${DEFAULT_PRODUCT_ID:=lysnrai}"
|
||||||
|
: "${PRODUCT_ID:=$DEFAULT_PRODUCT_ID}"
|
||||||
|
export PLATFORM_API_URL PLATFORM_SERVICE_URL DEFAULT_PRODUCT_ID PRODUCT_ID
|
||||||
|
|
||||||
|
echo "[tracker-web-boot] $(date '+%Y-%m-%d %H:%M:%S') starting tracker-web on :3003" \
|
||||||
|
"(platform=$PLATFORM_API_URL, product=$DEFAULT_PRODUCT_ID)"
|
||||||
|
|
||||||
|
cd "$WEB_DIR"
|
||||||
|
# exec so the LaunchAgent tracks the real next-dev PID (clean KeepAlive restarts).
|
||||||
|
# `dev` matches the rest of the local setup; the package script pins --port 3003.
|
||||||
|
exec pnpm dev
|
||||||
Loading…
Reference in New Issue
Block a user