release-firefox.ts

4.7 KB · raw

1#!/usr/bin/env bun2// scripts/release-firefox.ts3// One-command Firefox AMO release.4// Usage: bun run scripts/release-firefox.ts56import { execSync } from "child_process";7import { readFileSync, existsSync, mkdirSync } from "fs";8import { join } from "path";910const ROOT = process.cwd();1112function run(cmd: string, label?: string, env?: Record<string, string>) {13  const display = label ?? cmd;14  console.log(`\n▶ ${display}`);15  execSync(cmd, { stdio: "inherit", cwd: ROOT, env: { ...process.env, ...env } });16}1718function fail(msg: string): never {19  console.error(`\n✗ ${msg}`);20  process.exit(1);21}2223// ── Verify environment ────────────────────────────────────────────────────────2425if (!process.env.AMO_JWT_ISSUER) {26  fail("AMO_JWT_ISSUER not set. Add it to your shell profile and reload.");27}28if (!process.env.AMO_JWT_SECRET) {29  fail("AMO_JWT_SECRET not set. Add it to your shell profile and reload.");30}3132// ── Read version ──────────────────────────────────────────────────────────────3334const manifest = JSON.parse(35  readFileSync(join(ROOT, "manifest.firefox.json"), "utf8")36);37const version = manifest.version;38if (!version) fail("Could not read version from manifest.firefox.json");39console.log(`\n🍑 Peach Firefox — releasing v${version}`);4041// ── CI gate ───────────────────────────────────────────────────────────────────4243run("npm run ci", "Running CI gate");4445// ── Build ─────────────────────────────────────────────────────────────────────4647run("npm run build:firefox", `Building Firefox extension v${version}`);4849// ── Package source archive ────────────────────────────────────────────────────50// AMO requires source for any extension with minified/transpiled code.51// This zips everything a reviewer needs to build Peach from source.5253const sourceZip = `peach-source-${version}.zip`;54run(55  [56    "zip -r",57    sourceZip,58    "src",59    "scripts",60    "public",61    // PB-26-004: the shipped .wasm is transpiled from crypto-core/src/lib.rs —62    // AMO reviewers must be able to inspect and rebuild it (npm run63    // build:noise-core). Build cache and generated output are excluded.64    "crypto-core",65    "manifest.json",66    "manifest.firefox.json",67    "package.json",68    "bun.lock",69    "tsconfig.json",70    "vite.config.ts",71    "--exclude 'node_modules/*'",72    "--exclude 'dist-*/*'",73    "--exclude 'crypto-core/target/*'",74    "--exclude 'crypto-core/generated/*'",75    "--exclude '*.zip'",76    "--exclude '.DS_Store'",77    "--exclude '__MACOSX/*'",78  ].join(" "),79  "Packaging source archive for AMO"80);8182// ── Ensure artifacts dir ──────────────────────────────────────────────────────8384if (!existsSync(join(ROOT, "artifacts"))) {85  mkdirSync(join(ROOT, "artifacts"));86}8788// ── Sign and submit ───────────────────────────────────────────────────────────8990run(91  [92    "npx web-ext sign",93    "--source-dir dist-firefox",94    "--artifacts-dir artifacts",95    "--channel=listed",96  ].join(" "),97  "Signing and submitting to AMO",98  // web-ext reads WEB_EXT_API_KEY/WEB_EXT_API_SECRET from env — pass via99  // child env so the JWT credentials are not visible in the process table.100  {101    WEB_EXT_API_KEY: process.env.AMO_JWT_ISSUER!,102    WEB_EXT_API_SECRET: process.env.AMO_JWT_SECRET!,103  }104);105106// ── Cleanup zip ───────────────────────────────────────────────────────────────107108run(`trash ${sourceZip}`, "Cleaning up source zip");109110// ── Done ──────────────────────────────────────────────────────────────────────111112console.log(`\n✓ Peach Firefox v${version} submitted to AMO.`);113console.log("  Existing users will receive the update automatically.");114console.log("  Check AMO developer hub for review status.");115console.log("");