← back to Dw Yolo Loop
scripts/promote-canary.sh
77 lines
#!/bin/bash
# promote-canary.sh — turn a built-but-unscheduled canary script into a launchd
# job. WRITES a plist to ~/Library/LaunchAgents/ and PRINTS the bootstrap command
# — it NEVER runs launchctl bootstrap itself (plist install is Steve-gated, and
# the auto-mode classifier blocks autonomous launchd bootstrap). Idempotent: a
# re-run overwrites the plist with the same content.
#
# Born from the 2026-06-16 Officer Council #2 pick (Canary Promotion Harness):
# the overnight loop built ~8 read-only canaries and scheduled NONE — the exact
# pattern that let the pg_dump backup die silent for 12 days. This closes the
# build→schedule gap with one reusable step.
#
# Usage:
# bash scripts/promote-canary.sh <label> <abs-script-path> <cadence> [hour] [minute] [weekday]
# <label> e.g. dw-handle-freshness (becomes com.steve.<label>)
# <cadence> daily | weekly
# weekday 0-6 (Sun=0), only used for weekly
# Example (nightly 3:10am): bash scripts/promote-canary.sh dw-handle-freshness \
# "$HOME/Projects/designerwallcoverings/scripts/handle-freshness/handle-freshness-canary.mjs" daily 3 10
# Example (weekly Mon 4:00): ... tls-expiry ... weekly 4 0 1
#
# READ-ONLY w.r.t. prod. $0. The generated job just runs the (read-only) canary.
set -euo pipefail
LABEL="${1:?need label, e.g. dw-handle-freshness}"
SCRIPT="${2:?need absolute script path}"
CADENCE="${3:?need cadence: daily|weekly}"
HOUR="${4:-3}"
MIN="${5:-15}"
WEEKDAY="${6:-1}" # Monday default for weekly
[ -f "$SCRIPT" ] || { echo "✗ script not found: $SCRIPT" >&2; exit 1; }
FULL="com.steve.${LABEL}"
PLIST="$HOME/Library/LaunchAgents/${FULL}.plist"
# choose runner by extension
case "$SCRIPT" in
*.mjs|*.js) RUN="/usr/bin/env node \"$SCRIPT\"";;
*.sh) RUN="/bin/bash \"$SCRIPT\"";;
*.py) RUN="/usr/bin/env python3 \"$SCRIPT\"";;
*) RUN="\"$SCRIPT\"";;
esac
if [ "$CADENCE" = "weekly" ]; then
CAL="<dict><key>Weekday</key><integer>${WEEKDAY}</integer><key>Hour</key><integer>${HOUR}</integer><key>Minute</key><integer>${MIN}</integer></dict>"
else
CAL="<dict><key>Hour</key><integer>${HOUR}</integer><key>Minute</key><integer>${MIN}</integer></dict>"
fi
cat > "$PLIST" <<PLISTEOF
<?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>${FULL}</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string><string>-lc</string>
<string>${RUN} >> /tmp/${LABEL}.log 2>&1</string>
</array>
<key>StartCalendarInterval</key>${CAL}
<key>RunAtLoad</key><false/>
<key>StandardOutPath</key><string>/tmp/${LABEL}.launchd.out.log</string>
<key>StandardErrorPath</key><string>/tmp/${LABEL}.launchd.err.log</string>
</dict>
</plist>
PLISTEOF
echo "✓ wrote $PLIST (${CADENCE} ${HOUR}:$(printf '%02d' "$MIN")${CADENCE:+${WEEKDAY:+}})"
echo ""
echo " → To ENABLE (Steve-gated — run this yourself):"
echo " launchctl bootstrap gui/\$(id -u) \"$PLIST\""
echo " → Verify: launchctl list | grep ${FULL}"
echo " → Run-now: launchctl kickstart -k gui/\$(id -u)/${FULL}"
echo " → Disable: launchctl bootout gui/\$(id -u)/${FULL}"