Skip to content

feat(workers push): make build wait opt-in with --wait flag - #6371

Open
johnstonmatt wants to merge 1 commit into
FUNC-853/workers-logs-commandfrom
FUNC-848/workers-deploy-wait-flag
Open

feat(workers push): make build wait opt-in with --wait flag#6371
johnstonmatt wants to merge 1 commit into
FUNC-853/workers-logs-commandfrom
FUNC-848/workers-deploy-wait-flag

Conversation

@johnstonmatt

@johnstonmatt johnstonmatt commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Summary

supabase workers push blocked on the server-side container build on every invocation. That build routinely runs for minutes, so the common case — a deploy that builds fine — was the slowest thing in the loop.

The command now returns once the platform accepts the deploy, which is the last thing it can learn without waiting: the deploy response arrives only after the spec and the uploaded context are accepted, and it carries the accepted spec back. --wait opts into the build's verdict, for CI and for anyone who needs the image version before continuing.

  • A deploy answered with a spec already in failed is reported as a failure whether or not the build was waited on, rather than exiting zero on a worker that will never come up.
  • Without --wait the details block leads with a State row — the one row that says the worker is not serving yet — and drops Image, since no image exists until the build produces one.
  • A success trailer then names both workers status and --wait as ways to follow the build. Text output only; machine callers read build_state from the payload.

Stack

Stack 7, on top of the workers output polish (#6389). The output and styling work was split out so it can ship on its own — this PR is now only the flag and the behaviour change behind it, and can be rejected independently.

Linked issue

FUNC-848 (Linear). Supabase maintainer, exempt from the open-for-contribution flow.

Checklist

@johnstonmatt
johnstonmatt requested a review from a team as a code owner August 28, 2026 01:39
@github-actions

github-actions Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Supabase CLI preview

npx --yes https://pkg.pr.new/supabase/cli/supabase@22d3cfb3578f5bc8ba3a9cdd1ec4a502a8ee029a

Preview package for commit 22d3cfb.

@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: fdff3a52a1

ℹ️ 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/legacy/cli/legacy-boolean-flag-defaults.unit.test.ts Outdated
Comment thread apps/cli/src/legacy/cli/legacy-boolean-flag-defaults.unit.test.ts
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 29, 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 🔄 Running since 2026-08-31T22:34:18.796856Z 3bf251a 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.

@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: 6a6e00c91e

ℹ️ 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/legacy/commands/workers/push/push.handler.ts Outdated
Comment thread apps/cli/src/legacy/commands/workers/push/SIDE_EFFECTS.md Outdated
@johnstonmatt
johnstonmatt force-pushed the FUNC-848/workers-deploy-wait-flag branch from 6a6e00c to 8026a04 Compare August 29, 2026 02:43

@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: 5072b3ec0d

ℹ️ 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 on lines +83 to +85
| `--output-format json` | one structured result carrying `worker_name`, `project_ref`, `kept_*` | as above |
| `--output-format stream-json` | the same result as a single terminal event | as above |
| `-o json` / `yaml` / `toml` | the same payload in that encoding, and nothing else | as above |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Limit the delete trailer documentation to text mode

For --output-format json, stream-json, and -o json|yaml|toml, the handler returns immediately after emitting the payload, before reaching emitSuccessTrailer; therefore these rows' “as above” wording incorrectly promises the newly documented redeploy hint on stderr. Qualify the hint as text-only so this compatibility checklist matches the actual output branches.

AGENTS.md reference: apps/cli/AGENTS.md:L359-L366

Useful? React with 👍 / 👎.

Comment on lines +67 to +69
| `--output-format json` | one structured result carrying every reported field | as above |
| `--output-format stream-json` | the same result as a single terminal event | as above |
| `-o json` / `yaml` / `toml` | the same payload in that encoding, and nothing else | as above |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Limit the status trailer documentation to text mode

In the JSON, stream-JSON, and legacy machine-format branches, legacyWorkersStatus returns before the failed-build emitSuccessTrailer call, so “as above” falsely documents a build-retry hint that those modes never emit. Mark the retry hint as text-only rather than including it in every machine-mode stderr contract.

AGENTS.md reference: apps/cli/AGENTS.md:L359-L366

Useful? React with 👍 / 👎.

// On the success trailer rather than inline, the way `bootstrap` emits its
// "start your app" line: the shell prints trailers once at the end of the
// run, so the next step is the last thing on screen.
yield* emitSuccessTrailer(`Deploy it with ${legacyAqua(`supabase workers push ${name}`)}.\n`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Record the workers-new output-channel change

For a successful text-mode workers new, this changes the deploy hint from inline stdout to a deferred stderr success trailer, but workers/new/SIDE_EFFECTS.md was not updated and still contains no output-format contract describing the new channel. Since stdout/stderr behavior is an established compatibility surface and these checklists drive E2E coverage, document this intentional change in the same commit.

AGENTS.md reference: apps/cli/AGENTS.md:L267-L279

Useful? React with 👍 / 👎.

@johnstonmatt
johnstonmatt force-pushed the FUNC-848/workers-deploy-wait-flag branch from 5072b3e to 6010d9f Compare August 29, 2026 03:13
@johnstonmatt
johnstonmatt changed the base branch from FUNC-840/select-workers-new-name to FUNC-851/general-output-polish August 29, 2026 03:16

@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: 6010d9fcd1

ℹ️ 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 on lines +341 to +342
const settled = input.wait
? yield* awaitWorkerBuild(api, projectRef, name, {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Honor terminal deploy responses before polling

When --wait is set and the deploy POST already returns build_state: active or failed—both are permitted by V2DeployAWorkerOutput—this branch discards that terminal verdict and performs a GET anyway. If that read is temporarily unavailable, still returns the documented post-deploy 404 race, or observes a concurrent deployment, the command can time out, fail, or even succeed contrary to its own deploy response. Only poll when accepted.buildState === "building"; otherwise use accepted directly.

Useful? React with 👍 / 👎.

Comment on lines +410 to +413
yield* emitSuccessTrailer(
`\nYour build was submitted successfully.\n` +
`Run ${legacyAqua(`supabase workers status ${name}${input.refSuffix}`)} to check on it.\n` +
`Add ${legacyAqua("--wait")} to block on the build next time.\n`,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve accepted-build hints when a later worker fails

In a text-mode multi-worker push without --wait, an accepted worker queues its status command here, but if any later worker fails the real runCli path exits nonzero and never drains SuccessTrailer (shared/cli/run.ts only calls takeAll for exit code 0). The first remote build is still running, yet its only follow-up guidance is silently discarded; the handler-level tests do not expose this because their missing SuccessTrailer service makes emitSuccessTrailer write immediately. Surface these already-submitted build hints on partial failure rather than retaining them only for an entirely successful batch.

Useful? React with 👍 / 👎.

@johnstonmatt
johnstonmatt force-pushed the FUNC-848/workers-deploy-wait-flag branch from 6010d9f to 22d3cfb Compare August 31, 2026 19:14
@johnstonmatt
johnstonmatt changed the base branch from FUNC-851/general-output-polish to FUNC-853/workers-logs-command August 31, 2026 19:21
@chatgpt-codex-connector

Copy link
Copy Markdown

💡 Codex Review

// A poll asks for whatever arrived since the cursor, not for `--tail` lines;
// `--tail 0` means "no history", not "no new lines".
const pollTail = Math.max(flags.tail, 1);

P1 Badge Decouple live polling from the history tail limit

When --follow is used, this makes the history-only --tail value the SQL limit for every live poll. If more than that many entries arrive between polls, only the newest entries are returned and the cursor advances past the omitted ones, so they can never be emitted. The documented --tail 0 --follow flow is especially vulnerable because each poll requests only one row and silently loses all other lines from the interval; use a separate live-page limit and pagination/cursor handling instead.


const streams = Option.isSome(flags.source)
? [WORKER_LOG_STREAMS[flags.source.value as WorkerLogSourceChoice]]
: ALL_WORKER_LOG_STREAMS;

P1 Badge Derive source choices without a type assertion

This assertion suppresses the compiler check that every value accepted by --source is a key of WORKER_LOG_STREAMS. Because SOURCE_VALUES and the mapping are maintained separately, adding or renaming a choice can now compile while producing an undefined stream in the SQL query at runtime. Derive the choices from the mapping or preserve the closed key type without an assertion.

AGENTS.md reference: AGENTS.md:L220-L220


// A 429 or a blip should not end a tail the user is watching; the schedule is
// spaced in seconds, so retrying rides out a transient failure without
// spending the rate limit.
const poll = pollOnce.pipe(Effect.retry({ schedule: readRetrySchedule }));

P2 Badge Retry only transient log-read failures

Under --follow, this retries every typed failure from fetchWorkerLogs, including permanent 402 usage exhaustion, 404 enrollment failures, and rejected-query errors. Those cases therefore delay the actionable error for up to a minute while repeatedly spending requests; a 429 is also retried every five seconds despite the documented ten-request-per-minute limit. Restrict retries to transient network/rate-limit failures and give rate limits an interval that can actually clear.

AGENTS.md reference: AGENTS.md:L181-L187


processControl
.awaitSignal()
.pipe(Effect.flatMap((signal) => processControl.exit(signal === "SIGINT" ? 130 : 0))),

P1 Badge Let interruption unwind before exiting the process

When a followed command receives SIGINT or SIGTERM in the real runtime, ProcessControl.exit calls process.exit synchronously, so control never unwinds through the handler's Effect.ensuring finalizers or the outer instrumentation wrapper. Consequently the linked-project cache and telemetry flush are skipped on the normal way users terminate --follow; set the exit code and return from the race so finalizers can complete before the CLI process ends.

AGENTS.md reference: apps/cli/AGENTS.md:L286-L290


if (!flags.follow && output.format !== "text") {
yield* output.success("", payload);
return;

P1 Badge Honor the legacy text format before output-format

When callers combine -o pretty or -o table with --output-format json or stream-json, legacyEmitWorkersMachineOutput returns false for the legacy text choice and this branch then emits according to output.format. The lower-priority --output-format therefore wins, producing structured output instead of the explicitly requested legacy text rendering; the same mismatch also changes whether --follow is accepted. Branch on the presence of the legacy format before consulting output.format.

AGENTS.md reference: apps/cli/AGENTS.md:L298-L300


yield* output.event({
type: "log-entry",
timestamp: new Date(entry.timestampMs).toISOString(),
service: name,
stream: level === "error" || level === "warn" ? "stderr" : "stdout",
line: entry.message,
source: origin,

P2 Badge Preserve request and build details in followed JSON logs

With --follow --output-format stream-json, this writes only event_message into each event. For request rows that field contains just the method and path while status and duration live in attributes; for build rows the failure reason also lives in attributes. Those details are retained in bounded JSON and composed into text output, but are irretrievably lost from the streaming machine format, so consumers cannot reconstruct the actual request result or build failure. Include the relevant attributes in the streamed representation.

ℹ️ 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 workers push` blocked on the server-side container build on every
invocation. That build routinely runs for minutes, so the common case — a
deploy that builds fine — was the slowest thing in the loop.

The command now returns once the platform accepts the deploy, which is the last
thing it can learn without waiting: the deploy response arrives only after the
spec and the uploaded context are accepted, and it carries the accepted spec
back. `--wait` opts into the build's verdict, for CI and for anyone who needs
the image version before continuing.

A deploy answered with a spec already in `failed` is still reported as a
failure whether or not the build was waited on, rather than exiting zero on a
worker that will never come up. Without `--wait` the details block leads with a
`State` row — the one row that says the worker is not serving yet — and drops
`Image`, since no image exists until the build produces one. A success trailer
then names both `workers status` and `--wait` as ways to follow the build.

The flag closes with `Flag.withDefault(false)`; the guard added in the previous
commit is what keeps a boolean flag from shipping required again.
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.

1 participant