← back to Shopify Sample Shipping
publish-theme.mjs
42 lines
#!/usr/bin/env node
// TK-11333 — publish the "DW Sample-Shipping DEV" theme LIVE. Steve runs this (--apply).
// Captures the currently-published theme id FIRST so rollback is one command.
// Uses a minimal userErrors-only selection (no theme/newTheme field ambiguity).
import fs from 'node:fs';
import { query } from './query.mjs';
const APPLY = process.argv.includes('--apply');
const REC = new URL('./verification/theme-publish.json', import.meta.url);
const DEV_NAME = 'DW Sample-Shipping DEV';
const themes = (await query(`{themes(first:30){nodes{id name role}}}`)).themes.nodes;
const curMain = themes.find(t => t.role === 'MAIN');
const dev = themes.filter(t => t.name === DEV_NAME).sort((a,b)=>b.id.localeCompare(a.id))[0];
console.log('current LIVE (MAIN):', curMain ? `${curMain.name} ${curMain.id}` : 'none');
console.log('DEV to publish :', dev ? `${dev.name} ${dev.id} [${dev.role}]` : 'NOT FOUND');
if (!dev) { console.error('⛔ DEV theme not found — run ~/theme first.'); process.exit(1); }
if (dev.role === 'MAIN') { console.log('DEV is already MAIN — nothing to do.'); process.exit(0); }
if (!APPLY) {
console.log(`\nDRY-RUN. --apply will publish ${dev.name} LIVE (previous MAIN "${curMain?.name}" becomes an unpublished backup → rollback: ~/publishrollback).`);
process.exit(0);
}
// record rollback target BEFORE publishing
fs.writeFileSync(REC, JSON.stringify({ at: new Date().toISOString(), publishedThemeId: dev.id, publishedName: dev.name, previousMainId: curMain?.id, previousMainName: curMain?.name }, null, 2) + '\n');
const r = (await query(`mutation($id:ID!){themePublish(id:$id){userErrors{field message}}}`, { id: dev.id })).themePublish;
if (r.userErrors?.length) { console.error('themePublish errors:', JSON.stringify(r.userErrors)); process.exit(1); }
// verify
const after = (await query(`{themes(first:30){nodes{id name role}}}`)).themes.nodes;
const nowMain = after.find(t => t.role === 'MAIN');
console.log('\n✅ PUBLISHED. LIVE theme is now:', nowMain ? `${nowMain.name} ${nowMain.id}` : '(?)');
console.log(`Rollback anytime: ~/publishrollback (re-publishes "${curMain?.name}")`);
try {
const { execSync } = await import('node:child_process');
execSync(`node ${process.env.HOME}/.claude/yolo-queue/executed-reversible/log-exec.mjs --agent vp-dw-commerce --ticket TK-11333 ` +
`--action ${JSON.stringify('published "' + dev.name + '" LIVE (sample-shipping engine)')} --blast 1 ` +
`--undo ${JSON.stringify('cd ~/Projects/shopify-sample-shipping && node publish-rollback.mjs --apply')} ` +
`--verify ${JSON.stringify('shopify theme list')}`, { stdio: 'inherit' });
} catch (e) { console.log('(ledger note skipped:', e.message, ')'); }