← back to Pj Image Repair
TK-10467: add guarded rollback for PJ image canary (delete added image -> logo returns to pos1)
9a3f729e81ab69112e22f6b648cbb89a529d026a · 2026-09-13 15:11:59 -0700 · Steve
Files touched
Diff
commit 9a3f729e81ab69112e22f6b648cbb89a529d026a
Author: Steve <steve@designerwallcoverings.com>
Date: Sun Sep 13 15:11:59 2026 -0700
TK-10467: add guarded rollback for PJ image canary (delete added image -> logo returns to pos1)
---
rollback_images.py | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 63 insertions(+)
diff --git a/rollback_images.py b/rollback_images.py
new file mode 100644
index 0000000..5e171f4
--- /dev/null
+++ b/rollback_images.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python3
+"""
+TK-10467 — rollback for the PJ logo-hero image canary.
+Reads data/pj_write_journal.jsonl 'post' records (product_id + added_image_id) and DELETEs
+each image we added. Because the canary left the logo in place, deleting the one added
+webdamdb image returns the PhillipJeffriesLogo_*.png to position 1 — a clean, complete undo.
+
+DRY-RUN by default; requires --apply AND env CONFIRM_PJ_WRITE=1 (same gate as the writer).
+"""
+import os, sys, json, time, urllib.request, urllib.error
+
+HERE = os.path.dirname(os.path.abspath(__file__))
+JRN = os.path.join(HERE, "data", "pj_write_journal.jsonl")
+SHOP = "designer-laboratory-sandbox.myshopify.com"
+API = "2024-10"
+APPLY = "--apply" in sys.argv
+
+def token():
+ envp = os.path.expanduser("~/Projects/secrets-manager/.env")
+ vals = {}
+ with open(envp) as f:
+ for line in f:
+ for k in ("SHOPIFY_ADMIN_TOKEN", "SHOPIFY_FULL_ACCESS_TOKEN"):
+ if line.startswith(k + "="):
+ vals[k] = line.split("=", 1)[1].strip().strip('"').strip("'")
+ tok = vals.get("SHOPIFY_ADMIN_TOKEN") or vals.get("SHOPIFY_FULL_ACCESS_TOKEN")
+ if not tok:
+ raise SystemExit("no SHOPIFY_ADMIN_TOKEN / SHOPIFY_FULL_ACCESS_TOKEN")
+ return tok
+
+TOK = token()
+
+def api(method, path):
+ url = f"https://{SHOP}/admin/api/{API}/{path}"
+ req = urllib.request.Request(url, method=method,
+ headers={"X-Shopify-Access-Token": TOK, "Content-Type": "application/json"})
+ with urllib.request.urlopen(req, timeout=60) as r:
+ return r.getcode()
+
+def main():
+ if APPLY and os.environ.get("CONFIRM_PJ_WRITE") != "1":
+ print("REFUSING: --apply requires env CONFIRM_PJ_WRITE=1. Aborting.")
+ sys.exit(2)
+ posts = [json.loads(l) for l in open(JRN) if '"added_image_id"' in l]
+ print(f"mode={'APPLY' if APPLY else 'DRY-RUN'} rollback_records={len(posts)}")
+ ok = err = 0
+ for i, d in enumerate(posts, 1):
+ pid, iid = d["product_id"], d["added_image_id"]
+ if not APPLY:
+ print(f"[{i}] DRY would DELETE products/{pid}/images/{iid}.json ({d.get('dw_sku')})")
+ continue
+ try:
+ api("DELETE", f"products/{pid}/images/{iid}.json")
+ ok += 1
+ print(f"[{i}] OK deleted image {iid} on {pid} ({d.get('dw_sku')})")
+ except Exception as e:
+ err += 1
+ print(f"[{i}] ERR {pid}/{iid}: {e}")
+ time.sleep(0.4)
+ print(f"done ok={ok} err={err}" + ("" if APPLY else " (DRY-RUN)"))
+
+if __name__ == "__main__":
+ main()
← eb7a525 TK-10467: fix+harden PJ image writer (handle bug, apply path
·
back to Pj Image Repair
·
TK-10467: resolve Tier-2 cohort (194 handle-marked logo-hero 2f8529e →