Skip to content
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
993caf3
feat(cli): port supabase stop and status commands to native TypeScript
Coly010 Jul 2, 2026
491f052
test(cli): add live tests for supabase stop/status and document *.liv…
Coly010 Jul 2, 2026
deaf1e6
fix(cli): address Go-parity review findings on stop/status (review: #…
Coly010 Jul 2, 2026
d362f41
fix(cli): honor image-name exclusions in status (review: PRRT_kwDOErm…
Coly010 Jul 2, 2026
1b42381
Merge remote-tracking branch 'origin/develop' into cli/port-stop-stat…
Coly010 Jul 2, 2026
4cfa1ec
fix(cli): treat empty --project-id as unset in stop (review: PRRT_kwD…
Coly010 Jul 2, 2026
db0ea33
fix(cli): CSV-split status StringSlice flags (review: PRRT_kwDOErm0O8…
Coly010 Jul 2, 2026
003c83f
fix(cli): reject short jwt secrets in status (review: PRRT_kwDOErm0O8…
Coly010 Jul 2, 2026
d74f043
fix(cli): honor SUPABASE_AUTH_* env overrides in status keys (review:…
Coly010 Jul 2, 2026
6841019
fix(cli): sign status keys with asymmetric signing keys when configur…
Coly010 Jul 2, 2026
9a38255
fix(cli): validate JWK kty/curve before asymmetric signing
Coly010 Jul 2, 2026
e74201b
refactor(cli): resolve status state once instead of calling legacySta…
Coly010 Jul 2, 2026
60877ba
fix(cli): match Go's signing-keys error wording and add missing integ…
Coly010 Jul 2, 2026
7574db6
fix(cli): preserve real Docker error text in status/stop container in…
Coly010 Jul 2, 2026
1cc8deb
fix(cli): print stop's "Stopping containers..." unconditionally (ci: …
Coly010 Jul 2, 2026
ad5c212
test(cli-test-helpers): ignore Docker client negotiation noise in par…
Coly010 Jul 2, 2026
bd2fee9
fix(cli): apply SUPABASE_AUTH_SIGNING_KEYS_PATH env override to statu…
Coly010 Jul 2, 2026
fb10163
fix(cli): resolve SUPABASE_PROJECT_ID from supabase/.env for stop and…
Coly010 Jul 2, 2026
2395187
fix(cli): omit Docker-only --all from Podman's volume prune in stop (…
Coly010 Jul 3, 2026
c0d1e5d
fix(cli): resolve project-root/SUPABASE_ENV dotenv values in stop/sta…
Coly010 Jul 3, 2026
8cf349e
fix(cli): preserve env-specific dotenv precedence and fail on malform…
Coly010 Jul 3, 2026
3b114c2
fix(cli): resolve project env values before decoding config.toml in s…
Coly010 Jul 3, 2026
f9768ba
fix(cli): skip signing-key file reads in status when auth is disabled…
Coly010 Jul 3, 2026
00a85de
Merge remote-tracking branch 'origin/develop' into cli/port-stop-stat…
Coly010 Jul 6, 2026
40e948d
fix(cli): expand $VAR/${VAR} refs in stop/status dotenv files to matc…
Coly010 Jul 6, 2026
a9d944c
fix(cli): harden stop's Docker CLI calls against pipe deadlock and pr…
Coly010 Jul 6, 2026
36e2ad2
fix(cli): preserve literal # in project-env dotenv values to match go…
Coly010 Jul 6, 2026
11e8937
fix(cli): let status -o pretty win over --output-format (review: #5765)
Coly010 Jul 6, 2026
b903a13
Merge remote-tracking branch 'origin/develop' into cli/port-stop-stat…
Coly010 Jul 6, 2026
e360260
test(cli): cover --exclude/--ignore-health-check merge semantics on n…
Coly010 Jul 6, 2026
e8fdbbb
fix(cli): match godotenv's quoted-value and colon-separator parsing i…
Coly010 Jul 6, 2026
e865fcc
fix(config): preserve env() literal when the referenced var is set bu…
Coly010 Jul 6, 2026
de74ef1
fix(cli): apply SUPABASE_* env overrides to db/studio/mailpit/api por…
Coly010 Jul 6, 2026
3242e54
fix(cli): read stop/status dotenv overrides even when config.toml is …
Coly010 Jul 6, 2026
ae68ba5
fix(cli): treat --workdir as an exact, non-searching project root in …
Coly010 Jul 6, 2026
e2a278c
fix(cli): apply SUPABASE_API_TLS_ENABLED to status/stop URL scheme (r…
Coly010 Jul 6, 2026
aff9ff0
fix(cli): apply SUPABASE_AUTH_ENABLED before status/stop signing-key …
Coly010 Jul 6, 2026
81811c0
fix(cli): read Docker's Running boolean instead of deriving it from S…
Coly010 Jul 6, 2026
844f448
fix(cli): apply SUPABASE_*_ENABLED overrides to every status gate and…
Coly010 Jul 6, 2026
b1f28da
fix(cli): preserve backslash-escaped $VAR references in extra dotenv …
Coly010 Jul 6, 2026
df513cb
fix(cli): reject malformed SUPABASE_*_ENABLED bool env overrides (rev…
Coly010 Jul 6, 2026
9f8a784
fix(cli): parse --override-name before touching config or Docker in s…
Coly010 Jul 6, 2026
866daf0
fix(cli): reject a zero SUPABASE_DB_PORT override (review: #5765)
Coly010 Jul 6, 2026
31b5025
fix(cli): validate status config before any Docker probe (review: #5765)
Coly010 Jul 6, 2026
46d0a88
fix(cli): treat stop --all=false as mutually exclusive with --project…
Coly010 Jul 6, 2026
b081bbd
fix(config): match Go's case-agnostic env() reference pattern (review…
Coly010 Jul 6, 2026
f4b4292
fix(cli): validate api.tls cert/key pairing before status prints URLs…
Coly010 Jul 6, 2026
21ac0c7
fix(cli): preserve multiline quoted dotenv values in stop/status extr…
Coly010 Jul 6, 2026
a7081ba
fix(cli): reject auth-enabled configs with an empty site_url before s…
Coly010 Jul 6, 2026
dd36f4b
fix(cli): validate db.major_version and api.port before status render…
Coly010 Jul 6, 2026
c0faae5
fix(cli): validate config before default stop, matching Go's flags.Lo…
Coly010 Jul 6, 2026
f2a35d0
fix(cli): resolve relative --workdir/SUPABASE_WORKDIR to an absolute …
Coly010 Jul 6, 2026
622a066
fix(cli): reject zero studio/local_smtp ports and invalid deno_versio…
Coly010 Jul 6, 2026
c36a9e2
fix(cli): load config.toml only for legacy status/stop, matching Go's…
Coly010 Jul 6, 2026
d3838ed
fix(config): preserve env() literal for present-but-empty vars in def…
Coly010 Jul 6, 2026
f97b0a1
fix(cli): validate auth.captcha and analytics/bigquery config for sta…
Coly010 Jul 6, 2026
2fc16a2
fix(config): accept Go's full boolean spelling set for env()-substitu…
Coly010 Jul 6, 2026
88aa0fa
fix(config): parse multiline quoted .env values in loadProjectEnviron…
Coly010 Jul 6, 2026
1db573a
fix(config): reject duplicate remote project_id even without a projec…
Coly010 Jul 6, 2026
5262a1f
fix(config): reject malformed remote project refs, matching Go's Conf…
Coly010 Jul 6, 2026
39d5a3b
fix(cli): reject an explicit --workdir/SUPABASE_WORKDIR that isn't a …
Coly010 Jul 6, 2026
a4aa017
fix(cli): reject an explicit empty project_id, matching Go's Config.V…
Coly010 Jul 6, 2026
a0e5cb6
fix(cli): port missing Config.Validate checks to status/stop resolver…
Coly010 Jul 6, 2026
f21ab35
fix(cli): validate auth.third_party providers in status/stop resolver…
Coly010 Jul 6, 2026
8e7610b
fix(cli): validate experimental config in status/stop resolver (revie…
Coly010 Jul 6, 2026
1a48c6d
fix(cli): validate auth email template content_path in status/stop re…
Coly010 Jul 6, 2026
4c7dd3b
fix(cli): validate studio.api_url via a Go-parity net/url.Parse port …
Coly010 Jul 6, 2026
6b8d4e9
fix(cli): enforce passkey/WebAuthn requirement in status/stop resolve…
Coly010 Jul 6, 2026
0461e35
fix(cli): treat present SMTP table as enabled and validate SUPABASE_A…
Coly010 Jul 6, 2026
46916aa
fix(config): strip deprecated auth.external.{linkedin,slack} before s…
Coly010 Jul 6, 2026
9518a79
fix(cli): backfill RSA CRT params so signing keys without dp/dq/qi ve…
Coly010 Jul 6, 2026
c902298
fix(cli): resolve env() indirection inside SUPABASE_* overrides (revi…
Coly010 Jul 6, 2026
cd1b7c3
fix(config): match remotes before env() interpolation, not after (rev…
Coly010 Jul 6, 2026
b15c7dd
fix(cli): resolve status host from the active Docker context (review:…
Coly010 Jul 6, 2026
5907b69
fix(cli): skip supabase/.env.local under SUPABASE_ENV=test to match G…
Coly010 Jul 6, 2026
09e218a
fix(config): split string values into slices for array-typed config f…
Coly010 Jul 6, 2026
5964d2e
fix(config): scope Go viper decode semantics behind goViperCompat opt-in
Coly010 Jul 7, 2026
4956817
fix(cli): opt legacy config loading into goViperCompat Go parity sema…
Coly010 Jul 7, 2026
4086791
cleanup(cli): add legacy-config-validate as the single home for Confi…
Coly010 Jul 7, 2026
49fc64a
cleanup(cli): route status/stop config validation through legacy-conf…
Coly010 Jul 7, 2026
0c62a91
fix(cli): validate db config through legacy-config-validate, correcti…
Coly010 Jul 7, 2026
4515e13
cleanup(cli): consolidate validation tests and add cross-caller parit…
Coly010 Jul 7, 2026
b257e20
docs(cli): declare legacy-config-validate the single home for Config.…
Coly010 Jul 7, 2026
19a750e
Merge remote-tracking branch 'origin/develop' into cli/port-stop-stat…
Coly010 Jul 7, 2026
2ddbeb5
fix(cli): opt legacySeedBucketsRun into goViperCompat after seed-buck…
Coly010 Jul 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions apps/cli/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@ Read https://www.effect.solutions/testing for Effect testing patterns. Note that
- `*.unit.test.ts` belongs to the `unit` Vitest project and is the default for unit-style and other fast in-process tests.
- `*.integration.test.ts` belongs to the `integration` project and is for in-process integration tests that exercise real handler or service behavior with layered dependency replacement.
- `*.e2e.test.ts` belongs to the `e2e` Vitest project and is for black-box CLI subprocess tests.
- `*.live.test.ts` belongs to the `live` Vitest project and is for black-box CLI subprocess tests that run against a **real, running Supabase platform or local Docker stack** — see "Live tests" below.

### Testing policy

Expand All @@ -416,6 +417,21 @@ Read https://www.effect.solutions/testing for Effect testing patterns. Note that
- Keep `*.e2e.test.ts` focused on golden paths, CLI surface behavior, and subprocess correctness, not branch-by-branch coverage.
- **Forbidden pattern (do not add):** spawning the CLI to assert that `--help` renders a flag. Help text is dynamic over flag wiring and is exercised by the integration test's flag parser. The two backups e2e files removed alongside this guidance update are the canonical example of what not to write.

### Live tests (`*.live.test.ts`)

Live tests are black-box CLI subprocess tests — like `*.e2e.test.ts`, but run against a **real backend** instead of local fakes/mocks: either the real Management API (a full [supabox](https://github.com/supabase/supabox) platform stack) or a real local Docker dev stack (`supabase start`'s actual containers). They are the highest-fidelity, most expensive tier — reserved for the small set of behaviors that only a genuinely running backend can prove (auth round-trips, real Docker label filtering, real container lifecycle), not for anything an integration test can already cover with mocks.

- **Where they run:** authored in this repo, but executed by the [`supabase/cli-e2e-ci`](https://github.com/supabase/cli-e2e-ci) harness, which builds this CLI, brings up a full supabox stack (and has a real Docker daemon, since that's how supabox itself runs), and invokes the `live` Vitest project (`nx run-many -t test:live`). They never run as part of the default unit/integration/e2e loop, and locally they no-op unless the live environment is configured (see below) — there is no need to stand up supabox yourself to develop other code.
- **Add one whenever you add or change a command whose correctness genuinely depends on a real backend** — a new Management API command, or a change to `start`/`stop`/`status`'s real Docker interaction. Colocate it with the command, same as `*.e2e.test.ts`: `src/legacy/commands/<command>/[<subcommand>/]<subcommand>.live.test.ts`.
- **Gating:** every live suite must be wrapped in one of `tests/helpers/live.ts`'s `describe.skipIf` gates so the file is inert (skipped, not failed) outside the cli-e2e-ci runner:
- `describeLive` — runs whenever `SUPABASE_ACCESS_TOKEN` is set (the live env is configured at all). Reuse this even for commands that don't call the Management API themselves (e.g. `stop`/`status`) — it doubles as the "we're in the full cli-e2e-ci runner, which also has a real Docker daemon" signal, and there is no dedicated Docker-availability gate today.
- `describeLiveProject` — additionally requires a provisioned project (`SUPABASE_LIVE_PROJECT_REF`); use for project-scoped Management API commands (branches, functions, project-scoped db).
- `describeLiveDataPlane` — additionally requires the project's own Postgres instance to be `ACTIVE_HEALTHY`; use for commands that talk to the project's data plane (migration, db, storage).
- **Invocation:** use `runSupabaseLive(args, options?)` (wraps `runSupabase` with the `legacy` entrypoint and the live profile/timeout defaults) rather than calling `runSupabase` directly, so every live test picks up the same environment plumbing.
- **Local-dev-stack live tests** (`start`/`stop`/`status`, and anything else that manages real Docker containers rather than calling the Management API) follow the same file/gating convention but don't need `SUPABASE_PROFILE`/project-ref machinery. Pattern: `mkdtemp` a project dir, `runSupabaseLive(["init"], { cwd })` to generate a real Go-schema `config.toml`, `runSupabaseLive(["start", ...])` to bring up (a lightweight subset of) the real stack, exercise the command under test, then clean up in `afterEach` (best-effort `stop --no-backup` + `rm` the temp dir) so a failed assertion never leaks containers onto the CI runner. See `commands/stop/stop.live.test.ts` and `commands/status/status.live.test.ts` for the canonical example.
- **Keep the suite small and golden-path only** — same philosophy as `*.e2e.test.ts`, but even more so given the cost of a real backend. One or two scenarios per command is normal; branch-by-branch coverage belongs in `*.integration.test.ts`.
- Timeouts are generous by default (`testTimeout`/`hookTimeout: 300_000` for the whole `live` project) because real platform/Docker operations are slow — pass an explicit per-`test()` timeout when a scenario needs less (or, for a real local-stack `start`, close to the full budget).

---

## Go CLI Parity Tracking
Expand Down
4 changes: 2 additions & 2 deletions apps/cli/docs/go-cli-porting-status.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,8 +269,8 @@ Legend:
| `init` | `ported` | [`../src/legacy/commands/init/init.command.ts`](../src/legacy/commands/init/init.command.ts) |
| `services` | `ported` | [`../src/legacy/commands/services/services.command.ts`](../src/legacy/commands/services/services.command.ts) |
| `start` | `wrapped` | [`../src/legacy/commands/start/start.command.ts`](../src/legacy/commands/start/start.command.ts) |
| `stop` | `wrapped` | [`../src/legacy/commands/stop/stop.command.ts`](../src/legacy/commands/stop/stop.command.ts) |
| `status` | `wrapped` | [`../src/legacy/commands/status/status.command.ts`](../src/legacy/commands/status/status.command.ts) |
| `stop` | `ported` | [`../src/legacy/commands/stop/stop.command.ts`](../src/legacy/commands/stop/stop.command.ts) — native; talks directly to Docker/Podman via subprocess, replicating Go's label-filter and container-naming scheme |
| `status` | `ported` | [`../src/legacy/commands/status/status.command.ts`](../src/legacy/commands/status/status.command.ts) — native; talks directly to Docker/Podman via subprocess, replicating Go's label-filter and container-naming scheme |
| `telemetry enable` | `ported` | [`../src/legacy/commands/telemetry/enable/enable.command.ts`](../src/legacy/commands/telemetry/enable/enable.command.ts) |
| `telemetry disable` | `ported` | [`../src/legacy/commands/telemetry/disable/disable.command.ts`](../src/legacy/commands/telemetry/disable/disable.command.ts) |
| `telemetry status` | `ported` | [`../src/legacy/commands/telemetry/status/status.command.ts`](../src/legacy/commands/telemetry/status/status.command.ts) |
Expand Down
Loading
Loading