[object Object]

← back to Wolfgordon Crawl

Add --phase1 (variant-free update+archive) + --new-only/--max staggered Phase 2

4be3ecc617d9372496e2150095e604663edfd194 · 2026-06-19 10:20:44 -0700 · Steve

Files touched

Diff

commit 4be3ecc617d9372496e2150095e604663edfd194
Author: Steve <steve@designerwallcoverings.com>
Date:   Fri Jun 19 10:20:44 2026 -0700

    Add --phase1 (variant-free update+archive) + --new-only/--max staggered Phase 2
---
 push-shopify.js | 54 ++++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 40 insertions(+), 14 deletions(-)

diff --git a/push-shopify.js b/push-shopify.js
index af917f1..dd0aa11 100644
--- a/push-shopify.js
+++ b/push-shopify.js
@@ -40,6 +40,15 @@ const THROTTLE_MS = 500; // ~2 req/s
 const argv = process.argv.slice(2);
 const APPLY = argv.includes('--apply');
 const CANARY = argv.includes('--canary');
+// Phase 1 = updates + archives only, and VARIANT-FREE (no Sample variant added
+// to existing products) so it never touches the daily variant-create cap.
+const PHASE1 = argv.includes('--phase1');
+// Phase 2 = create net-new products (new + draft) only; staggered by variant cap.
+const NEW_ONLY = argv.includes('--new-only');
+const MAX = (() => {
+  const i = argv.indexOf('--max');
+  return i !== -1 && argv[i + 1] ? parseInt(argv[i + 1], 10) : null;
+})();
 const LIMIT = (() => {
   const i = argv.indexOf('--limit');
   return i !== -1 && argv[i + 1] ? parseInt(argv[i + 1], 10) : null;
@@ -346,19 +355,23 @@ async function updateProduct(item) {
   if (ue && ue.length) throw new Error('variantsBulkUpdate: ' + JSON.stringify(ue));
 
   // 2. ensure a Sample variant exists ({DW_SKU}-Sample @ $4.25, untracked).
-  const sampleSku = `${target.dw_sku}-Sample`;
-  // (canary: existing legacy products are single-variant; add the sample.)
-  await gql(`
-    mutation($pid:ID!,$variants:[ProductVariantsBulkInput!]!){
-      productVariantsBulkCreate(productId:$pid, variants:$variants){
-        productVariants{ id sku } userErrors{ field message }
-      }
-    }`, {
-    pid: live.productId,
-    variants: [{ price: SAMPLE_PRICE, inventoryItem: { sku: sampleSku, tracked: false },
-                 inventoryPolicy: 'CONTINUE',
-                 optionValues: [{ optionName: 'Title', name: 'Sample' }] }],
-  }).catch(e => console.error('    sample-variant warn:', e.message));
+  //    PHASE 1 is VARIANT-FREE: creating a Sample variant consumes the daily
+  //    variant-create cap, which Phase 2's ~10,400-variant rollout needs. So
+  //    skip the sample-create entirely in Phase 1 (Steve's explicit rule).
+  if (!PHASE1) {
+    const sampleSku = `${target.dw_sku}-Sample`;
+    await gql(`
+      mutation($pid:ID!,$variants:[ProductVariantsBulkInput!]!){
+        productVariantsBulkCreate(productId:$pid, variants:$variants){
+          productVariants{ id sku } userErrors{ field message }
+        }
+      }`, {
+      pid: live.productId,
+      variants: [{ price: SAMPLE_PRICE, inventoryItem: { sku: sampleSku, tracked: false },
+                   inventoryPolicy: 'CONTINUE',
+                   optionValues: [{ optionName: 'Title', name: 'Sample' }] }],
+    }).catch(e => console.error('    sample-variant warn:', e.message));
+  }
 
   // 3. images ADD/diff — add any catalog image not already on the product.
   const have = new Set((live.images || []).map(u => u.split('?')[0]));
@@ -410,8 +423,10 @@ function pickCanary(plan) {
 // ---------- main ----------
 async function main() {
   console.log('='.repeat(74));
+  const phaseTag = PHASE1 ? '  [PHASE1: update+archive, variant-free]'
+                  : NEW_ONLY ? `  [PHASE2: new-only${MAX != null ? `, max ${MAX}` : ''}]` : '';
   console.log(`  WOLF GORDON -> SHOPIFY PUSHER   mode=${APPLY ? 'APPLY (LIVE WRITES)' : 'DRY-RUN'}` +
-              `${CANARY ? '  [CANARY]' : ''}${LIMIT ? `  [limit ${LIMIT}]` : ''}`);
+              `${CANARY ? '  [CANARY]' : ''}${phaseTag}${LIMIT ? `  [limit ${LIMIT}]` : ''}`);
   console.log(`  store=${SHOP}  api=${API}  token=...${TOKEN.slice(-4)}`);
   console.log('='.repeat(74));
 
@@ -429,6 +444,17 @@ async function main() {
   let work;
   if (CANARY) {
     work = pickCanary(plan);
+  } else if (PHASE1) {
+    // Phase 1: re-price/re-SKU matched live products + archive discontinued.
+    // ZERO new variants (updates touch existing variants; sample-create skipped).
+    work = { new: [], update: plan.update, draft: [], archive: plan.archive };
+  } else if (NEW_ONLY) {
+    // Phase 2: create net-new only, capped to today's variant budget (--max
+    // products; each = 2 variants). draft (quote-only) counts toward the cap too.
+    const cap = MAX != null ? MAX : (LIMIT != null ? LIMIT : plan.new.length + plan.draft.length);
+    const newAdds = plan.new.slice(0, cap);
+    const draftAdds = plan.draft.slice(0, Math.max(0, cap - newAdds.length));
+    work = { new: newAdds, update: [], draft: draftAdds, archive: [] };
   } else if (LIMIT) {
     work = { new: plan.new.slice(0, LIMIT), update: [], draft: [], archive: [] };
   } else {

← e28d26a Harden pusher: graceful defer on Shopify daily variant-creat  ·  back to Wolfgordon Crawl  ·  Add Phase-2 resumable daily-push.sh driver + launchd plist ( d88890b →