#!/usr/bin/env bun // scripts/release.ts // One command to release Peach to both Chrome Web Store and Firefox AMO. // Usage: npm run release // npm run release:chrome (Chrome only — skips AMO) // // Required environment variables (set from your secret store, then export // in the release shell — PB-26-013: never written to a shell profile): // CWS_CLIENT_ID, CWS_CLIENT_SECRET, CWS_REFRESH_TOKEN, CWS_EXTENSION_ID, // PUBLISHER_ID // AMO_JWT_ISSUER, AMO_JWT_SECRET (not needed for --chrome-only) // // PB-26-211: all tools are resolved from node_modules/.bin — run // `bun install --frozen-lockfile` before invoking release. import { preflight, readVersion, runCommand, safeEnv, uploadChrome, packageSourceArchive, signFirefox, } from "./release-lib"; const CHROME_ONLY = process.argv.includes("--chrome-only"); const BOLD = "\x1b[1m"; const DIM = "\x1b[2m"; const ACCENT = "\x1b[38;5;208m"; const GREEN = "\x1b[32m"; const RESET = "\x1b[0m"; function success(msg: string) { console.log(`${GREEN}✓ ${msg}${RESET}`); } // ─── Header ────────────────────────────────────────────────────────────────── console.clear(); console.log(""); console.log(`${ACCENT}${BOLD} ░░ peach release ░░${RESET}`); console.log(""); // ─── Preflight ─────────────────────────────────────────────────────────────── preflight(); const version = readVersion("manifest.json"); const targets = CHROME_ONLY ? "Chrome" : "Chrome + Firefox"; console.log(`${BOLD}Releasing Peach v${version} to ${targets}${RESET}`); console.log(`${DIM}Stores update automatically for existing users.${RESET}`); // ─── CI gate ────────────────────────────────────────────────────────────────── // PB-26-211: CI runs with a minimal safe environment — no store credentials. runCommand("npm", ["run", "ci"], { label: "Running CI gate", env: safeEnv(), }); success("All tests pass"); // ─── Build ──────────────────────────────────────────────────────────────────── // PB-26-211: build children receive no store credentials. if (CHROME_ONLY) { runCommand("npm", ["run", "build:chrome"], { label: "Building Chrome target", env: safeEnv(), }); } else { runCommand("npm", ["run", "build"], { label: "Building all targets (Chrome + Firefox)", env: safeEnv(), }); } success("Build complete"); runCommand("npm", ["run", "test:sync:cross-client"], { label: "Running cross-client sync gate", env: safeEnv(), }); // ─── Chrome release ─────────────────────────────────────────────────────────── // PB-26-211: CWS credentials are read and validated here, immediately before // upload. They are passed only to the Chrome upload child, never to build or // CI children. console.log(`\n${ACCENT}${BOLD}Chrome Web Store${RESET}`); uploadChrome(version); success(`Chrome v${version} submitted — review typically takes minutes to hours`); // ─── Firefox release ────────────────────────────────────────────────────────── // PB-26-211: AMO credentials are read and validated here, immediately before // signing. They are passed only to the web-ext child, never to Chrome tooling // or build children. if (!CHROME_ONLY) { console.log(`\n${ACCENT}${BOLD}Firefox Add-ons (AMO)${RESET}`); const sourceZip = packageSourceArchive(version); signFirefox(sourceZip); success(`Firefox v${version} submitted with source archive retained in artifacts/`); } // ─── Done ───────────────────────────────────────────────────────────────────── console.log(""); console.log(`${ACCENT}${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}`); console.log(`${ACCENT}${BOLD} Peach v${version} released to ${targets}.${RESET}`); console.log(`${ACCENT}${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}`); console.log(""); if (!CHROME_ONLY) { console.log(` Chrome: under review — existing users update automatically`); console.log(` Firefox: under review — existing users update automatically`); } else { console.log(` Chrome: under review — existing users update automatically`); } console.log(""); console.log(`${DIM}Check status:${RESET}`); console.log(` Chrome: https://chrome.google.com/webstore/devconsole`); if (!CHROME_ONLY) { console.log(` Firefox: https://addons.mozilla.org/developers/`); } console.log("");