diff --git a/packages/runtime-cloudflare/README.md b/packages/runtime-cloudflare/README.md index d294d33cc..9b443562b 100644 --- a/packages/runtime-cloudflare/README.md +++ b/packages/runtime-cloudflare/README.md @@ -52,7 +52,7 @@ SSI is extracted only for import requests, so normal browser, mutation, publicat 2. Run `npm run provision:cloudflare-wordpress-runtime-corpus -- --local --persist-to ` to verify and upload all exact content-addressed artifacts into isolated local R2 storage. For an authorized deployment, run the provisioner with `--remote` and require every upload to succeed before deploying the Worker that imports their manifests. 3. Run `npm run test:cloudflare-runtime` for routing, coordinator composition, canonical-state, artifact validation, source contract, and TypeScript coverage. 4. Run `npm run cloudflare:dry-run` and `npm run cloudflare:dry-run:d1` to compile the Durable Object and D1 profiles without creating Cloudflare resources. The placeholder D1 database ID is for local/dry-run verification; an implementation supplies its provisioned binding at deployment. - Use `npm run provision:cloudflare-d1-coordinator -- --output ` to idempotently create or resolve the named production database and emit a mode-`0600` deployment config from the checked-in template. + Use `npm run provision:cloudflare-d1-coordinator -- --output ` to idempotently create or resolve the named production database and emit a mode-`0600` deployment config from the checked-in template. Relative entrypoints are resolved from that template so the emitted config remains deployable outside the checkout. 5. Run `npm run cloudflare:local-gate` and `npm run cloudflare:local-gate:d1` for the same isolated workerd workflow through both coordinator implementations. Each gate generates and provisions all artifacts, verifies the selected backend through the state envelope, injects stable test-only admin-password, auth-secret, and operator-token values, uploads and activates a real plugin ZIP, establishes an anonymous homepage and canonical-permalink publication, updates a published post through authenticated REST without immediate rendering, restarts with pending publication work, and proves bounded scheduled draining eventually exposes the updated permalink through coordinator-free R2. The cron gate also proves that a scheduled post becomes readable from the publication path without an operator call. Restart verification requires the immutable R2 publication. A final two-host phase proves isolated mutations, coordinator versions, REST collections, credentials, publications, and caches plus fail-closed unknown-host routing. The remaining coverage includes login, concurrent canonical writes, media, representative frontend/admin/editor assets, PHP diagnostics, session recovery, and a fresh login after restart. This document describes local candidate verification only. It does not claim remote deployment. diff --git a/scripts/provision-cloudflare-d1-coordinator.mjs b/scripts/provision-cloudflare-d1-coordinator.mjs index 82b0351ce..81073a307 100644 --- a/scripts/provision-cloudflare-d1-coordinator.mjs +++ b/scripts/provision-cloudflare-d1-coordinator.mjs @@ -1,6 +1,6 @@ import { spawn } from "node:child_process" import { readFile, writeFile } from "node:fs/promises" -import { resolve } from "node:path" +import { dirname, resolve } from "node:path" const args = process.argv.slice(2) const option = (name, fallback) => { @@ -26,6 +26,7 @@ const database = matches[0] if (!database || typeof database.uuid !== "string" || !/^[a-f0-9-]{36}$/.test(database.uuid)) throw new Error(`D1 database ${databaseName} was not resolved after provisioning.`) const template = parseJsonc(await readFile(templatePath, "utf8")) +if (typeof template.main === "string" && !template.main.startsWith("/")) template.main = resolve(dirname(templatePath), template.main) const configured = template.d1_databases?.find((candidate) => candidate.binding === binding && candidate.database_name === databaseName) if (!configured) throw new Error(`D1 template does not declare ${binding} for ${databaseName}.`) configured.database_id = database.uuid diff --git a/tests/cloudflare-d1-provisioner.test.mjs b/tests/cloudflare-d1-provisioner.test.mjs index 1ca2f42e4..d71f033a5 100644 --- a/tests/cloudflare-d1-provisioner.test.mjs +++ b/tests/cloudflare-d1-provisioner.test.mjs @@ -27,6 +27,7 @@ test("D1 provisioner creates once and emits a deployable config deterministicall assert.deepEqual(second, first) const config = JSON.parse(await readFile(output, "utf8")) assert.equal(config.d1_databases[0].database_id, first.databaseId) + assert.equal(config.main, join(directory, "src/worker-d1.ts")) const invocations = (await readFile(calls, "utf8")).trim().split("\n").map(JSON.parse) assert.equal(invocations.filter((args) => args[1] === "create").length, 1) } finally {