fix(cli): keep bulk function deploys going and always sync metadata (INC-699) - #6018
Conversation
…INC-699) Bulk deploys upload each function with bundleOnly=true, which writes the bundle and bumps the remote version without persisting metadata - only the final bulk update PUT does. Failing fast on the first upload error skipped that PUT, stranding the new versions client-side and making every subsequent deploy fail with 409 version conflicts. Both the Go CLI and the TS port now run every upload to completion, always send the bulk update with the functions that succeeded (skipping it only when none did), and then fail with the collected upload errors so partial failures still exit non-zero. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9525dba84a
ℹ️ 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".
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".
Supabase CLI previewnpx --yes https://pkg.pr.new/supabase/cli/supabase@032c2fa2a488bd39944bcaa74310b330655298c8Preview package for commit |
Adds the missing Go test for the partial-upload-then-PUT-failure branch, mirrors the same scenario in the legacy TS suite, and preserves the original error objects (AggregateError) when the shared deploy path joins failure messages. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Go collected upload failures from the job queue's error channel, i.e. in job-completion order, while the TS port reports them in input order. Record errors per function index instead so both implementations emit identical, deterministic error ordering under concurrency. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 032c2fa2a4
ℹ️ 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".
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".
Summary
Bulk
functions deployuploads each function withbundleOnly=true, which writes the bundle and bumps the remote version without persisting metadata — only the finalPUT /v1/projects/{ref}/functionsdoes. The flow failed fast: any single upload error (409deployment already exists, 400Bundle generation timed out, …) aborted the deploy before that PUT, stranding the new version metadata client-side. The backend was left with stale versions, so every subsequent deploy computed a conflicting version and failed with 409 — the poisoned-project loop driving INC-699.This change makes the bulk path continue through per-function failures, in both the Go CLI and the TS port (identical semantics, since legacy TS is a 1:1 Go port):
errors.Joinsemantics on the Go side). If the PUT itself fails, its error is appended after the upload errors.A failed bulk deploy no longer poisons the project: re-running the deploy just works.
Before — fail-fast strands the metadata
flowchart TD A["POST fn-a ?bundleOnly=true → 201<br/><i>bundle stored, version bumped</i>"] B["POST fn-b ?bundleOnly=true → 201<br/><i>bundle stored, version bumped</i>"] C["POST fn-c ?bundleOnly=true → 409<br/><i>CLI aborts the whole deploy</i>"] D["PUT /functions metadata sync<br/><i>never sent — new versions lost</i>"] E["Backend metadata now stale<br/><i>every re-deploy hits 409</i>"] A --> B --> C C -.-x D -.-> E classDef ok fill:#e1f5ee,stroke:#0f6e56,color:#04342c classDef bad fill:#fcebeb,stroke:#a32d2d,color:#501313 classDef skipped fill:#f1efe8,stroke:#5f5e5a,color:#2c2c2a,stroke-dasharray:6 4 class A,B ok class C,E bad class D skippedAfter — failures are skipped, successes always synced
flowchart TD A["POST fn-a ?bundleOnly=true → 201<br/><i>bundle stored, version bumped</i>"] B["POST fn-b ?bundleOnly=true → 201<br/><i>bundle stored, version bumped</i>"] C["POST fn-c ?bundleOnly=true → 409<br/><i>error collected, flow continues</i>"] D["PUT /functions with fn-a, fn-b<br/><i>metadata synced for successes</i>"] E["Exit 1, report fn-c failure<br/><i>state consistent — retry works</i>"] A --> B --> C --> D --> E classDef ok fill:#e1f5ee,stroke:#0f6e56,color:#04342c classDef tolerated fill:#faeeda,stroke:#854f0b,color:#412402 classDef outcome fill:#f1efe8,stroke:#5f5e5a,color:#2c2c2a class A,B,D ok class C tolerated class E outcomeReviewer notes
bundleOnly) and the Docker bundler path (per-function upserts persist metadata server-side) are unaffected and untouched.--jobsconcurrency — Go records failures per function index instead of reading the job queue's completion-order error channel, matching TS.AggregateErrorcarrying the original error objects; itsmessagestays byte-identical to Go'serrors.Joinoutput.Linked issue
Incident: INC-699 (bulk edge function deployments failing / 409 deployment already exists). Internal incident, no
open-for-contributionissue — Supabase maintainer.Checklist
fix(cli): …).pnpm check:allandpnpm testpass for the workspace(s) I touched (apps/cliintegration suites;go build/go vet/go test ./pkg/function/...incl.-raceforapps/cli-go).🤖 Generated with Claude Code