diff --git a/.changeset/workers-builds-override-name.md b/.changeset/workers-builds-override-name.md new file mode 100644 index 00000000..8d2eb56a --- /dev/null +++ b/.changeset/workers-builds-override-name.md @@ -0,0 +1,5 @@ +--- +"@cloudhal/cli": patch +--- + +The Deploy to Cloudflare button deploys the admin Worker under its own name. Workers Builds sets `WRANGLER_CI_OVERRIDE_NAME` to the Worker a build is connected to, and wrangler then deploys every config under that name, so the admin Worker overwrote the site Worker (the site's address served Studio). `cloudhal deploy` no longer passes `WRANGLER_CI_OVERRIDE_NAME` or `WRANGLER_CI_MATCH_TAG` to wrangler; it names each Worker itself. diff --git a/docs/guides/deploy-button.md b/docs/guides/deploy-button.md index 6035d74b..c1dd8b65 100644 --- a/docs/guides/deploy-button.md +++ b/docs/guides/deploy-button.md @@ -43,3 +43,7 @@ Start from `npm create cloudhal@latest`, then: - commit `cloudhal.json` and a root `wrangler.jsonc` that names the site Worker, a `DB` D1 database (placeholder id `00000000-0000-0000-0000-000000000000`) and a `BLOBS` R2 bucket - remove the `build` script (Workers Builds would run it before `deploy`), keep `"deploy": "cloudhal deploy"` - commit a lockfile and a `.node-version` of `24`. The CLI runs on Node 24. + +## Before 0.3.2: the site Worker shows Studio + +Workers Builds sets `WRANGLER_CI_OVERRIDE_NAME` to the Worker a build is connected to. Before 0.3.2, `cloudhal deploy` passed it on to wrangler, so the admin Worker was uploaded under the site Worker's name. The site's address then served Studio, and no `-admin` Worker existed. To fix a deployment made that way, bump `@cloudhal/*` in your copy of the template to 0.3.2 or later and push. The next build deploys both Workers under their own names. diff --git a/packages/cli/src/cloudflare/wrangler.ts b/packages/cli/src/cloudflare/wrangler.ts index 6e9983f7..a044dff2 100644 --- a/packages/cli/src/cloudflare/wrangler.ts +++ b/packages/cli/src/cloudflare/wrangler.ts @@ -70,7 +70,17 @@ export function wranglerRunner( return async (args, { cwd, quiet }) => { const dir = await mkdtemp(path.join(os.tmpdir(), "cloudhal-wrangler-")); const outputFile = path.join(dir, "output.ndjson"); - const { VITEST: _v, NODE_ENV: _n, ...env } = process.env; + // Workers Builds sets WRANGLER_CI_OVERRIDE_NAME (and WRANGLER_CI_MATCH_TAG) to the one Worker + // the build is connected to; wrangler then deploys every config under that name. `cloudhal + // deploy` names each Worker itself (the site keeps the connected name), so the admin Worker + // would otherwise overwrite the site. Seen on the first Deploy to Cloudflare button run. + const { + VITEST: _v, + NODE_ENV: _n, + WRANGLER_CI_OVERRIDE_NAME: _ciName, + WRANGLER_CI_MATCH_TAG: _ciTag, + ...env + } = process.env; try { const result = await new Promise<{ code: number; stdout: string; stderr: string }>( (resolve) => { diff --git a/packages/cli/test/wrangler-ci-env.test.ts b/packages/cli/test/wrangler-ci-env.test.ts new file mode 100644 index 00000000..047ff409 --- /dev/null +++ b/packages/cli/test/wrangler-ci-env.test.ts @@ -0,0 +1,35 @@ +import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises"; +import os from "node:os"; +import path from "node:path"; +import { afterAll, describe, expect, it } from "vitest"; +import { wranglerRunner } from "../src/cloudflare/wrangler.ts"; + +describe("wranglerRunner in Workers Builds", () => { + let dir: string; + afterAll(async () => { + if (dir) await rm(dir, { recursive: true, force: true }); + }); + + it("does not pass the build's Worker-name override to wrangler", async () => { + dir = await mkdtemp(path.join(os.tmpdir(), "cloudhal-wrangler-env-")); + await writeFile(path.join(dir, "package.json"), "{}"); + const pkg = path.join(dir, "node_modules/wrangler"); + await mkdir(path.join(pkg, "bin"), { recursive: true }); + await writeFile(path.join(pkg, "package.json"), '{"name":"wrangler","version":"4.151.0"}'); + // A stand-in wrangler that prints the variables a real one would read. + await writeFile( + path.join(pkg, "bin/wrangler.js"), + "process.stdout.write(JSON.stringify({ name: process.env.WRANGLER_CI_OVERRIDE_NAME ?? null, tag: process.env.WRANGLER_CI_MATCH_TAG ?? null, ci: process.env.WORKERS_CI ?? null }));", + ); + const saved = { ...process.env }; + process.env.WRANGLER_CI_OVERRIDE_NAME = "my-blog-site"; + process.env.WRANGLER_CI_MATCH_TAG = "tag123"; + process.env.WORKERS_CI = "1"; + try { + const r = await wranglerRunner(dir)(["deploy"], { cwd: dir, quiet: true }); + expect(JSON.parse(r.stdout)).toEqual({ name: null, tag: null, ci: "1" }); + } finally { + process.env = saved; + } + }); +});