diff --git a/apps/cloud/scripts/build.mjs b/apps/cloud/scripts/build.mjs index aeae418e3..1ee4e283b 100644 --- a/apps/cloud/scripts/build.mjs +++ b/apps/cloud/scripts/build.mjs @@ -9,7 +9,7 @@ import { spawnSync } from "node:child_process"; import { randomBytes } from "node:crypto"; -import { rmSync } from "node:fs"; +import { readFileSync, rmSync, writeFileSync } from "node:fs"; if (!process.env.VITE_PUBLIC_ANALYTICS_PATH) { process.env.VITE_PUBLIC_ANALYTICS_PATH = randomBytes(4).toString("hex"); @@ -32,3 +32,27 @@ for (const step of steps) { process.exit(result.status ?? 1); } } + +// Preview (non-production) Cloudflare Workers Builds deploy via `wrangler versions +// upload`, which REJECTS any config containing an unapplied Durable Object +// migration (error 10211 — "migrations must be applied via a non-versioned +// deployment"). Preview versions share production's already-applied DO state, so +// they neither need nor can apply migrations. Strip `migrations` from the +// generated deploy config on non-`main` CI branches so PR preview builds stop +// failing. Production (`main`) keeps migrations and applies them on the real, +// non-versioned deploy. Fail-safe: only triggers on a confirmed non-`main` CI +// branch, so it can never drop migrations from a production deploy. +const ciBranch = process.env.WORKERS_CI_BRANCH; +if (process.env.WORKERS_CI === "1" && ciBranch && ciBranch !== "main") { + const cfgUrl = new URL("../dist/server/wrangler.json", import.meta.url); + // oxlint-disable-next-line executor/no-json-parse -- build script, not domain code; wrangler emits plain JSON + const cfg = JSON.parse(readFileSync(cfgUrl, "utf8")); + if (Array.isArray(cfg.migrations) && cfg.migrations.length > 0) { + delete cfg.migrations; + writeFileSync(cfgUrl, JSON.stringify(cfg)); + console.log( + `[build] preview branch '${ciBranch}': stripped Durable Object migrations from ` + + `dist/server/wrangler.json (versions upload cannot apply migrations)`, + ); + } +}