Skip to content

fix(cloudflare): stop on unsupported runtimes and keep deploy failures readable and safe - #721

Merged
Brooooooklyn merged 1 commit into
mainfrom
fix/cloudflare-deploy-node-runtime
Nov 6, 2026
Merged

Brooooooklyn merged 1 commit into
mainfrom
fix/cloudflare-deploy-node-runtime

Conversation

@Brooooooklyn

Copy link
Copy Markdown
Member

Fixes #627

What went wrong

generated Bun workflow (setup-bun only)
 └─ bunx void deploy → "#!/usr/bin/env node" → runner Node 22
     ├─ build, checks, cf children ── work on Node 22
     └─ credential helper child ── fails to load (node:http has no setGlobalProxyFromEnv)
          ├─ reason dropped → "Cloudflare session has no bearer for version-aware upload."
          └─ later run: trigger sync failed after go-live
               └─ recovery switched traffic back to an empty previous version → secrets looked gone

The keyring flag in the issue plays no part: with CLOUDFLARE_API_TOKEN set, the token is returned before any keyring use.

Changes

Part Change
Runtime void and create-void check the runtime first and stop with a clear message on Node outside ^24.22.0 || >=26.12.0 or Bun < 1.4.0. The bin entry imports only the check, then loads the CLI, so an old Node never hits a load-time SyntaxError.
CI template void init --github adds actions/setup-node to Bun workflows; setup-node gets check-latest: true.
Child errors One reporter for Cloudflare child steps: exit code / signal / spawn error plus a stderr tail. Credentials are scrubbed by exact value before truncation; the credential step's stdout is never logged. "no bearer" becomes the real cause.
Logs Each child step writes a debug cloudflare_op record; cloudflare_deploy_failed carries reason, status and version ids; failures write deploy_end. Log writes are synchronous so records survive process.exit.
Settings When observability/logpush settings will be published, the credential is read before upload, so a missing credential leaves traffic unchanged. The publish step reads a fresh one.
Recovery If trigger sync fails after go-live and the previous version is an empty draft, a placeholder, or has no Void trigger snapshot, the new version stays live. activeVersionId always names the live version; new triggersRestored / restoreSkipped fields. The message always says Live now: <id> and gives Cloudflare's reason.
keep_vars keep_vars no longer drops secret types from the kept bindings (regression from 546a76e; hardening, not the reporter's cause).

Recovery decision table:

trigger sync fails after N got 100%
  previous P = Void version with trigger snapshot ─► switch back to P, replay its triggers
  previous P = draft / placeholder / non-Void ─────► keep N live, say so
  P could not be read ──────────────────────────────► keep N live, no rollback hint
  someone else moved traffic ───────────────────────► report the live version, no switch

Release notes (behaviour changes)

  • Every void command, including --help, now exits 1 on Node 22, 24.14–24.21, 25.x or 26.0–26.11, and on Bun < 1.4.0. Existing Bun CI workflows need an actions/setup-node step (Node 24.22+) before bunx void.
  • @void/deploy-cloudflare: trigger-failure results always set activeVersionId and add triggersRestored and restoreSkipped.
  • Deploy log files are created owner-only (0600).

Not in this PR

  • Warning before deploying over a version another tool made, a check for declared secrets missing on the live version, trigger preflight, and auto-retry. These are separate product decisions.
  • A few exits (migration check, prompt cancel, managed deploy Ctrl-C) still skip deploy_end; their earlier records now reach disk.

Verification

  • Built CLI on real Node 22 (Docker): message + exit 1. create-void on Node 18/22: message, exit 1, no folder. Node 24.22 and Bun 1.4.4: void --version works.
  • Two review rounds (6 + 3 reviewers, 2 skeptics per finding); 9 confirmed findings fixed, each with a regression test.
  • vp run check: 33/33. vp run test: 780 files passed (16082 tests).

🤖 Generated with Claude Code

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-06T06:56:59.178773Z 2b9ff55 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

🚀 Deploying Preview to Cloudflare 🚀

Preview URL: https://fix-cloudflare-deploy-node-runtime-void-cloud.voidzero-docs.workers.dev (commit 2b9ff55)

This URL reflects your latest Preview deployment

Preview Deployments by commit

Status Deployment URL Commit Updated (UTC) See this deployment's details
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://07ae8c29-void-cloud.voidzero-docs.workers.dev 2b9ff55 2026-11-06T06:57:14.433Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://73613ab8-void-cloud.voidzero-docs.workers.dev 51f9fec 2026-11-05T04:48:42.645Z Visit the dashboard ↗

…s readable and safe

`bunx void deploy` in the generated Bun workflow ran the CLI on the runner's
Node 22. The helper child that reads the Cloudflare credential failed to load
there (`node:http` has no `setGlobalProxyFromEnv`), the reason was dropped,
and the upload stopped with "Cloudflare session has no bearer". A later
trigger-sync failure then switched traffic back to an empty previous version.

- Check the runtime before loading the CLI: `void` and `create-void` stop on
  Node outside ^24.22.0 || >=26.12.0, or Bun below 1.4.0, with a clear message.
  The bin entry imports only the check, then loads the CLI.
- `void init --github` adds actions/setup-node to Bun workflows and sets
  check-latest on setup-node.
- Child failures keep their exit code, signal and a scrubbed stderr tail.
  Credentials are removed by exact value before truncation. Each Cloudflare
  child step writes a debug `cloudflare_op` record, and failures write
  `deploy_end`.
- Read the credential before upload when Worker settings will be published,
  so a missing credential leaves traffic unchanged.
- When trigger sync fails after activation, keep the new version live if the
  previous one is an empty draft, a placeholder, or has no Void trigger
  snapshot. `activeVersionId` now always names the live version, and new
  `triggersRestored`/`restoreSkipped` fields drive a "Live now: <id>" message.
- `keep_vars` no longer narrows the kept bindings to drop secret types.
- Deploy log writes are synchronous so records survive process.exit.

Fixes #627

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Brooooooklyn
Brooooooklyn force-pushed the fix/cloudflare-deploy-node-runtime branch from 51f9fec to 2b9ff55 Compare November 6, 2026 06:54
@Brooooooklyn
Brooooooklyn merged commit 28bb13f into main Nov 6, 2026
20 checks passed
@Brooooooklyn
Brooooooklyn deleted the fix/cloudflare-deploy-node-runtime branch November 6, 2026 07:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CI deploy fails with "Cloudflare session has no bearer for version-aware upload" (runner-only; passed 10h earlier with the same token)

1 participant