← back to Fb21 Mfr Images
finish_fb21.sh
62 lines
#!/bin/bash
# Finish FB21 reactivation: convert $0 Default variant -> Size:Sample @ $4.25 (sku DWK-<dwsku>-Sample),
# then publish to Online Store + Google & YouTube. Matches reference Koroseal contract product.
# Steve-approved 2026-07-14. FB21-05 handled separately (re-archive).
set -uo pipefail
TOKEN="$(grep '^SHOPIFY_ADMIN_TOKEN=' ~/Projects/secrets-manager/.env | cut -d= -f2)"
BASE="https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-10"
GQL="https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-10/graphql.json"
H="X-Shopify-Access-Token: $TOKEN"
PUB_ONLINE="gid://shopify/Publication/22208643184"
PUB_GOOGLE="gid://shopify/Publication/29646651457"
MODE="${1:-canary}" # canary = FB21-01 only ; all = the 17 (FB21-05 excluded)
# mfr:productid:dwsku (FB21-05 intentionally omitted)
PAIRS="FB21-01:7766998286387:DWK-304096
FB21-02:7766998450227:DWK-304015
FB21-03:7766998482995:DWK-303997
FB21-04:7766998515763:DWK-303998
FB21-06:7766998712371:DWK-303999
FB21-07:7766998745139:DWK-304032
FB21-08:7766998253619:DWK-304017
FB21-09:7766998908979:DWK-304000
FB21-10:7766998941747:DWK-304166
FB21-11:7766999105587:DWK-304155
FB21-12:7766999138355:DWK-303921
FB21-13:7766999334963:DWK-304001
FB21-14:7766999498803:DWK-304002
FB21-15:7766999531571:DWK-304003
FB21-16:7766999695411:DWK-304136
FB21-17:7766999728179:DWK-304137
FB21-18:7766999892019:DWK-303965"
[ "$MODE" = "canary" ] && PAIRS="$(echo "$PAIRS" | head -1)"
echo "$PAIRS" | while IFS=: read -r sku id dwsku; do
[ -z "$sku" ] && continue
# current variant + option ids
read -r optid varid < <(curl -s "$BASE/products/$id.json?fields=options,variants" -H "$H" | python3 -c 'import sys,json
p=json.load(sys.stdin)["product"]; print(p["options"][0]["id"], p["variants"][0]["id"])')
# 1) rename option Title->Size, convert variant to Sample @ 4.25 with sku
body=$(python3 - "$id" "$optid" "$varid" "$dwsku" <<'PY'
import json,sys
pid,optid,varid,dwsku=sys.argv[1:5]
print(json.dumps({"product":{"id":int(pid),
"options":[{"id":int(optid),"name":"Size"}],
"variants":[{"id":int(varid),"option1":"Sample","price":"4.25","sku":f"{dwsku}-Sample",
"inventory_management":"shopify","inventory_policy":"continue","taxable":True,"requires_shipping":True}]}}))
PY
)
r=$(curl -s -o /tmp/ff.json -w "%{http_code}" -X PUT "$BASE/products/$id.json" -H "$H" -H "Content-Type: application/json" -d "$body")
ok=$(python3 -c 'import json;d=json.load(open("/tmp/ff.json"));v=d.get("product",{}).get("variants",[{}])[0];print(v.get("title"),v.get("price"),v.get("sku"))' 2>/dev/null)
echo "[$sku] variant PUT HTTP $r -> $ok"
sleep 0.4
# 2) publish to Online Store via legacy REST flag (publishablePublish is a no-op for this app).
# Google & YouTube left to the standing google-merchant-agent (documented GMC $4.25 gate).
pr=$(curl -s -o /tmp/ffp.json -w "%{http_code}" -X PUT "$BASE/products/$id.json" -H "$H" -H "Content-Type: application/json" -d "{\"product\":{\"id\":$id,\"published\":true,\"published_scope\":\"global\"}}")
pat=$(python3 -c 'import json;print(json.load(open("/tmp/ffp.json")).get("product",{}).get("published_at"))' 2>/dev/null)
echo "[$sku] publish OnlineStore HTTP $pr -> published_at=$pat"
sleep 0.5
done
echo "DONE ($MODE)"