From 930009695f62a57691e14026c6b8ec29fa8408fb Mon Sep 17 00:00:00 2001 From: nplusonedev <313439419+nplusonedev@users.noreply.github.com> Date: Fri, 14 Aug 2026 06:54:33 +0000 Subject: [PATCH 1/2] ci: check the Worker configs against the code before deploying MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `wrangler.jsonc` names code that no TypeScript gate reads: the entrypoint, and every Durable Object class the entrypoint has to export. Rename a class without renaming its binding and `pnpm lint`, `pnpm typecheck` and `pnpm test` all stay green. Verified by renaming one `class_name`: typecheck reported 0 errors, the dry run exited 1 with "Your Worker depends on the following Durable Objects, which are not exported in your entrypoint file". Left alone, that first fails in the deploy jobs — after D1 migrations have been applied, and for the dispatcher after the substrate and canary have already shipped. `ci` gates every later job, so catching it here means nothing mutates. `--containers-rollout none` is load-bearing. A plain `--dry-run` still builds every container image (wrangler skips the push, not the build), which the deploy jobs then build again; with the flag each check is a ~2s bundle and the `ci` job needs no Docker. Scoped honestly: this does NOT catch a misspelled `cloudflare:*` import. `cloudflare:*` is an esbuild external, so any spelling bundles and exits 0. The vitest suite is what catches that, because its alias matches only the exact specifier. --- .github/workflows/deploy.yml | 9 +++++++++ AGENTS.md | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 71d0b8b..778cd4b 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -76,6 +76,15 @@ jobs: - run: pnpm lint - run: pnpm typecheck - run: pnpm test + # wrangler.jsonc names code that no TypeScript gate checks: entrypoints, + # and Durable Object classes the entrypoint must export. Rename a class + # without its binding and lint, typecheck and test all stay green — the + # first failure is the deploy below, after migrations have been applied. + # `--containers-rollout none` keeps this to the bundle: without it a dry + # run still builds every container image, which the deploy jobs then + # build again. + - run: pnpm exec wrangler deploy --dry-run --containers-rollout none + - run: pnpm exec wrangler deploy --dry-run --containers-rollout none -c apps/substrate/wrangler.jsonc # The substrate deploys BEFORE the dispatcher, and its own job rather than a # step in `deploy`, because the ordering is a real constraint and not a diff --git a/AGENTS.md b/AGENTS.md index 5a9ca36..d3c6cc0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,7 +4,7 @@ BYOC CI/CD that offloads the expensive half of GitHub Actions onto a Cloudflare ## Status -Working monorepo: Effect-TS DSL (`packages/core`), capability layers (`packages/runtime-cf`), run definitions (`runs/`), the dispatcher Worker (`apps/dispatcher`), the substrate (`apps/substrate`), and the bundled CLIs (`packages/demo-agent`, `packages/review-agent`). Deployed via `wrangler deploy` with container images built in-repo (`infra/Dockerfile.sandbox*`); CI runs `pnpm lint && pnpm typecheck && pnpm test` (`deploy.yml`). +Working monorepo: Effect-TS DSL (`packages/core`), capability layers (`packages/runtime-cf`), run definitions (`runs/`), the dispatcher Worker (`apps/dispatcher`), the substrate (`apps/substrate`), and the bundled CLIs (`packages/demo-agent`, `packages/review-agent`). Deployed via `wrangler deploy` with container images built in-repo (`infra/Dockerfile.sandbox*`); CI runs `pnpm lint && pnpm typecheck && pnpm test`, then `wrangler deploy --dry-run` for both workers so a Worker config that names missing code fails before anything deploys (`deploy.yml`). ## Architecture From 76d7c1cd273c1a7c39df87d7feb596364ade9cd0 Mon Sep 17 00:00:00 2001 From: nplusonedev <313439419+nplusonedev@users.noreply.github.com> Date: Sat, 15 Aug 2026 21:40:30 +0000 Subject: [PATCH 2/2] ci: dry-run the configs before the suite, not after The two dry runs cost seconds and pnpm test costs minutes, so ordered last a config that names missing code waited out the whole suite before saying so. After typecheck deliberately, so a real code error still fails with the typechecker's message rather than esbuild's. --- .github/workflows/deploy.yml | 8 ++++++-- AGENTS.md | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 778cd4b..e5b10b9 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -75,16 +75,20 @@ jobs: - run: pnpm install --frozen-lockfile - run: pnpm lint - run: pnpm typecheck - - run: pnpm test # wrangler.jsonc names code that no TypeScript gate checks: entrypoints, # and Durable Object classes the entrypoint must export. Rename a class # without its binding and lint, typecheck and test all stay green — the # first failure is the deploy below, after migrations have been applied. # `--containers-rollout none` keeps this to the bundle: without it a dry # run still builds every container image, which the deploy jobs then - # build again. + # build again. BEFORE `pnpm test`, deliberately: these cost seconds and + # the suite costs minutes, so on the main-push run a config that names + # missing code reds this job without waiting out the suite. After + # `typecheck`, also deliberately: a real code error should fail with the + # typechecker's message, not esbuild's. - run: pnpm exec wrangler deploy --dry-run --containers-rollout none - run: pnpm exec wrangler deploy --dry-run --containers-rollout none -c apps/substrate/wrangler.jsonc + - run: pnpm test # The substrate deploys BEFORE the dispatcher, and its own job rather than a # step in `deploy`, because the ordering is a real constraint and not a diff --git a/AGENTS.md b/AGENTS.md index d3c6cc0..f2a6f68 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,7 +4,7 @@ BYOC CI/CD that offloads the expensive half of GitHub Actions onto a Cloudflare ## Status -Working monorepo: Effect-TS DSL (`packages/core`), capability layers (`packages/runtime-cf`), run definitions (`runs/`), the dispatcher Worker (`apps/dispatcher`), the substrate (`apps/substrate`), and the bundled CLIs (`packages/demo-agent`, `packages/review-agent`). Deployed via `wrangler deploy` with container images built in-repo (`infra/Dockerfile.sandbox*`); CI runs `pnpm lint && pnpm typecheck && pnpm test`, then `wrangler deploy --dry-run` for both workers so a Worker config that names missing code fails before anything deploys (`deploy.yml`). +Working monorepo: Effect-TS DSL (`packages/core`), capability layers (`packages/runtime-cf`), run definitions (`runs/`), the dispatcher Worker (`apps/dispatcher`), the substrate (`apps/substrate`), and the bundled CLIs (`packages/demo-agent`, `packages/review-agent`). Deployed via `wrangler deploy` with container images built in-repo (`infra/Dockerfile.sandbox*`); CI runs `pnpm lint && pnpm typecheck`, then `wrangler deploy --dry-run` for both workers — so a Worker config that names missing code fails before anything deploys — then `pnpm test` (`deploy.yml`). ## Architecture