[object Object]

← back to Marketing Command Center

Add --dry-run readiness self-test to calendar snapshot publisher

092a26c5f835c92e9bf3251006cedc023024b473 · 2026-08-30 09:19:17 -0700 · steve

Regenerate + full validation gate, then stop before the rsync/ssh publish +
cache-bust so anyone can re-prove the job is healthy without touching Kamatera
prod. Additive, gated behind --dry-run/--check/DRY_RUN=1; the launchd plist
passes no args so the scheduled 6:30 PT run is unaffected. TK-10893.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit 092a26c5f835c92e9bf3251006cedc023024b473
Author: steve <steve@designerwallcoverings.com>
Date:   Sun Aug 30 09:19:17 2026 -0700

    Add --dry-run readiness self-test to calendar snapshot publisher
    
    Regenerate + full validation gate, then stop before the rsync/ssh publish +
    cache-bust so anyone can re-prove the job is healthy without touching Kamatera
    prod. Additive, gated behind --dry-run/--check/DRY_RUN=1; the launchd plist
    passes no args so the scheduled 6:30 PT run is unaffected. TK-10893.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 scripts/publish-calendar-snapshot.mjs | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/scripts/publish-calendar-snapshot.mjs b/scripts/publish-calendar-snapshot.mjs
index 9995312..816d243 100644
--- a/scripts/publish-calendar-snapshot.mjs
+++ b/scripts/publish-calendar-snapshot.mjs
@@ -40,6 +40,11 @@ const PUBLIC_URL = 'https://marketing.designerwallcoverings.com/api/calendars/ev
 const AUTH = `${process.env.MCC_HTTP_USER || 'admin'}:${process.env.MCC_HTTP_PASS || 'DW2024!'}`;
 const MIN_ITEMS = parseInt(process.env.SNAP_MIN_ITEMS, 10) || 15000;
 const CNCP_URL = process.env.CNCP_URL || 'http://127.0.0.1:3333/api/parking-lot';
+// Readiness self-test: regenerate + run the full validation gate, then STOP before
+// the rsync/ssh publish + cache-bust. Lets anyone re-prove the job is healthy without
+// touching Kamatera prod. Enabled via `--dry-run` (or `--check`) / DRY_RUN=1. The
+// launchd plist passes no args, so the scheduled run is unaffected.
+const DRY_RUN = process.argv.includes('--dry-run') || process.argv.includes('--check') || process.env.DRY_RUN === '1';
 
 const log = (m) => console.log(`[publish-calendar-snapshot] ${new Date().toISOString()} ${m}`);
 
@@ -89,6 +94,11 @@ async function main() {
   if (first !== expected) fail(`first activation date ${first} !== tomorrow ${expected} (window not anchored to today+1)`);
   log(`validation PASS — activation_live=true, items=${items.length}, window ${first} … ${items[items.length - 1]?.date}`);
 
+  if (DRY_RUN) {
+    log('DRY-RUN — readiness gate PASSED; skipping publish + cache-bust (prod untouched).');
+    return;
+  }
+
   // 3. atomic publish (rsync -> remote temp, then ssh mv), retry once on transient failure
   const publish = () => {
     execFileSync(RSYNC, ['-az', '--timeout=60', SNAPSHOT, `${REMOTE_HOST}:${REMOTE_TMP}`], { stdio: 'inherit' });

← d54ceab auto-data-snapshot: 2026-08-30T09:05:58 (4 data files) — cta  ·  back to Marketing Command Center  ·  prove every Quick Post control across browsers d5e756d →