[object Object]

← back to Dw Domain Fleet

deploy-articles.sh: fail-flag + full-fleet verify so a partial deploy exits non-zero

5e945b3d06fe0e490c037cd46ed6fbfa2e839725 · 2026-09-16 09:44:39 -0700 · Steve Abrams

Review-fix: rsync/pm2/save failures now set fail=1; run returns it and the
script does exit "${PIPESTATUS[0]}" so the status survives the | tee. Verify
widened from 4 hardcoded sentinels to all 43 sites (/articles 200 + non-empty);
multi-word content sentinel matched token-by-token to kill false OLD. POSIX-sh safe.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TJ94XCE5W2H1FXU2AqudVG

Files touched

Diff

commit 5e945b3d06fe0e490c037cd46ed6fbfa2e839725
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed Sep 16 09:44:39 2026 -0700

    deploy-articles.sh: fail-flag + full-fleet verify so a partial deploy exits non-zero
    
    Review-fix: rsync/pm2/save failures now set fail=1; run returns it and the
    script does exit "${PIPESTATUS[0]}" so the status survives the | tee. Verify
    widened from 4 hardcoded sentinels to all 43 sites (/articles 200 + non-empty);
    multi-word content sentinel matched token-by-token to kill false OLD. POSIX-sh safe.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01TJ94XCE5W2H1FXU2AqudVG
---
 scripts/deploy-articles.sh | 68 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 68 insertions(+)

diff --git a/scripts/deploy-articles.sh b/scripts/deploy-articles.sh
new file mode 100644
index 0000000..3aa21ea
--- /dev/null
+++ b/scripts/deploy-articles.sh
@@ -0,0 +1,68 @@
+#!/usr/bin/env bash
+# deploy-articles.sh — TK-11428: push de-mail-merged article content (43 monetize sites)
+# + render.js to Kamatera prod, restart the dwf-* procs, verify. Content-only (no --delete).
+# Run:  sh scripts/deploy-articles.sh    (tees full output to logs/deploy-last.log)
+LOCAL="$HOME/Projects/dw-domain-fleet"
+LOG="$LOCAL/logs/deploy-last.log"
+mkdir -p "$LOCAL/logs"
+
+run() {
+  set -uo pipefail
+  HOST=root@45.61.58.125
+  REMOTE=/root/public-projects/dw-domain-fleet
+  SSHO="-oBatchMode=yes -oConnectTimeout=15 -oStrictHostKeyChecking=accept-new"
+  fail=0   # any rsync/restart/save failure, any stale-content or down-site flips this -> non-zero exit
+
+  echo "== START $(date) =="
+
+  echo "==> rsync sites/ (no --delete)"
+  if rsync -az -e "ssh $SSHO" --exclude node_modules --exclude .git --exclude 'logs/*' --exclude '.env*' \
+    "$LOCAL/sites/" "$HOST:$REMOTE/sites/"; then echo "  rsync sites OK"; else echo "  rsync sites FAILED rc=$?"; fail=1; fi
+
+  echo "==> rsync render.js"
+  if rsync -az -e "ssh $SSHO" "$LOCAL/shared/render.js" "$HOST:$REMOTE/shared/render.js"; then echo "  rsync render OK"; else echo "  rsync render FAILED rc=$?"; fail=1; fi
+
+  echo "==> pm2 restart dwf-* in batches of 8"
+  batch=""; n=0
+  for f in "$LOCAL"/sites/*.json; do
+    b=$(basename "$f" .json); batch="$batch dwf-$b"; n=$((n+1))
+    if [ "$n" -ge 8 ]; then
+      echo "  -- batch:$batch"
+      ssh $SSHO "$HOST" "cd $REMOTE && pm2 restart $batch 2>&1 | tail -3" || { echo "    ssh rc=$?"; fail=1; }
+      batch=""; n=0
+    fi
+  done
+  if [ -n "$batch" ]; then
+    echo "  -- batch:$batch"
+    ssh $SSHO "$HOST" "cd $REMOTE && pm2 restart $batch 2>&1 | tail -3" || { echo "    ssh rc=$?"; fail=1; }
+  fi
+  ssh $SSHO "$HOST" "pm2 save 2>&1 | tail -1" || { echo "  save ssh rc=$?"; fail=1; }
+
+  # Deep content sentinels: prove NEW (de-mail-merged) content is actually live.
+  # Space-separated tokens are matched individually so an HTML tag / line break
+  # between the words of a phrase can't produce a false OLD.
+  echo "==> verify NEW content live (deep sentinels)"
+  for pair in "fireratedwallcovering.com:flame-spread" "wallpaperfromthe80s.com:Memphis" "asseeninla.com:Pacific+Design" "1800wallcoverings.com:perimeter"; do
+    d=${pair%%:*}; needle=${pair##*:}
+    body=$(curl -s -m 15 "https://$d/articles")
+    ok=1
+    for tok in $(echo "$needle" | tr '+' ' '); do echo "$body" | grep -qi -- "$tok" || ok=0; done
+    if [ "$ok" -eq 1 ]; then echo "  NEW ok  $d"; else echo "  OLD !!  $d"; fail=1; fi
+  done
+
+  # Broad liveness: every deployed site's /articles must answer 200 with a non-trivial
+  # body after the restart, so a site that crashed on reload is caught (not just the 4).
+  echo "==> verify all sites reachable (/articles 200 + non-empty)"
+  for f in "$LOCAL"/sites/*.json; do
+    d=$(basename "$f" .json)
+    resp=$(curl -s -o /dev/null -m 15 -w '%{http_code} %{size_download}' "https://$d/articles")
+    code=${resp%% *}; size=${resp##* }
+    if [ "$code" = "200" ] && [ "${size:-0}" -gt 500 ]; then echo "  up   $d ($code, ${size}b)"; else echo "  DOWN $d ($code, ${size:-0}b)"; fail=1; fi
+  done
+
+  echo "== END $(date) — fail=$fail =="
+  return "$fail"
+}
+
+run 2>&1 | tee "$LOG"
+exit "${PIPESTATUS[0]}"

← e5dcb36 content drip: +4 fresh article(s) — etciemurals.com, fabricf  ·  back to Dw Domain Fleet  ·  auto-data-snapshot: 2026-09-23T14:48:42 (1 data files) — dat fc5a721 →