← back to Designerwallcoverings
scripts/anna-french-rolls/af-noroll-resume.sh
57 lines
#!/bin/bash
# af-noroll-resume.sh — daily, self-terminating build of the missing Anna French (DWAA)
# "Sold Per Roll" variants for the 131 sample-only products the reprice logged as no-roll.
#
# af-build-noroll.js prices each at the new single-roll basis (retail x0.45/0.65/0.85),
# self-heals the Shopify default-variant-consumes-sample trap, skips Title-option products,
# and aborts cleanly on the daily variant-creation cap (resumable next morning).
#
# Runs at 5:45am — BEFORE com.steve.sample-split-resume (6:15) and com.steve.schu-build-resume
# (7:00) — so its small 121-variant job grabs cap headroom first and finishes in ~1 day, then
# boots itself out and hands the full daily cap back to the longer-running jobs.
set -u
export PATH="/usr/local/bin:/opt/homebrew/bin:/opt/homebrew/opt/postgresql@14/bin:/usr/bin:/bin"
cd /Users/macstudio3/Projects/designerwallcoverings || exit 1
DIR=scripts/anna-french-rolls
BUDGET="$HOME/Projects/designerwallcoverings/scripts/variant-budget/budget.cjs"
LOG=/tmp/af-noroll-resume-$(date +%Y%m%d).log
{
echo "=== af-noroll build $(date) ==="
# Shared kill-switch (2026-06-19): this job previously ignored it entirely.
if [ -f "$HOME/.dw-fixer-stop" ]; then echo "kill-switch present — skip"; echo "=== done $(date) ==="; exit 0; fi
# Shared variant-budget gate (2026-06-19): af-build-noroll.js adds 1 roll variant per product,
# so REPRICE_LIMIT is a variant count. Draw from the live 'upload' pool (== global ~864/day
# Shopify ceiling minus osborne) and clamp the build to the grant so the whole writer fleet
# can't blow the daily cap. take returns min(req, upload-remaining, global-remaining); 0 → skip.
GRANT=$(node "$BUDGET" take upload 131 2>/dev/null || echo 131)
if [ "${GRANT:-0}" -lt 1 ]; then echo "no variant budget this run (grant=$GRANT) — exit clean"; echo "=== done $(date) ==="; exit 0; fi
echo "budget grant=$GRANT variants — building (REPRICE_LIMIT=$GRANT)"
AF_OUT=$(COMMIT=1 REPRICE_LIMIT="$GRANT" node "$DIR/af-build-noroll.js" 2>&1)
echo "$AF_OUT"
# ── refund the unused upload grant (budget-integrity, 2026-06-20; DTD verdict A) ──
# We took GRANT variants UP FRONT (== REPRICE_LIMIT) but af-build-noroll.js adds only 1 roll variant
# per product actually built. It ALWAYS prints a trailing JSON tally with "made": N (even on the cap
# break), so N is reliable; a cap/empty slot builds 0 (refund whole grant), a partial slot fewer.
# Without this the unused grant silently drains the shared 864 upload slice. GUARD: refund ONLY when
# the "made": N field was found (AF_MADE non-empty) — a crash that printed no tally keeps its debit
# (conservative; never over-refunds → never over-grants against Shopify's real cap).
AF_MADE=$(printf '%s' "$AF_OUT" | grep -oE '"made":[[:space:]]*[0-9]+' | grep -oE '[0-9]+' | tail -1)
if [ -n "$AF_MADE" ]; then
AF_REFUND=$(( GRANT - AF_MADE )) # 1 roll variant per product built
if [ "$AF_REFUND" -gt 0 ]; then
AF_GOT=$(node "$BUDGET" refund upload "$AF_REFUND" 2>/dev/null || echo 0)
echo "budget refund: grant=$GRANT used=$AF_MADE (built×1) → refunded $AF_GOT upload variants"
fi
fi
echo "--- remaining check ---"
NOROLL=$(grep -c . "$DIR/out/af-reprice-noroll.jsonl" 2>/dev/null || echo 0)
DONE=$(grep -c . "$DIR/out/af-build-noroll-done.txt" 2>/dev/null || echo 0)
echo "done=$DONE / noroll=$NOROLL"
if [ "$DONE" -ge "$NOROLL" ] && [ "$NOROLL" -gt 0 ]; then
echo "AF NO-ROLL BUILD COMPLETE — self-unloading com.steve.af-noroll-resume"
launchctl bootout gui/$(id -u)/com.steve.af-noroll-resume 2>/dev/null
fi
echo "=== done $(date) ==="
} >> "$LOG" 2>&1