From 97a3a1bc4f9bea5fa41feef1e2ba46ec3ed04d23 Mon Sep 17 00:00:00 2001 From: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com> Date: Sun, 28 Jun 2026 16:04:57 -0700 Subject: [PATCH 1/2] fix(cloud): strip DO migrations from preview deploy config so PR builds stop failing Preview (non-main) Workers Builds deploy via 'wrangler versions upload', which rejects any config containing Durable Object migrations (error 10211). Previews share production's already-applied DO state, so they neither need nor can apply migrations. build.mjs strips 'migrations' from the generated dist/server/wrangler.json on non-main CI branches; main keeps them and applies on the real deploy. Fail-safe: only strips on a confirmed non-main CI branch, never on a production deploy. Leaves the orphaned KV McpSessionDO + its stub export in place (harmless, unbound); not worth a delete migration whose own preview build can't pass. --- apps/cloud/scripts/build.mjs | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/apps/cloud/scripts/build.mjs b/apps/cloud/scripts/build.mjs index aeae418e3..43d7be99e 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,26 @@ 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); + 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)`, + ); + } +} From 243e6c01bdc64654e7961c61cf3e5d4f20270237 Mon Sep 17 00:00:00 2001 From: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com> Date: Sun, 28 Jun 2026 16:08:33 -0700 Subject: [PATCH 2/2] chore(cloud): suppress no-json-parse on the build script's wrangler-config read --- apps/cloud/scripts/build.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/cloud/scripts/build.mjs b/apps/cloud/scripts/build.mjs index 43d7be99e..1ee4e283b 100644 --- a/apps/cloud/scripts/build.mjs +++ b/apps/cloud/scripts/build.mjs @@ -45,6 +45,7 @@ for (const step of steps) { 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;