fix(planetscale): turn off auto-apply on every deploy request SchemaBot creates - #965
Draft
aparajon wants to merge 1 commit into
Draft
fix(planetscale): turn off auto-apply on every deploy request SchemaBot creates#965aparajon wants to merge 1 commit into
aparajon wants to merge 1 commit into
Conversation
…ot creates SchemaBot is the sole cutover actor on PlanetScale: a deploy request must park at pending_cutover so the driver — or the operator holding a deferred cutover — decides when the schema swaps. The create request cannot express that. The SDK tags CreateDeployRequestRequest.AutoCutover `omitempty`, so false is the zero value and "auto-cutover off" serializes identically to "unspecified". The deploy request then inherits the database's own remembered auto-apply default, which may be on, and cuts over unattended. Stating the intent requires the auto-apply endpoint, whose flag is sent unconditionally. Every deploy request now has auto-apply turned off immediately after creation, and a deploy request whose auto-apply could not be turned off is refused rather than driven — SchemaBot cannot guarantee it owns the swap. LocalScale grows the same endpoint, and an absent auto_cutover on create now defaults to on the way PlanetScale's remembered default can. Defaulting it off made a caller that never stated its intent look correct. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Ensures SchemaBot remains the sole cutover actor for PlanetScale deploy requests by explicitly disabling auto-apply immediately after deploy request creation (working around the Go SDK’s omitempty behavior), and extends LocalScale to emulate the same semantics.
Changes:
- Add
PSClient.DisableAutoApplyand implement it via the PlanetScale auto-apply endpoint. - Update the PlanetScale engine to disable auto-apply right after creating a deploy request and refuse to proceed if it can’t be disabled.
- Extend LocalScale with the auto-apply endpoint and make create-deploy default
auto_cutoverto “on” when the field is absent; update integration/unit tests accordingly.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| pkg/psclient/client.go | Adds a DisableAutoApply API to reliably force auto-apply off on deploy requests. |
| pkg/engine/planetscale/branch.go | Calls DisableAutoApply after deploy request creation and fails closed if it can’t be disabled. |
| pkg/engine/planetscale/branch_test.go | Updates tests to assert the new “disable auto-apply” behavior and refusal-on-failure. |
| pkg/localscale/server.go | Registers the LocalScale auto-apply route to match PlanetScale behavior. |
| pkg/localscale/handlers_actions.go | Implements the LocalScale auto-apply handler that flips stored auto_cutover. |
| pkg/localscale/handlers_deploy.go | Treats auto_cutover as optional (pointer) and defaults absent to “on” to emulate remembered defaults. |
| pkg/localscale/server_integration_test.go | Updates integration test helper to disable auto-apply when requesting a held cutover. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+548
to
+549
| e.logger.Info("auto-apply disabled on deploy request; the drive is the sole cutover actor", | ||
| "organization", org, "database", database, "deploy_request", dr.Number, "branch", branchName) |
Comment on lines
+222
to
+225
| // handleAutoApplyDeployRequest turns a deploy request's auto-apply on or off. | ||
| // It is the only way a client can state that a deploy request must hold at | ||
| // pending_cutover instead of cutting over on its own, because the create | ||
| // request's auto_cutover field cannot carry a false. |
Comment on lines
+545
to
+547
| if err := client.DisableAutoApply(ctx, org, database, dr.Number); err != nil { | ||
| return nil, fmt.Errorf("deploy request %d was created but auto-apply could not be turned off, so PlanetScale may cut over without SchemaBot: %w", dr.Number, err) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why this matters
SchemaBot is the sole cutover actor on PlanetScale: a deploy request must park at
pending_cutoverso the driver — or the operator holding a deferred cutover — decides when the schema swaps. Today--defer-cutoveris a no-op there.The create request cannot express the intent. The SDK tags
CreateDeployRequestRequest.AutoCutoveromitempty, sofalseis the zero value and "auto-cutover off" serializes identically to "unspecified". The deploy request then inherits the database's own remembered auto-apply default, which may be on, and cuts over unattended.What it does
auto_cutoveron create default to on, the way the remembered default can. Defaulting it off made a caller that never stated its intent look correct.🤖 Generated with Claude Code