Skip to content

fix(cli): keep bulk function deploys going and always sync metadata (INC-699) - #6018

Merged
avallete merged 3 commits into
developfrom
avallete/incident-response-b9d9ad
Jul 31, 2026
Merged

fix(cli): keep bulk function deploys going and always sync metadata (INC-699)#6018
avallete merged 3 commits into
developfrom
avallete/incident-response-b9d9ad

Conversation

@avallete

@avallete avallete commented Jul 31, 2026

Copy link
Copy Markdown
Member

Summary

Bulk functions deploy uploads each function with bundleOnly=true, which writes the bundle and bumps the remote version without persisting metadata — only the final PUT /v1/projects/{ref}/functions does. The flow failed fast: any single upload error (409 deployment already exists, 400 Bundle 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):

  • Run every upload to completion instead of aborting on the first error; failed functions are skipped and their errors collected.
  • Always send the final bulk update PUT assembled from the functions that uploaded successfully, so remote metadata stays consistent. The PUT is only skipped when every upload failed (nothing new to sync, nothing stranded).
  • Still exit non-zero on partial failure, reporting each failed function's error (messages joined with newlines, errors.Join semantics 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 skipped
Loading

After — 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 outcome
Loading

Reviewer notes

  • The final PUT already only ever carried the functions being deployed (never the full remote set), so sending the successful subset is upsert-safe.
  • The single-function path (no bundleOnly) and the Docker bundler path (per-function upserts persist metadata server-side) are unaffected and untouched.
  • Error ordering: both implementations report upload errors in input order regardless of --jobs concurrency — Go records failures per function index instead of reading the job queue's completion-order error channel, matching TS.
  • On failure, the TS error is an AggregateError carrying the original error objects; its message stays byte-identical to Go's errors.Join output.

Linked issue

Incident: INC-699 (bulk edge function deployments failing / 409 deployment already exists). Internal incident, no open-for-contribution issue — Supabase maintainer.

Checklist

  • The PR title follows Conventional Commits (e.g. fix(cli): …).
  • Tests added or updated for the change.
  • pnpm check:all and pnpm test pass for the workspace(s) I touched (apps/cli integration suites; go build/go vet/go test ./pkg/function/... incl. -race for apps/cli-go).

🤖 Generated with Claude Code

…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>
@avallete
avallete requested a review from a team as a code owner July 31, 2026 07:41

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread apps/cli/src/shared/functions/deploy.ts
@github-actions

github-actions Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Supabase CLI preview

npx --yes https://pkg.pr.new/supabase/cli/supabase@032c2fa2a488bd39944bcaa74310b330655298c8

Preview package for commit 032c2fa.

avallete and others added 2 commits July 31, 2026 10:01
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>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread apps/cli/src/shared/functions/deploy.ts
Comment thread apps/cli-go/pkg/function/deploy.go
Comment thread apps/cli-go/pkg/function/deploy.go
@avallete
avallete enabled auto-merge July 31, 2026 08:27
@avallete
avallete added this pull request to the merge queue Jul 31, 2026
Merged via the queue into develop with commit ae89b16 Jul 31, 2026
72 of 74 checks passed
@avallete
avallete deleted the avallete/incident-response-b9d9ad branch July 31, 2026 08:38
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.

2 participants