← back to Daily Overnight Skus

check-overnight-run.sh

81 lines

#!/usr/bin/env bash
# One-shot self-check for the revived daily-overnight-skus launchd job.
# Fires ~45 min after the 6:30 AM PT run, verifies it succeeded, emails the
# pass/fail to info@ via George, then UNLOADS + DELETES its own plist so it
# truly runs once. Installed by Steve on 2026-06-02 after reviving the job.
set -u
DIR=/Users/macstudio3/Projects/daily-overnight-skus
SELFPLIST=/Users/macstudio3/Library/LaunchAgents/com.steve.daily-overnight-skus-selfcheck.plist
LOG="$DIR/selfcheck.log"
exec >>"$LOG" 2>&1
echo "=== selfcheck $(date) ==="

# Load George creds the same way run.sh does.
set -a; . /Users/macstudio3/Projects/secrets-manager/.env 2>/dev/null; set +a
GMAIL_AGENT="${GMAIL_AGENT:-https://kamatera.tail79cb8e.ts.net:9850}"
AUTH="Basic ${GMAIL_BASIC_AUTH_B64:-}"

TODAY_PT=$(TZ=America/Los_Angeles date +%Y-%m-%d)
PASS=1
FINDINGS=""

add() { FINDINGS="${FINDINGS}- $1"$'\n'; }

# 1) run.log has a header from today
LASTHDR=$(grep '^=== ' "$DIR/run.log" 2>/dev/null | tail -1)
if echo "$LASTHDR" | grep -q "$(TZ=America/Los_Angeles date '+%a %b %e')" 2>/dev/null \
   || echo "$LASTHDR" | grep -q "$TODAY_PT"; then
  add "run.log: fresh header today ✓  ($LASTHDR)"
else
  PASS=0; add "run.log: NO fresh header for $TODAY_PT — job may not have fired. last: ${LASTHDR:-<none>}"
fi

# 2) launchd.err.log empty / no errors
ERRSIZE=$(wc -c < "$DIR/launchd.err.log" 2>/dev/null | tr -d ' ')
if [ "${ERRSIZE:-0}" -gt 0 ]; then
  PASS=0; add "launchd.err.log: NON-EMPTY (${ERRSIZE} bytes) — tail: $(tail -3 "$DIR/launchd.err.log" 2>/dev/null | tr '\n' '|')"
else
  add "launchd.err.log: empty ✓"
fi

# 3) launchctl last-exit status for the main job
LCLINE=$(launchctl list 2>/dev/null | grep 'com.steve.daily-overnight-skus$')
LCEXIT=$(echo "$LCLINE" | awk '{print $2}')
if [ "${LCEXIT:-x}" = "0" ]; then
  add "launchctl: job present, last exit 0 ✓"
else
  PASS=0; add "launchctl: last exit='${LCEXIT:-MISSING}' (line: ${LCLINE:-<not loaded>})"
fi

# 4) email actually sent (or legitimately no orders)
if grep -q '\[weekend-csv\] Email sent' "$DIR/run.log" 2>/dev/null && \
   [ -n "$(grep '\[weekend-csv\] Email sent' "$DIR/run.log" | tail -1)" ]; then
  add "email: $(grep '\[weekend-csv\] Email sent' "$DIR/run.log" | tail -1)"
elif grep -q 'No orders in window' "$DIR/run.log" 2>/dev/null; then
  add "email: no orders in window (valid success — nothing to send)"
else
  PASS=0; add "email: no 'Email sent' nor 'No orders in window' line — send path may have failed. Check George at $GMAIL_AGENT"
fi

VERDICT=$([ "$PASS" = "1" ] && echo "PASS ✅" || echo "FAIL ❌")
echo "VERDICT: $VERDICT"
echo "$FINDINGS"

# Email the result via George (same path the job uses).
BODY="<h2>Overnight-SKU job self-check — $VERDICT</h2><p>First scheduled run after the 2026-06-02 revive. Date: $TODAY_PT PT.</p><pre>$(echo "$FINDINGS" | sed 's/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g')</pre><p>Logs: $DIR/run.log · launchd.err.log · selfcheck.log</p>"
if [ -n "${GMAIL_BASIC_AUTH_B64:-}" ]; then
  curl -s -m 25 -X POST "$GMAIL_AGENT/api/send-with-attachment" \
    -H 'Content-Type: application/json' -H "Authorization: $AUTH" \
    -d "$(python3 -c "import json,sys; print(json.dumps({'to':'info@designerwallcoverings.com','subject':'[overnight-job self-check] $VERDICT — $TODAY_PT','body':sys.argv[1]}))" "$BODY")" \
    && echo "[selfcheck] notification POSTed" || echo "[selfcheck] George POST failed (job verdict still in this log)"
else
  echo "[selfcheck] GMAIL_BASIC_AUTH_B64 not loaded — cannot email; verdict is in this log only"
fi

# Self-destruct: this is a one-shot. Unload + remove own plist.
echo "[selfcheck] unloading + removing own plist (one-shot)"
launchctl unload "$SELFPLIST" 2>/dev/null
rm -f "$SELFPLIST"
echo "=== selfcheck done $(date) ==="
exit 0