Repository navigation
fix(deploy): bypass deployment checks for automatic rollbacks - #571
Brooooooklyn merged 4 commits into
Conversation
058c950 to
c16802d
Compare
c16802d to
96e5881
Compare
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Codex Review: Something went wrong. Try again later by commenting “@codex review”. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
@codex review |
|
Codex Review: Something went wrong. Try again later by commenting “@codex review”. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
#594) The Astro playground's dev smoke test (`astro.test.ts > playground/astro dev`) sometimes misses its 20 s start limit during a full parallel run. The server log shows why: ``` [WARN] Failed to resolve dependency: drizzle-orm/sqlite-core, present in ssr 'optimizeDeps.include' astro ready first GET / ──→ Vite finds drizzle-orm/sqlite-core now ──→ "optimized dependencies changed. reloading" / "program reload" ──→ 200 after 6.5 s (limit already used up) ``` `astro.config.mjs` lists `drizzle-orm/sqlite-core` so it is optimized up front, but `drizzle-orm` is Void's dependency, not the playground's, so Vite can't resolve that name and skips it. This names it through Void (`void > drizzle-orm/sqlite-core`), the same way Void's own plugin names `void > email-validator`. | Fresh `astro dev` (`.void` and `.wrangler` removed) | Warning | Reload in first request | First `GET /` | |---|---|---|---| | before | yes | yes | 1.05 s on an idle machine | | after | none | none | 0.42 s | Only the playground config changes. Seen while working on #571. `vinext-pages dev` failed the same way once in another run. I didn't capture its log, and its config has no `optimizeDeps`, so this PR doesn't claim to fix that one. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Cloudflare rejects a deployment that rolls back to an older version after a secret changed (error 10220) unless it is forced. Void's automatic recovery after failed readiness, activation or trigger synchronization therefore failed whenever the failed version changed a secret, leaving the Worker at previous@100 plus failed@0 and blocking later deploys with deployment-changed. Add an optional bypassDeploymentChecks flag to versions.deploy, mapped to cf's --bypass-deployment-checks (force=true), and set it only on automatic recovery paths that have already verified ownership of current traffic: restorePreviousVersion, the trigger-synchronization rollback, and platform deployment restoration. Normal deploys and user-requested rollbacks are unchanged.
…an old secret version Try the automatic app rollback without force first, as Wrangler's rollback does. Only when Cloudflare answers 10220 (a secret changed since the previous version was active), read the owner again and retry with force, so a secret changed outside Void is not overwritten and any other Cloudflare check still applies. Keep the trigger-sync rollback and the platform installer unforced. The first returns to the version that served traffic seconds before, so a 10220 there comes from someone else. The second would undo voidzero-dev#569: a credential update rolls forward instead of restoring old secrets. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
When Cloudflare refused the automatic restore over a secret change and Void forced it, the activation result now carries `restoredOlderSecrets: true`, and the deploy error tells the user that the previous version runs with its old secret values and that deploying again applies the new ones. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
7ac03d2 to
1df0efe
Compare
Cloudflare refuses a deployment that moves traffic back to an older Worker version when a secret has changed since that version was active (error 10220), unless the request is forced. Void's automatic recovery runs into this. After a failed readiness check, activation or trigger sync, it deploys the previous version at 100%. Cloudflare rejects that, the Worker stays at the previous version at 100% plus the failed one at 0%, and the next deploy stops with
deployment-changeduntil someone fixes the deployment by hand.What changed
versions.deploygets an optionalbypassDeploymentChecks. Both cf runners pass it as--bypass-deployment-checks, which sendsforce=trueto the Deployments API.restorePreviousVersion(readiness, uploader-check, activation and trigger-sync failures) first tries the restore without force. Only when Cloudflare answers 10220 does it read the owner again and retry with force. Wrangler's own rollback does the same: it tries without force and forces only after a 10220.restoredOlderSecrets: trueand the deploy error adds:void rollback(user asked for it)restorePreviousVersion)activateCloudflareExistingVersionWhy the last two are not forced
platform-installer.tsand the test "rolls forward a partially restored credential update"). ForcingrestorePlatformWorkerDeploymentwould undo that for the one Worker whose trigger or domain publish failed, and put it back on the old, possibly revoked, API token. Without a credential update, Void's own platform deploys don't cause a 10220.Where this applies
The app path is the one that hits this: a deploy whose new version changes a secret and then fails readiness, activation or trigger sync. I found it in a fork that publishes prebuilt artifacts with explicit secrets. With this change, the same live run on Cloudflare restored the previous version and the next deploy went through.
Tests
operations.test.tsruns every recovery path (readiness, activation, triggers; with and withoutpreserveTriggers) in 4 cases:restoredOlderSecrets: true.unsafe, no forced retry.failed, no retry.cloudflare-deploy.test.tschecks that the readiness, trigger and uploader errors add the old-secrets line only whenrestoredOlderSecretsis set.cloudflare-operations.test.tschecks that the trigger-sync rollback and user rollbacks are not forced.platform-install-cutover.test.tschecks that no platform activation or restoration is forced.?force=trueis sent next to the deployment body.restoredOlderSecrets, drop it on the trigger path, skip the message line.vp fmt,vp lint, thedeploy-cloudflareandvoidtypechecks, andvp run test --base origin/mainpass.Known limits
forceonly as skipping checks "such as" the secret one. This PR forces only after Cloudflare answers 10220, so force is used only in the case Cloudflare names.🤖 Generated with Claude Code