← back to Sister Parish Onboarding
schedule Shopify push for Wed 2am PT via launchd com.steve.sister-parish-push (idempotent, self-unloads at 73/73)
0956a19f29864389ada49008c808454d1131e52e · 2026-05-11 15:19:31 -0700 · Steve
Files touched
A scripts/scheduled_push.sh
Diff
commit 0956a19f29864389ada49008c808454d1131e52e
Author: Steve <steve@designerwallcoverings.com>
Date: Mon May 11 15:19:31 2026 -0700
schedule Shopify push for Wed 2am PT via launchd com.steve.sister-parish-push (idempotent, self-unloads at 73/73)
---
scripts/scheduled_push.sh | 82 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 82 insertions(+)
diff --git a/scripts/scheduled_push.sh b/scripts/scheduled_push.sh
new file mode 100755
index 0000000..96689cb
--- /dev/null
+++ b/scripts/scheduled_push.sh
@@ -0,0 +1,82 @@
+#!/bin/zsh
+# Wrapper called by com.steve.sister-parish-push launchd job.
+#
+# Idempotent:
+# - If Sister Parish products already in DW Shopify (count > 0), exit and self-unload.
+# - Otherwise run push_shopify.js, then if successful and all 73 landed, self-unload.
+#
+# Logs go to logs/scheduled_push.log alongside the project.
+
+set -euo pipefail
+
+ROOT="/Users/stevestudio2/Projects/sister-parish-onboarding"
+LOG="$ROOT/logs/scheduled_push.log"
+PLIST="$HOME/Library/LaunchAgents/com.steve.sister-parish-push.plist"
+PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin"
+
+mkdir -p "$ROOT/logs"
+exec >> "$LOG" 2>&1
+echo
+echo "===== $(date '+%F %T %Z') · scheduled_push.sh fired ====="
+
+# 1) Load DW Shopify creds
+if [[ ! -f "$HOME/Projects/dw-collections-viewer/.env" ]]; then
+ echo "FATAL: cannot find dw-collections-viewer/.env for SHOPIFY_* creds"
+ exit 2
+fi
+set -a; source "$HOME/Projects/dw-collections-viewer/.env"; set +a
+if [[ -z "${SHOPIFY_ADMIN_TOKEN:-}" || -z "${SHOPIFY_STORE:-}" ]]; then
+ echo "FATAL: SHOPIFY_ADMIN_TOKEN or SHOPIFY_STORE empty"; exit 2
+fi
+
+# 2) Pre-flight: how many SP products already in Shopify
+COUNT=$(curl -sf -H "X-Shopify-Access-Token: $SHOPIFY_ADMIN_TOKEN" \
+ "https://${SHOPIFY_STORE}/admin/api/2024-10/products/count.json?vendor=Sister+Parish&status=any" \
+ | /usr/bin/python3 -c "import json,sys; print(json.load(sys.stdin)['count'])" 2>/dev/null || echo "ERR")
+
+echo "Sister Parish count on DW Shopify: $COUNT"
+
+if [[ "$COUNT" == "ERR" ]]; then
+ echo "Shopify pre-flight failed — leaving plist installed for next fire"
+ exit 3
+fi
+
+if (( COUNT >= 73 )); then
+ echo "All 73 already in Shopify — running backfill, then self-unloading"
+ cd "$ROOT"
+ /usr/local/bin/node scripts/backfill_shopify_ids.js || /opt/homebrew/bin/node scripts/backfill_shopify_ids.js || true
+ echo "Unloading $PLIST"
+ /bin/launchctl unload "$PLIST" 2>/dev/null || true
+ /bin/rm -f "$PLIST"
+ echo "===== self-unloaded ====="
+ exit 0
+fi
+
+if (( COUNT > 0 )); then
+ echo "Partial state — $COUNT < 73. Will re-attempt push (push script idempotent on handle conflict)."
+fi
+
+# 3) Run push
+echo "--- running push_shopify.js ---"
+cd "$ROOT"
+NODE_BIN="/opt/homebrew/bin/node"
+[[ -x "$NODE_BIN" ]] || NODE_BIN="/usr/local/bin/node"
+[[ -x "$NODE_BIN" ]] || NODE_BIN="$(/usr/bin/which node)"
+"$NODE_BIN" scripts/push_shopify.js || PUSH_FAILED=1
+
+# 4) Verify final count + decide whether to self-unload
+COUNT2=$(curl -sf -H "X-Shopify-Access-Token: $SHOPIFY_ADMIN_TOKEN" \
+ "https://${SHOPIFY_STORE}/admin/api/2024-10/products/count.json?vendor=Sister+Parish&status=any" \
+ | /usr/bin/python3 -c "import json,sys; print(json.load(sys.stdin)['count'])")
+
+echo "Post-push Sister Parish count: $COUNT2"
+
+if (( COUNT2 >= 73 )); then
+ echo "All 73 landed — running backfill and self-unloading"
+ "$NODE_BIN" scripts/backfill_shopify_ids.js || true
+ /bin/launchctl unload "$PLIST" 2>/dev/null || true
+ /bin/rm -f "$PLIST"
+ echo "===== self-unloaded ====="
+else
+ echo "Only $COUNT2/73 landed (probably another daily-variant cap). Leaving plist in place for next Wednesday 02:00 PT."
+fi
← 81602d3 tick 3: normalize curly quotes in specs · extract dominant_h
·
back to Sister Parish Onboarding
·
tick 4: Shopify still 0 SP products · recorded 10 Backend-C 1c08599 →