Skip to content

feat(cli): select stack start and stop with feature flag - #6544

Merged
jgoux merged 4 commits into
developfrom
feat/stack-feature-flag-start-stop
Sep 9, 2026
Merged

feat(cli): select stack start and stop with feature flag#6544
jgoux merged 4 commits into
developfrom
feat/stack-feature-flag-start-stop

Conversation

@jgoux

@jgoux jgoux commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Expose the new local runtime as supabase stack start|stop. Projects can opt top-level start and stop into that runtime with [experimental] stack = true in supabase/config.toml, or override it with SUPABASE_EXPERIMENTAL_STACK=1|0. Selection happens before argument parsing and completion, preserving each implementation’s flags and the invoked command’s telemetry identity. Unreadable or invalid routing config defaults to the legacy command tree; explicit environment overrides take precedence, and each command retains its own execution-time config validation.

The shared experimental flag resolver is reusable for the later workers migration. status keeps its existing implementation and experimental workers remains available. The two stack backends retain separate state and databases; enabling the flag does not migrate existing data. The flag is excluded from hosted project configuration and accepted as a TypeScript-owned field by the Go sidecar.

Extracts the start/stop portion of #6516 onto develop after #6507, so it can merge independently of the remaining stack commands.

Regenerates the published configuration schemas, including previously stale auth fields already present in the source schemas. Refreshes stale Go config fixtures to match the current serializer and schema.

@jgoux
jgoux requested a review from a team as a code owner September 9, 2026 12:14

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🤖 AI Review

The PR has one critical compatibility break: the published experimental.stack key is rejected by the bundled Go sidecar, breaking delegated commands for users who enable the documented setting. Confirmed minor issues include incorrect completion routing, silently discarded completion-routing errors, help depending on valid config, inconsistent boolean-env parsing, duplicate root-tree construction, and command ordering. Three Claude findings were refuted because the documentation already states the alias-only scope, the resolver branches are covered and its exported error is required by trusted conventions, and the backend remains explicitly experimental despite its renamed command path.

Findings

Severity Location Category Sources Claim
🔴 CRITICAL packages/config/src/experimental.ts:35 compatibility claude The new experimental.stack key is absent from the bundled Go config model, so Go-delegated commands that load a config containing it fail UnmarshalExact.
🟡 MINOR apps/cli/src/command-internal/experimental-feature.ts:28 consistency claude SUPABASE_EXPERIMENTAL_STACK rejects conventional boolean spellings such as true and false, unlike related config boolean overrides.
🟡 MINOR apps/cli/src/cli/root.ts:93 cli-parity claude stackCommand is declared out of alphabetical order, affecting declaration-order consumers such as help and generated documentation.
🟡 MINOR apps/cli/src/commands/experimental/stack/stack-backend.ts:100 error-handling claude Top-level start and stop help now requires routing config to parse successfully, so malformed config prevents --help from rendering.
🟡 MINOR apps/cli/src/cli/main.ts:26 error-handling claude+codex Completion routing failures are silently discarded, and the new entrypoint failure wiring lacks direct coverage.
🟡 MINOR apps/cli/src/cli/main.ts:23 performance claude Normal invocations construct the full root command tree twice.
🟡 MINOR apps/cli/src/commands/experimental/stack/stack-backend.ts:103 completion-routing codex Hidden completion argv is interpreted as execution argv, causing root completion to read config and help-path completion to select the wrong backend.
⚪ NIT apps/cli/src/commands/experimental/stack/stack-backend.ts:69 error-handling claude TOML syntax errors are mislabeled as config read failures.
⚪ NIT apps/cli/src/docs/docs-spec.tables.ts:143 style claude The new default-override entries violate the table's alphabetical ordering.
⚪ NIT apps/cli/src/cli/root.ts:71 observability claude Top-level stack aliases emit the legacy start/stop command identity without any telemetry field identifying the selected backend.
⚪ NIT apps/cli/src/commands/experimental/stack/stack-command-telemetry.integration.test.ts:26 style claude The test imports a sibling module through a needlessly roundabout path.
⚪ NIT apps/docs/public/cli/config.schema.json:996 maintainability claude The generated schema changes include unrelated pre-existing source drift.
Refuted findings (kept for transparency, not posted as review comments)
  • apps/cli/docs/stack-commands.md:44 (documentation): The documentation fails to disclose that only start and stop are switched, leaving users with an undocumented split between local backends.
    Refuted: The cited guide explicitly discloses both the alias-only scope and separate backend state. Enumerating every unaffected local command could improve the guide but is not an undisclosed behavior.
  • apps/cli/src/command-internal/experimental-feature.ts:8 (test-coverage): The exported error and shared experimental resolver are unused or inadequately tested.
    Refuted: The export is a trusted repository requirement, not dead API, and the integration suite covers the resolver's relevant branches through its production caller.
  • apps/cli/src/commands/experimental/stack/stack-config.ts:707 (documentation): The phrase experimental stack is stale now that the command moved to supabase stack.
    Refuted: Removing experimental from the invocation path does not establish that the backend itself is no longer experimental; the feature remains explicitly controlled by the experimental config section.

Stats

Claude findings: 14 · Codex findings: 2 · Confirmed: 12 · Refuted: 3 · Uncertain: 0


Models: claude-opus-5 + gpt-5.6-sol · Trigger: auto · Workflow run

This review runs once per PR. A maintainer can request another with a /ai-review comment.

Comment thread packages/config/src/experimental.ts
Comment thread apps/cli/src/command-internal/experimental-feature.ts
Comment thread apps/cli/src/cli/root.ts Outdated
Comment thread apps/cli/src/commands/experimental/stack/stack-backend.ts Outdated
Comment thread apps/cli/src/cli/main.ts
Comment thread apps/cli/src/docs/docs-spec.tables.ts Outdated
Comment thread apps/cli/src/cli/root.ts
Comment thread apps/docs/public/cli/config.schema.json
Comment thread apps/cli/src/commands/experimental/stack/stack-backend.ts
@Coly010 Coly010 assigned Coly010 and unassigned Coly010 Sep 9, 2026

@Coly010 Coly010 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ran this through parallel architecture, implementation, and DX reviews. The pre-parse backend-selection mechanism itself (lazy config reads, typed routing errors, completion-cursor handling, preserved telemetry identity) is well-built. The problems are all in what happens once someone actually flips experimental.stack = true — inline comments below cover the specific spots, and this summarizes what doesn't map to a single line:

No signposting when the backend switches. supabase start/stop with the flag on produce a completely different output shape (a Stack <id> / Runtime / Lifecycle block instead of the usual API URL / anon key table) with nothing printed anywhere saying "this is the experimental stack backend" or "your legacy stack's data is untouched." A user flipping the flag has no way to tell this from data loss.

The rest of local dev doesn't follow the flag. status, db reset, and db diff stay bound to the legacy Docker stack regardless of experimental.stack, so with the flag on, supabase start (new stack) followed by supabase status (legacy) reports nothing running. None of this is documented in docs/stack-commands.md, which only mentions status in passing.

stack stop doesn't know about a legacy stack from the same project. If a legacy stack is running when the flag gets flipped on, supabase stop (now routed to the stack backend) exits 0 having found nothing to do, while the legacy containers keep the port bound — so the next supabase start fails with a PortUnavailableError that never mentions the other backend is the actual cause.

Docs ordering. docs/stack-commands.md buries the "backends don't share data" caveat at the bottom in defensive phrasing ("does not import, copy, seed from, or reuse") instead of leading with it, and references a command path (supabase experimental stack) that only ever existed in an unreleased beta — likely to confuse rather than help.

Scope creep. The 14 apps/cli-go/pkg/config/testdata/*.diff fixture updates plus the db_test.go/updater_test.go changes fix pre-existing drift (a db_allowed_cidrsallowed_cidrs rename, a swapped diff direction, a deleted gock stub) unrelated to stack routing — worth splitting into its own PR so a reviewer of a start/stop feature flag isn't also on the hook for auth/network-restrictions fixture correctness.

Given the number of user-facing regressions once the flag is actually used, I'd want at minimum the flag-stripping diagnostic, the --help/malformed-config interaction, and the config-loader bypass (comments below) resolved before merge.

Comment thread apps/cli/src/cli/root.ts
Comment thread apps/cli/src/cli/main.ts
Comment thread apps/cli/src/commands/experimental/stack/stack-backend.ts
Comment thread apps/cli/src/commands/experimental/stack/stack-backend.ts
Comment thread apps/cli/src/commands/experimental/stack/stack-backend.ts Outdated
Comment thread apps/cli/src/command-internal/experimental-feature.ts
Comment thread apps/cli/src/commands/experimental/stack/stack.command.ts Outdated
Comment thread apps/cli/src/docs/docs-spec.tables.ts
Comment thread apps/cli/src/commands/stop/SIDE_EFFECTS.md
@jgoux

jgoux commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the detailed review. This PR is the foundation for the new local stack: status and the remaining local-stack commands will migrate in follow-up PRs before the feature flag is promoted. Backend-specific arguments and flags are intentional, and each backend continues to own its own resources. We are not adding temporary cross-backend compatibility behavior or migration banners for this intermediate state.

This revision fixes short-cluster routing, defaults unresolved config-based routing to legacy, and clarifies experimental status and configuration reads. Local TOML-only loading, remote-selection behavior, and the 1|0 environment contract remain unchanged for the reasons in the inline replies.

The fixture-only Go repairs are retained so the full nested config module suite passes; they align stale fixtures with existing serializers and do not change runtime behavior.

@jgoux
jgoux added this pull request to the merge queue Sep 9, 2026
Merged via the queue into develop with commit ab5cffc Sep 9, 2026
37 checks passed
@jgoux
jgoux deleted the feat/stack-feature-flag-start-stop branch September 9, 2026 21:55
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