chore(monorepo): consolidate repos CLI-1408#5168
Open
Conversation
Release channels
* first command design * first command design * test coverage setup * refactor * hello Effect * agents doc * use env from Effect * convert everything to Effect * CliConfig * construct url correctly * tests * reuse mocks * isolate code * refactor command type * docs generation * --usage convention * skills support * bump * fumadocs * bump * use new global flags API * mirror old cli reading patterns * services are fully covered now * effect patterns * process compose, the Effect way! * process-compose the Effect way * unless stopped and timeout * hook output and global shutdown timeout * feat(local): scaffold @supabase/local package Add the packages/local workspace package with package.json, tsconfig.json, and src/index.ts placeholder. Wires in workspace dependency on @supabase/process-compose and the same Effect pre-release URLs as process-compose. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(local): add typed error definitions for local stack management Implements 5 tagged error types (BinaryNotFoundError, DownloadError, ChecksumMismatchError, StackBuildError, PortConflictError) using Effect's Data.TaggedError pattern and exports them from index.ts. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(local): add platform detection with asset name mapping Implements PlatformInfo type, detectPlatform Effect, and pure mapping functions (postgresAssetName, postgrestAssetName, authAssetName) for resolving binary asset names per OS/arch combination. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(local): add service definition factories for postgres, postgrest, and auth Pure factory functions that produce ServiceDef objects for process-compose. Includes TDD with vitest tests covering all four factory variants (native and Docker auth). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(local): add StackBuilder service; refactor buildGraph to return Effect - Refactor `buildGraph` in process-compose to return `Effect.Effect<ResolvedGraph, CyclicDependencyError | MissingDependencyError>` instead of throwing - Update all callers (DependencyGraph.test.ts, Orchestrator.test.ts, Orchestrator.e2e.test.ts) to use `Effect.runSync(buildGraph(defs))` - Create `packages/local/src/StackBuilder.ts` with `StackConfig` interface and `StackBuilder` service that resolves binaries, falls back to Docker for auth, filters excluded services, and calls `buildGraph` - Create `packages/local/tests/helpers/mocks.ts` with `mockBinaryResolver` factory - Create `packages/local/src/StackBuilder.test.ts` with 3 integration tests (native binaries, docker fallback, exclude) - Export `StackBuilder` and `StackConfig` from `packages/local/src/index.ts` Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(local): add LocalStack service with JWT generation and Orchestrator wiring Implements the main LocalStack Effect service that wires StackBuilder -> Orchestrator and exposes start/stop/restart, connection info, and HS256 JWT token generation for anon and service_role keys. Includes integration tests covering URL construction, JWT structure validation, and signature verification. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(local): add createStack convenience API with Promise-based wrapper Wraps all Effect machinery behind a single async function for ergonomic use in tests and non-Effect code; exports Stack and CreateStackOptions types from the package index. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(cli): add start command wired to LocalStack service Adds the `supabase start` command that will drive the local Supabase development stack. The command definition, handler, and barrel index are created following the login command pattern. A placeholder LocalStack layer is provided at the command level so all type requirements are satisfied at compile time; it will be replaced with the real LocalStack.layer(config) once config.toml parsing is wired up. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * add integration tests for start command and mockLocalStack helper Adds mockLocalStack factory to test helpers with stateful started/stopped tracking and Stream.empty for allStateChanges so tests complete without hanging. Creates three integration tests covering stack startup, info message content, and custom URL configuration. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(local): add BinaryResolver service with download, cache, and checksum verification Also clean up knip ignoreDependencies now that packages are in use. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add @supabase/local design and implementation plan Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address code review findings for @supabase/local - StackBuilder skips binary resolution for excluded services instead of resolving eagerly then disabling - BinaryResolver uses descriptive url field in error wrapping instead of misleading service name or hardcoded "checksum" - Start handler test covers state stream changes for 100% branch coverage Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * local package * local stack * simplify port allocation * simplify port allocation * refactor * properly handle docker shutdown for postgres * bump * detach feature * optimize probes * atom / ink integration * fix stack resource cleanup Harden stack shutdown so foreground, detached, and one-shot paths clean up child processes, Docker containers, state, and auto-managed data directories reliably across the CLI and stack layers. Made-with: Cursor * make process supervision platform-neutral Move service ownership and orphan cleanup into @supabase/process-compose so stack resources are torn down consistently across Unix and Windows without shell wrappers. Update CLI start handling, leak regressions, and internal docs to verify the new supervision model across foreground and detached flows. Made-with: Cursor * remove legacy probe and shutdown paths Tighten process-compose around the supervised ownership model so shell-style exec probes and unsupervised group-kill semantics cannot silently slip back in. Made-with: Cursor * attach is detach in disguise :) * minimize node usage * fix binary cache prewarm * symlink claude * reorganize files * refactor * avoid leaks in tests * fix regression * refactor * refactor * refactor * reorganize code * comments * reorganize files * calm down knip * bump --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This pull request adds several external repositories as Git submodules to the project, making it easier to manage and work with upstream dependencies. It also updates documentation and scripts to help developers set up and keep these submodules up to date. Repository integration: * Added multiple repositories as Git submodules under the `.repos/` directory by updating the `.gitmodules` file and adding submodule commits for each external project. This includes `effect`, `effect-patterns`, `effect-v3`, `lalph`, `cheffect`, `process-compose`, `supabase-cli-go`, and `t3code`. [[1]](diffhunk://#diff-fe7afb5c9c916e521401d3fcfb4277d5071798c3baf83baf11d6071742823584R1-R24) [[2]](diffhunk://#diff-bf30b8a3b1abe655f15c78356d0c42f26facd475b0c0cc84dfa0978b3ba6f52eR1) [[3]](diffhunk://#diff-71808e294879f14b57f9ad92458b8bedf2444cffff996338213e69b04bcfad7fR1) [[4]](diffhunk://#diff-278b86c606260e1ef5538df5f2b24772e6d53f6aca56d73354a63b444b26c060R1) [[5]](diffhunk://#diff-1ef73efa15d867ca9efc210cd2af677813d5f6c01b807308e5964244cf53b84eR1) [[6]](diffhunk://#diff-c098fe325b76c0187c9c0ed50980fdbf04b6e095a7d9d4156348aa157a4b3bd4R1) [[7]](diffhunk://#diff-966c92336ec631dc3bde774d65e7352be0ba3a038df5ce2a9b0e1e94e400b3d0R1) [[8]](diffhunk://#diff-9e63a8682fe0fa0da4fd10db208cb424965804a6a461ec07cdf3d7725b367012R1) [[9]](diffhunk://#diff-db5fcf3013401fac32cf2685e57b439e6e7562dbbc811b15278eebf359193277R1) Developer experience improvements: * Updated the `README.md` with setup instructions for installing dependencies and initializing submodules, making onboarding easier for new contributors. * Added a note to `AGENTS.md` explaining how to initialize submodules if the `.repos/effect/` directory is missing after cloning the repository. Script updates: * Added a `repos:install` script to `package.json` for initializing submodules, and updated the `repos:pull` script to use `git submodule update --remote` for keeping submodules up to date.
## Summary This PR brings the new TypeScript local stack much closer to old CLI parity by porting the remaining legacy Docker-backed services into `@supabase/stack`, wiring them into the CLI, and tightening the persistence/runtime model for named stacks. In practice, this means: - the CLI can now start the full local Supabase service set we support in TS, without relying on the old Go implementation - named stacks now persist their state/data under `SUPABASE_HOME/stacks/<name>` and keep stable owned ports across restarts - programmatic `createStack()` stays ephemeral by default - daemon runtime files now live under a short runtime root, which avoids Unix socket path-length issues Kong remains out of scope because we already replaced it with the JS proxy. Edge Runtime also remains out of scope for this pass. ## What changed ### Ported legacy Docker-backed services into `@supabase/stack` Added Docker-backed support for the old CLI services that were still missing from the TS stack: - `realtime` - `storage` - `imgproxy` - `mailpit` - `pgmeta` - `studio` - `analytics` - `vector` - `pooler` This includes: - pinned image/version support in the version manifest - service factories under `packages/stack/src/services` - dependency wiring in the stack graph - startup validation for unsupported/invalid combinations The newly ported services are still Docker-only in this branch. Native binaries remain limited to the services we already supported natively. ### Expanded stack modes and CLI defaults The stack/runtime split is now more explicit: - `createStack()` defaults to `mode: "native"` - CLI `start` uses `mode: "auto"` - CLI `start` enables the full legacy-compatible service set by default, excluding Kong and Edge Runtime This keeps the library lean by default while making the CLI behave more like the old local Supabase experience. ### Replaced missing Kong-era routes in the JS proxy Extended the JS proxy so the new services are reachable through the expected local API surface, including: - GraphQL - Realtime - Storage - PgMeta - Analytics - Pooler - OAuth discovery - MCP This lets us continue avoiding Kong while still exposing the old local endpoints. ### Added sticky port ownership for named stacks Named stacks now persist their allocated host ports and treat them as owned by that stack until it is explicitly deleted. Behavior: - first start prefers the old CLI’s default exposed ports when available - subsequent starts reuse the saved full port set - other named stacks do not steal those ports, even if the original stack is currently stopped - explicit user ports still fail if they conflict with another stack’s saved ownership This makes restart behavior much more predictable for CLI-managed stacks. ### Split cache root, stack root, and runtime root The old `home` concept was doing too much. This PR separates it into: - `cacheRoot`: shared binary/cache location - `stackRoot`: persistent stack state/data - `runtimeRoot`: short-lived runtime files like the daemon socket Defaults now look like: - CLI / named stacks: - `cacheRoot = ~/.supabase` - `stackRoot = ~/.supabase/stacks/<name>` - `runtimeRoot = /tmp/...` short hashed path - bare `createStack()`: - shared cache root - random ephemeral stack root - random short runtime root This also moves the daemon socket out of the persistent stack directory, which fixes the Unix socket path-length issue that can happen with long paths. ### Added `supabase stop --no-backup` The CLI now supports the old `--no-backup` flag again. Behavior: - `supabase stop` stops the stack and keeps persisted state/data - `supabase stop --no-backup` stops the stack and deletes its persisted folder under `SUPABASE_HOME/stacks/<name>` This includes deleting runtime state, durable port ownership metadata, and stack data. ### Startup/bootstrap and test harness fixes A number of follow-up fixes were needed to make the larger stack actually start reliably: - healthcheck and service startup fixes for several Docker-backed services - bootstrap/schema setup needed by services like analytics/realtime/pooler - JWT/JWKS generation needed by services that expect it - Postgres/runtime configuration updates needed by the expanded service set - CLI test harness cleanup to use `SUPABASE_HOME` instead of overriding `HOME` - short temp roots in CLI tests to avoid Bun/macOS path issues ## User-facing impact For CLI users: - `supabase start` can now bring up the full supported local service set - named stacks persist data under `SUPABASE_HOME/stacks/<name>/data` - named stacks keep stable ports across stop/start - `supabase stop --no-backup` deletes persisted local stack state For library users: - `createStack()` remains ephemeral by default - binary cache stays shared - runtime/data paths are cleaner and more intentional - the config model now separates cache, persistent state, and runtime files
## Summary This PR introduces a new generated `@supabase/api` package for the Supabase Management API and rewires the CLI `platform` command surface to build dynamically from that SDK + exported OpenAPI metadata instead of relying on a checked-in generated command tree. On the CLI side, this keeps `@supabase/api` focused on typed SDK concerns while letting `@supabase/cli` own command naming, UX, schema/dry-run behavior, and output formatting. ## What changed ### `@supabase/api` - adds a new generated Management API SDK package - generates and exports: - typed contracts / schemas - `operationDefinitions` - generated Effect operations - runtime-specific clients for `bun` and `node` - raw `openapi.json` - `openApiOperationIdMap` for joining raw OpenAPI operations back to SDK operation ids - replaces the previous large handwritten `v1.d.ts`-style surface with generated SDK artifacts and runtime clients - adds tests around public entrypoints and client behavior ### CLI `platform` commands - replaces the old CLI-side OpenAPI/codegen pipeline with a dynamic runtime-generated `platform` tree - builds platform command metadata from: - `@supabase/api/openapi.json` - `openApiOperationIdMap` - SDK operation definitions / execution - removes the need for a checked-in generated forest of platform command files - adds CLI-owned command path normalization and conflict detection - covers all supported platform operations, including previously missing bulk endpoints ### Request/input/schema UX - supports richer request body handling: - JSON object bodies via `--json` - non-object JSON / multipart / binary / urlencoded bodies via `--body` - path/query/header input via `--params` - improves schema inspection and dry-run flows - fixes string-only OpenAPI unions so fields like `branch_id_or_ref` prompt as plain text instead of JSON - improves platform input errors so suggestions point to the exact command and `--schema` usage - fixes misleading `--json` guidance for params-only commands ### Text output / interaction polish - removes noisy generic success banners where they don’t add value - adds a task/spinner-style output abstraction in the CLI output layer - improves multiline task completion rendering so continuation lines keep the left guide rail - makes text-mode dry-run output neutral by rendering the preview directly without a success banner ### Docs and test coverage - adds documentation for how dynamic platform command generation works - adds metadata, tree, input, schema, body-shape, integration, and e2e coverage for the new platform flow ## Why - keep `@supabase/api` as the single typed Management API SDK - avoid duplicating OpenAPI parsing / generation logic inside the CLI - make platform command ownership clearer in `@supabase/cli` - improve maintainability by replacing hundreds of generated command files with a smaller runtime metadata pipeline - improve command UX around prompting, dry-run, schema inspection, and output formatting ## Testing Validated with workspace checks and targeted tests across `packages/api` and `apps/cli`, including: - typecheck / lint / format / knip - `packages/api` tests - CLI core tests for platform metadata, input handling, schema output, tree construction, and body handling - targeted platform e2e coverage for normalized commands and dry-run behavior ## Notes - `@supabase/api` stays SDK-focused; CLI-specific metadata generation was intentionally not added there - the CLI continues to own public command naming and UX decisions for `platform`
## What kind of change does this PR introduce? Chore change: updating repo config. Update `.gitignore` file to include `.idea` directory. ## What is the current behavior? `.idea` directory is not ignored. ## What is the new behavior? `.idea` directory is ignored ## Additional context N/A
# Project Configuration & Multi-Stack Management
## Summary
This branch introduces the full project management lifecycle to the
TypeScript CLI — from initialization through linking, version
management, and multi-stack local development. It replaces the old
`jsonv-ts`-based config schema with an Effect V4 Schema system and
redesigns state management to cleanly separate committed project config,
per-checkout state, and ephemeral runtime state.
## What changed
### New CLI commands
| Command | Purpose |
|---------|---------|
| `supabase init` | Creates `supabase/config.json` with a `$schema`
reference and adds `.supabase/` to `.gitignore` |
| `supabase link [--project-ref]` | Binds the local project to a remote
Supabase project, caches service versions in `.supabase/project.json` |
| `supabase unlink` | Removes the cached remote link metadata |
| `supabase stack list` | Lists all named stacks for the current project
with ports and status |
| `supabase stack update` | Refreshes pinned service versions from the
linked project or CLI defaults |
Top-level aliases `start`, `stop`, `status`, `logs` are preserved. A new
`stack` command group exposes the full surface: `stack start`, `stack
stop`, `stack status`, `stack list`, `stack update`.
### `@supabase/config` — Schema & IO rewrite
- **Effect V4 Schema migration** — Every config section (`auth`, `db`,
`api`, `storage`, `realtime`, `analytics`, `studio`, `edge_runtime`,
`functions`, `experimental`, `inbucket`) rewritten from `jsonv-ts` to
`Schema.Struct` with annotations for descriptions, defaults, tags,
links, and secret markers.
- **Dual-format config** — Loads `supabase/config.json` or
`supabase/config.toml` (JSON takes precedence when both exist). Saves
preserve the existing format.
- **Minimal config semantics** — Default values are applied at the
schema level; saved configs only include non-default values.
- **Lazy `env(NAME)` resolution** — Raw configs preserve literal
`env(NAME)` strings. Resolution is explicit and on-demand via
`resolveProjectValue()` / `resolveProjectSubtree()`. Missing env vars
produce typed `MissingProjectEnvVarError`.
- **Secret redaction** — Schema annotations (`x-secret`) drive automatic
wrapping in `Redacted<string>` at resolution time.
- **Environment loading** — Merges `supabase/.env`,
`supabase/.env.local`, and `process.env` with source tracking.
- **Project discovery** — Upward filesystem walk from cwd to find
`supabase/config.json` or `supabase/config.toml`.
- **Platform-agnostic service layer** — `ProjectConfigStore` Effect
Service with `bun.ts` and `node.ts` runtime adapters.
- **JSON Schema generation** — Build script now produces
`dist/schema.json` via `Schema.toJsonSchemaDocument()` for editor
autocomplete.
- **New entrypoints** — `@supabase/config` (core),
`@supabase/config/bun`, `@supabase/config/node`.
### `@supabase/stack` — State management redesign
- **Dual-file state model** — `stack.json` (durable metadata: pinned
versions, ports, schema version) is separated from `state.json`
(ephemeral runtime: PID, connection info, running service versions).
- **`StackMetadata` schema** — New typed schema with
`STACK_METADATA_SCHEMA_VERSION = 1` and version validation at read time.
- **Project-scoped paths** — Stacks are now scoped to `(projectDir,
stackName)` pairs instead of being globally identified. New path
helpers: `projectStateManagerPaths`, `projectStateManagerPathsFromRoot`,
`singleStackStateManagerPaths`.
- **Stack discovery** — `listStacks()` scans metadata, overlays live
state from running daemons with PID validation. `resolveStackSummary()`
finds a specific stack.
- **RemoteStack rewrite** — Full `Stack` service implementation over
HTTP/SSE including `/status/stream`, `/logs`, `/logs/:service`,
`/logs/:service/history`, with transparent interface matching in-process
`LocalStack`.
- **Platform entrypoints** — `bun.ts` and `node.ts` with
`UnixHttpClient` abstraction for Unix socket communication.
- **Metadata persistence in createStack** — Reads existing `stack.json`
for port reuse across daemon restarts.
### `apps/cli` — Config infrastructure
- **`ProjectContext`** — Loads project config and environment from
`@supabase/config`.
- **`ProjectHome`** — Centralized paths provider for all per-checkout
state (`.supabase/project.json`, `stacks/<name>/stack.json`, etc.) with
project root discovery.
- **`ProjectLinkState`** — Persists/loads cached remote project metadata
with legacy path migration.
- **`ProjectLinkRemote`** — Fetches accessible projects and live service
versions from platform (Management API + tenant HTTP probes for
postgrest, auth, storage).
- **`ProjectLocalServiceVersions`** — Loads power-user checkout-local
version overrides from `.supabase/local-versions.json`.
- **`ProjectStackStateManager`** — Provides `StateManager` from
`@supabase/stack` wired to project-local paths.
- **Service version resolution** — Three-tier precedence: per-run flags
→ checkout-local overrides → pinned baseline → CLI defaults. Update
fingerprinting to notify once per unique diff set.
- **Gitignore management** — Automatic `.supabase/` addition to
`.gitignore` on `init` and `link`.
### Existing command changes
- **`start`** — New flags: `--stack NAME`, `--exclude SERVICE`,
`--service-version service=version`. Resolves versions via 3-tier
precedence, creates/updates `stack.json` metadata, warns about active
overrides and available updates.
- **`stop`** — Now passes `projectDir`, `projectStateRoot`, `name` for
multi-stack support.
- **`status`** — Shows stack name, all service versions (sorted), update
availability against candidate baseline. JSON output includes
`up_to_date` boolean and structured `available_updates`.
- **`logs`** — Scoped to named stack with `--stack` flag.
### State layout
```
my-project/
├── supabase/ # committed to git
│ ├── config.json # project configuration
│ ├── .env # shared env vars
│ └── .env.local # local-only env vars (gitignored)
└── .supabase/ # gitignored, per-checkout
├── project.json # cached remote link metadata
├── local-versions.json # checkout-local version overrides
└── stacks/
└── default/
├── stack.json # pinned baseline versions + ports
├── state.json # ephemeral daemon runtime state
├── data/ # persisted service data (volumes)
└── logs/ # service logs
```
### Documentation
- **New:** `apps/cli/docs/supabase-home.md` — State layout architecture
and ownership rules
- **New:** `packages/config/docs/project-config-loading.md` — Config
discovery, loading, and resolution architecture
- **Updated:** `packages/stack/docs/detach-mode.md` — Rewritten with new
state model, metadata schema, and multi-stack support
- **Updated:** `packages/stack/docs/service-versioning.md` —
Consolidated with current TypeScript resolution model
- **Updated:** `apps/cli/docs/go-cli-porting-status.md` — Reflects new
commands (`init`, `link`, `unlink`, completions via framework)
- **Updated:** `packages/config/README.md` — Reflects Effect Schema
migration and new entrypoints
### Testing
- **Integration tests** for all new commands (`init`, `link`, `unlink`,
`list`, `update`) following the `it.live` + mock-layer pattern
- **Integration tests** updated for refactored commands (`start`,
`stop`, `status`, `logs`)
- **E2e tests** for `init` and `link` (happy-path subprocess coverage)
- **Unit tests** for config IO (`io.test.ts`, 676 lines), project
discovery/resolution (`project.test.ts`, 311 lines), version resolution,
CLI config layer, project home layer, project link state layer, local
service versions layer
- **Stack package** — Extended `StateManager.test.ts` (metadata ops),
`discovery.test.ts` (listing/resolution), `createStack.test.ts`
(metadata persistence)
- **E2e cleanup** — Removed redundant platform e2e tests, consolidated
startup-timing tests
- **New test helpers** — `running-stack.ts` fixture builder for stack
integration tests, `stack-e2e-cleanup.ts` for reliable daemon teardown
## What kind of change does this PR introduce?
Feature — tier 1 e2e test coverage for the `telemetry enable`,
`telemetry disable`, and `telemetry status` commands.
## What is the current behavior?
No e2e tests existed for the telemetry commands. The ts-legacy CLI also
had no telemetry command at all (they were missing from the command tree
entirely).
Please link any relevant issues here: CLI-1366
## What is the new behavior?
- **ts-legacy Phase 0 proxy**: adds `telemetry enable/disable/status` to
the legacy command tree, proxying to the Go binary via `LegacyGoProxy`.
- **Harness fix**: changes `SUPABASE_TELEMETRY_DISABLED` from `"true"`
to `"1"` — the Go CLI checks `=== "1"`, not `=== "true"`, so the old
value was ineffective and the Go binary was writing `telemetry.json` on
every command, causing parity test failures due to unexpected filesystem
side-effects.
- **FS isolation**: adds `SUPABASE_HOME: harness.options.cwd` to the
exec env so telemetry state is scoped to each test's temp workspace,
keeping tests hermetic and enabling parity comparison of filesystem
changes.
- **Test coverage**:
- `testBehaviour`: success paths for enable/disable/status, round-trip
state checks (enable→status, disable→status), unwritable config dir
(exit non-zero), corrupted JSON config (exit non-zero)
- `testParity`: all three subcommands × {success, NON_AUTH injection}
> **Note**: replay mode (`test:legacy`) requires `SUPABASE_GO_BINARY` to
point to a build of the Go CLI that includes the `telemetry` commands,
since the system binary predates them. Same requirement as record mode.
## What kind of change does this PR introduce? Chore — adds tier 1 e2e tests for the `orgs` commands. ## What is the current behavior? `orgs.e2e.test.ts` had minimal coverage: one happy-path test for `orgs list`, one 401 error test, and two parity tests. `orgs create` had no tests at all. Closes [CLI-1378](https://linear.app/supabase/issue/CLI-1378/tier-1-tests-organizations) ## What is the new behavior? Full tier 1 coverage for both `orgs list` and `orgs create`, structured with nested describes matching the branches/projects pattern: **`orgs:list` (9 tests)** - Renders org data (happy path) - `--output json` returns parseable array - `--debug` produces output without error - Error paths: 401, 403, 429, 500 - Parity tests: success + NON_AUTH **`orgs:create` (10 tests)** - Creates org and prints slug — `skipIf(isRecording)` with hand-crafted fixture (orgs are irrecoverable; no `orgs delete` command) - Exits non-zero without name argument - Error paths: 401, 403 (plan limit), 409 (name conflict), 422 (validation), 429, 500 - Parity tests: success + NON_AUTH with hand-crafted recorded fixtures
## What kind of change does this PR introduce? New E2E tests (tier 1) for the `functions` subcommands: `list`, `deploy`, `delete`, and `download`. ## What is the current behavior? `functions.e2e.test.ts` only had minimal coverage — basic `list` and `new` tests. Linear: https://linear.app/supabase/issue/CLI-1373 ## What is the new behavior? Full tier-1 behaviour and parity test coverage across `functions:list`, `functions:delete`, `functions:download`, and `functions:deploy`, following the same pattern as the branches and projects/secrets test suites. **`functions:list`** — `testBehaviour` for JSON output, debug output, and error injection (403, 429, 500); `testParity` for Go vs TS-legacy consistency. **`functions:delete`** — `testBehaviour.skipIf(isRecording)` for success case (hand-crafted fixture); `testBehaviour` for 404/401/403/429/500 error injection; `testParity` for Go vs TS-legacy. **`functions:download`** — `testBehaviour` for 401/403/404/500 error injection; `testParity` for NON_AUTH failure parity. Success case omitted (see limitations below). **`functions:deploy`** — `testParity` only (AUTH + NON_AUTH). Success and error injection cases omitted (see limitations below). ### Known limitations | Command | Gap | Reason | |---|---|---| | `functions deploy` success | Not tested | Relay proxy only parses `application/json` bodies; `multipart/form-data` deploy request body is recorded as `null` and not forwarded to staging | | `functions deploy` error injection | Not tested | Upload goroutine + HTTP concurrency creates a race condition — error may be consumed before or after the multipart upload completes | | `functions download` success | Not tested | `downloadWithServerSideUnbundle` expects a `multipart/form-data` response; relay server records response bodies as JSON only |
…I-1365) (#43) ## What kind of change does this PR introduce? Docs/test stub — placeholder tests with detailed comments documenting the blocker and planned coverage. ## What is the current behavior? `login` and `logout` e2e tests cannot be implemented on macOS today. The Go CLI unconditionally uses the OS keychain for credential storage. When the test harness sets `HOME` to an isolated temp directory (to prevent writing to the developer's real `~/.supabase`), macOS Security framework shows a blocking dialog — "A keychain cannot be found to store 'test'" — because `$HOME/Library/Keychains/login.keychain-db` doesn't exist in the temp dir. This causes every login/logout test to hang indefinitely until the 60 s timeout fires. `SUPABASE_NO_KEYRING=true` is already set by the harness, but the Go CLI does not read this variable — it only suppresses keyring in the TS-next CLI. Closes CLI-1365 ## What is the new behavior? `apps/cli-e2e/src/tests/auth.e2e.test.ts` is created with a single `it.todo()` and a detailed file comment that documents: - The root cause of the blocker (Go CLI keyring opt-out missing) - What infrastructure change is needed before tests can be implemented (Go CLI must honour `SUPABASE_NO_KEYRING` or equivalent) - The full planned test coverage (login `--token`, `--name`, `--debug`, invalid token; logout `--yes` after login, double-logout pattern, parity tests) The suite passes: `1 todo`, zero failures introduced by this file.
## What kind of change does this PR introduce? chore: update vitest config with custom sequencer to run in order deterministically ## What is the current behavior? Tests run undeterministically causing issues with replay of fixtures ## What is the new behavior? Tests run alphabetically to ensure that replay is correct
## What kind of change does this PR introduce? chore / test coverage ## What is the current behavior? The `gen` command group (`gen types`, `gen signing-key`, `gen bearer-jwt`) had no e2e test coverage. ## What is the new behavior? - Adds `gen.e2e.test.ts` with behaviour and parity tests for all three `gen` subcommands: - `gen types` — happy path (TypeScript output shape), `--debug` flag, 401/403/404 error exits, unsupported `--lang go` with `--project-id`, missing data source - `gen signing-key` — default ES256 key shape, RS256 via `--algorithm` - `gen bearer-jwt` — missing `--role` error, anon/authenticated roles, custom `--valid-for`, custom `--sub` - Extends `normalize.ts` in `cli-test-helpers` with JWT/JWK normalization rules so `testParity` works on the non-deterministic crypto output from `gen signing-key` and `gen bearer-jwt` - Adds unit tests for the new normalize rules - Updates recorded fixtures for existing tests affected by fixture regeneration
## What kind of change does this PR introduce? CI improvement / chore ## What is the current behavior? Every PR runs the full e2e suite via `nx run-many -t test:e2e`, regardless of what changed. There is also no CI run when PRs merge to main. ## What is the new behavior? - **PRs**: `nx affected -t test:e2e` runs only the e2e projects whose source (or dependencies) changed. `nrwl/nx-set-shas@v4` determines the correct base SHA (last successful run on main) so the comparison is accurate. - **Push to main**: full `nx run-many -t test:e2e` always runs as a regression gate after merge. Also adds `fetch-depth: 0` to the e2e checkout (required for git history traversal by `nx affected`) and `actions: read` permission (required by `nrwl/nx-set-shas`).
## What kind of change does this PR introduce? Chore / CI improvement ## What is the current behavior? The Go CLI binary is compiled from source on every CI run, even when nothing in `.repos/supabase-cli-go/` has changed. This adds unnecessary build time to every PR. ## What is the new behavior? The compiled binary is cached using `actions/cache`, keyed on a hash of all `.go` files plus `go.mod` and `go.sum` in the submodule. On a cache hit both the `setup-go` and `build` steps are skipped entirely. On a cache miss (new submodule commit or any source change) the binary is built and saved to cache as before.
…#47) ## What kind of change does this PR introduce? Chore — adds tier 1 e2e test coverage for `network-bans`, `network-restrictions`, and `ssl-enforcement` commands (CLI-1381). Also fixes a recurring test fragility in the branches suite. ## What is the current behavior? No e2e tests exist for `network-bans get/remove`, `network-restrictions get/update`, or `ssl-enforcement get/update`. The `branches list --output json` test was also repeatedly broken by recording runs. ## What is the new behavior? **New test file:** `apps/cli-e2e/src/tests/network-security.e2e.test.ts` Covers all three command groups with behavioural and parity tests: - Success paths (fixture data, `--output json`, `--debug`) - Flag combinations (`--append`, `--bypass-cidr-checks`, `--enable/disable-db-ssl-enforcement`) - Client-side validation errors (invalid IP, invalid CIDR, mutually exclusive flags, missing required flags) - HTTP error paths (401, 403, 404, 429, 500) via error injection - Go vs TS-legacy parity for all subcommands Notable discoveries during recording: - All three command groups require `--experimental` - IP/CIDR validation is local (Go binary rejects before any API call), so those tests don't use error injection - `--append` uses `PATCH /network-restrictions` (not `POST /apply`), and private CIDRs (e.g. `10.0.0.0/8`) are rejected locally — switched to `8.8.8.0/24` - `ssl-enforcement update` with conflicting or missing flags exits via Go binary flag validation with 0 API interactions **Recurring branches fix:** marked `branches list --output json` as `skipIf(isRecording)` and restored the hand-crafted fixture. Root cause: `record` re-records all scenarios from a clean project; `branches:create` is already `skipIf(isRecording)` so branches:list always records an empty response; Go CLI marshals a nil slice as `null` not `[]`, breaking `Array.isArray`. Any test asserting on list content that depends on a `skipIf(isRecording)` mutation needs the same treatment.
## What kind of change does this PR introduce? New e2e test coverage (tier 1) for the 6 SSO CLI subcommands. ## What is the current behavior? The SSO commands (`sso list`, `sso info`, `sso show`, `sso add`, `sso update`, `sso remove`) have no e2e test coverage. Closes https://linear.app/supabase/issue/CLI-1379 ## What is the new behavior? 51 new tests across 6 subcommands covering: - **sso list** — renders output, `--output json`, `--debug`, error injection (401/403/404/429/500), parity success + NON_AUTH - **sso info** — renders output, `--output json`, parity success (no API calls made; no error injection needed) - **sso show** — renders output, `--output json`, `--metadata` (raw XML), error injection (401/403/404/429/500), parity success + NON_AUTH - **sso add** — adds via metadata file, 4 CLI-level validation errors, error injection (401/403/422/429/500), parity NON_AUTH - **sso update** — domain append/replace/remove, metadata file update, `--domains`+`--add-domains` exclusivity, error injection (401/403/404/429/500), parity success + NON_AUTH - **sso remove** — removes a provider (hand-crafted fixture), error injection (401/403/404/429/500), parity NON_AUTH Provider-dependent success cases (`sso show`, `sso update`, `sso remove`) use hand-crafted fixtures with `testBehaviour.skipIf(isRecording)` to avoid needing a real SAML provider on the test project. All other fixtures were recorded against the staging API.
## What kind of change does this PR introduce? E2e test coverage (tier 1) for the `init`, `link`, and `unlink` project lifecycle commands. ## What is the current behavior? No e2e tests exist for `init`, `link`, or `unlink`. ## What is the new behavior? Adds 16 new e2e tests across three command groups: **init** (6 tests) - Creates `supabase/config.toml` and exits zero - Exits non-zero if `config.toml` already exists without `--force` - Exits zero with `--force` when `config.toml` exists - Creates VS Code settings with `--with-vscode-settings` - Creates IntelliJ settings with `--with-intellij-settings` - Includes debug output with `--debug` **link** (7 tests) - Exits non-zero without `--project-ref` in non-TTY - Exits non-zero on 401, 403, 500 - Links project successfully (hand-crafted fixture — skipped in record mode due to concurrent non-fatal service calls) - `--skip-pooler` uses direct connection (hand-crafted fixture) - Parity test **unlink** (3 tests) - Exits non-zero when project not linked - Removes link state and prints confirmation (hand-crafted fixture — no API calls) - Parity test Notable design decisions: - `testParity` is omitted for `init` because `Eject()` uses `os.Getwd()` basename as `project_id`, producing different `config.toml` content across the two isolated parity temp dirs. - The `link` success tests use `testBehaviour.skipIf(isRecording)` with hand-crafted fixtures containing only the two sequential calls (project status + api-keys). The concurrent service calls get 502 but those errors are non-fatal. - `bootstrap` tests are omitted entirely — the command calls `api.github.com` before any Management API calls, which cannot be intercepted by the replay server. Closes [CLI-1367](https://linear.app/supabase/issue/CLI-1367)
… churn (#51) ## What kind of change does this PR introduce? Chore / developer experience improvement. ## What is the current behavior? Re-recording fixtures for any command that calls a shared endpoint (e.g. `GET /v1/organizations`, `GET /v1/projects`) changes several values that are meaningless for test correctness but differ every recording session: - `x-ratelimit-reset` / `x-ratelimit-remaining` — countdown timer and quota counter, depend on exactly when and how many calls were made in the session - `hash` in API key objects — SHA-256 base64url of the key, rotates when the test project is recreated between sessions - `prefix` in legacy API key objects — 5-char prefix, rotates with the key - Integer `id` fields in project/SSO response bodies — DB auto-increment, increments each time a resource is created This caused real merge conflicts when two parallel PRs both re-recorded shared fixtures: one PR's recording overwrote the other's for values that had no test meaning. ## What is the new behavior? `applyPlaceholders` in `placeholder.ts` now normalises all five categories to stable values: | Field | Stable value | |---|---| | `x-ratelimit-reset` | `"60"` | | `x-ratelimit-remaining` | `"119"` | | `hash` | `"<KEY_HASH>"` | | `prefix` (legacy keys) | `"<KEY_PREFIX>"` | | Integer `id` (4+ digits) | `0` | Rate-limit headers use valid integer strings so the CLI can still parse them for retry logic. All 73 existing fixture files have been back-filled in the same pass so the baseline is already clean. Future re-recordings of shared endpoints will produce identical fixture files, eliminating this class of merge conflict.
## Summary Lands Windows-arm64 parity, enables end-to-end Homebrew/Scoop validation against user-owned repos, fixes the CLI version plumbing, and writes up the full release process. ADR 0011 is flipped from `proposed` to `accepted`. Detailed context in [`docs/adr/0011-cli-release-and-distribution-strategy.md`](docs/adr/0011-cli-release-and-distribution-strategy.md) (new "Implementation progress" section + gate status updates) and [`apps/cli/docs/release-process.md`](apps/cli/docs/release-process.md) (new — operational playbook for local → PoC → production). ## Changes ### A. Windows-arm64 parity (closes ADR 0011 gate 1) Go CLI ships `windows_arm64` today; dropping it on TS cutover would be a user-visible regression. Now wired everywhere: ### B. `--name` + user-owned-repo support on updater scripts (unblocks gates 2 & 3 validation) Both updater scripts can now push to a reviewer's own repos under a non-`supabase` name, so Homebrew/Scoop can be validated end-to-end without risking `supabase/homebrew-tap` / `supabase/scoop-bucket` and without clashing with an already-installed `supabase` CLI. Validated end-to-end against: - [`avallete/supabase-cli-release-poc`](https://github.com/avallete/supabase-cli-release-poc) (GitHub Release host) - [`avallete/homebrew-supabase-shim-poc`](https://github.com/avallete/homebrew-supabase-shim-poc) (Homebrew tap — `darwin-arm64` passes; other platforms pending) - [`avallete/scoop-bucket`](https://github.com/avallete/scoop-bucket) (Scoop bucket — Windows x64 passes; arm64 pending hardware) Full reproducer in [`apps/cli/docs/release-process.md`](apps/cli/docs/release-process.md) Ring 2. ### C. Real CLI version plumbing `supabase --version` used to print `0.1.0` regardless of the actual package version. Fixed by injecting the real version at compile time: ### D. Build correctness fix [`apps/cli/scripts/build.ts`](apps/cli/scripts/build.ts) now runs `go build … .` with `.cwd(goSource)` instead of passing `goSource` as a positional argument. The old form made Go resolve modules from invocation CWD (repo root, no `go.mod`) and fail. ### Docs - [`docs/adr/0011-cli-release-and-distribution-strategy.md`](docs/adr/0011-cli-release-and-distribution-strategy.md) — status `proposed` → `accepted`; gate 1 marked DONE with landed-files; gate 2 annotated with the `supabase-go` install bug and fix; gate 3 updated to reflect Windows x64 is validated and only arm64 remains; gate 5 flagged as the largest remaining pre-cutover item; new "Implementation progress" section; "See Also" points at the new release-process doc. - [`apps/cli/docs/release-process.md`](apps/cli/docs/release-process.md) (new) — Ring 1 / 2 / 3 playbook. Commands, mermaid flow diagrams, rollback procedure, what the production pipeline looks like once gate 5 lands. - [`apps/cli/docs/binary-distribution.md`](apps/cli/docs/binary-distribution.md) — `cli-windows-arm64/bin/` added to the package layout; cross-link to release-process.md. ## Test plan - [x] `bun apps/cli/scripts/build.ts --version 0.0.1 --shell legacy` produces all 8 platform archives + 6 Linux packages + `checksums.txt` including `windows_arm64.zip`. - [x] `bun apps/cli/scripts/update-homebrew.ts --version 0.0.1 --dry-run` renders a valid Ruby formula with the `supabase-go` install line. - [x] `bun apps/cli/scripts/update-scoop.ts --version 0.0.1 --dry-run` renders a manifest with both `64bit` and `arm64` architecture entries. - [x] `brew install supabase-shim-poc` on `darwin-arm64` from `avallete/homebrew-supabase-shim-poc` — installs, `--version` prints `supabase v0.0.1`, `brew test` passes, Phase-0 proxied subcommands resolve the sidecar correctly. - [x] `scoop install supabase-shim-poc` on Windows x64 (`windows_amd64.zip`) — installs with no SmartScreen block on the unsigned Bun SFE, `--version` prints `supabase v0.0.1`. - [ ] `brew install supabase-shim-poc` on `darwin-x64` (Intel / Rosetta). - [ ] `brew install supabase-shim-poc` on `linux-arm64` / `linux-x64` (brew on Linux). - [x] `apt/rpm/...` install on `linux` (tested on ubuntu VM arm64 with `dpkg -i` - [ ] `scoop install supabase-shim-poc` on Windows arm64 (`windows_arm64.zip`) — pending hardware / Windows-on-ARM VM. ## Follow-ups (not in this PR) Tracked in [ADR 0011 Open Questions](docs/adr/0011-cli-release-and-distribution-strategy.md#open-questions--blockers): - Gate 5 — wire `update-homebrew.ts` / `update-scoop.ts` into `release-shared.yml` as a `post-publish` job gated on `npm_tag == 'latest'`, with a GitHub App token. - Gate 6 — extend CI smoke-test matrix with Alpine (musl) + `windows-11-arm`. - Gate 7 — consolidate local (`tools/release/local-release.ts`) and pipeline (`apps/cli/scripts/build.ts`) release logic ([CLI-1344](https://linear.app/supabase/issue/CLI-1344)). - Gate 8 — `findConfigInRoot` `ENOTDIR` handling in [`packages/config/src/paths.ts`](packages/config/src/paths.ts). Fixes: CLI-1330
## What kind of change does this PR introduce? New feature — tier 1 e2e test coverage for the four `storage` commands (`ls`, `cp`, `mv`, `rm`). ## What is the current behavior? Storage commands had zero e2e test coverage. The legacy shell wrappers for `storage ls/cp/mv/rm` also lacked `--local` and `--linked` flags, so parity tests between the Go and TS-legacy CLIs could not be run. Fixes CLI-1374 ## What is the new behavior? - `--local` and `--linked` flags added to all four storage legacy wrappers (`ls`, `cp`, `mv`, `rm`), aligning the TS flag surface with the Go CLI. - `HarnessOptions.projectId` added to `cli-test-helpers` — sets `SUPABASE_PROJECT_ID` in subprocess env, required for Go CLI local-mode config validation. - `ParityOptions.workspaceSetup` callback added — called on each temp dir before a CLI run so storage parity tests can write `supabase/config.toml`. - Replay server extended with `setStorageProxyUrl` / `setStorageProxyAuth` — routes storage API paths to the staging storage endpoint in record mode. - Global e2e setup extended to provision a test bucket and seed `hello.txt` during record mode. - **36 new e2e tests** across `ls`, `cp`, `mv`, `rm`: - Success paths (stdout content, request log assertions) - Error paths (401, 403, 429, 500 via error injection) - Go ↔ TS-legacy parity tests (exit code, stdout, stderr, request log) - 26 scenario fixture directories recorded against staging All tests use `--local --experimental` mode with a per-test `supabase/config.toml` pointing at the relay server, so storage HTTP calls are captured and replayed without requiring HTTPS or a real project subdomain.
## What kind of change does this PR introduce?
New e2e test coverage for the `db` and `test` command groups (CLI-1370).
## What is the current behavior?
No e2e tests existed for `db advisors`, `db query`, `db push`, `db
pull`, `db lint`, `db diff`, `db dump`, `db reset`, `test new`, or `test
db`.
## What is the new behavior?
Adds Tier 1 e2e tests covering:
- **`db advisors`** — security, performance, and all types; success path
(JSON output or "No issues found"), `--fail-on error`, and
401/403/429/500 error injection; parity (Go vs ts-legacy) and NON_AUTH
parity
- **`db query --linked`** — table format and JSON output (handles
agent-mode envelope); 401/403 error injection; parity and NON_AUTH
parity
- **`db push`** — `--dry-run` SQL output, `--local` connection-refused,
`--linked` 401 error path; parity
- **`db pull`, `db lint`, `db diff`, `db dump`, `db reset`** — `--local`
connection-refused; flag validation (`--role-only/--data-only`,
connection-refused parity)
- **`test new`** — file creation, missing-argument error, parity
- **`test db`** — `--local` connection-refused; parity
**Infrastructure changes:**
- `harness.ts`: adds `SUPABASE_DB_PASSWORD` to subprocess env so the Go
CLI's `ParseDatabaseConfig` takes the pooler path (via
`.supabase/.temp/pooler-url`) instead of TCP-probing
`db.{ref}.localhost:5432`, enabling `--linked` tests without a real
Postgres connection
- `normalize.ts`: adds rule to replace the per-process random `boundary`
UUID in `db query` agent-mode JSON output, making parity stable
- `test-context.ts`: threads `workspaceSetup` option through
`testParity` to `runParity` (already supported in parity.ts)
## What kind of change does this PR introduce?
This adds e2e test coverage for four `domains` commands and the option
to run parity tests with handwritten fixtures.
We can't really test the `domains` commands against staging, since we'd
have to set up actual DNS records to verify the happy path — so we're
using handwritten fixtures (recorded with Proxyman) for the happy path
and recorded responses for the unhappy path ("custom domain not
enabled").
I encountered two blockers here:
- The parity checks should probably test `domains get`, which is
scenario based – that's why I added scenario support to `testParity`
- The `domains create` commands first verify CNAME records by querying
`1.1.1.1`. IIUC, we can only mock that at the OS level, since it's
hard-coded in the Go binary — should we skip the test?
## What is the current behavior?
There was no e2e coverage for the domains commands.
Fixes CLI-1380
## What is the new behavior?
- testParity now supports scenarios
- `domains get` has behavior and parity tests for `--output json`
- `domains get` has coverage for various error paths (400, 401, 403,
429, 500, 502)
- e2e tests for `domains` commands based on various states:
- Custom Domains not enabled
- Custom Domains enabled, but no Custom Domain set
- Custom Domain set, but verification pending
- Custom Domain set & verified, but not activated
- Custom Domain activated
…55) ## What kind of change does this PR introduce? New e2e tests + infrastructure. ## What is the current behavior? No e2e tests existed for `inspect db` or `inspect report`. The commands connect directly to Postgres (no Management API), so the existing HTTP replay infrastructure couldn't cover them. ## What is the new behavior? Adds a minimal Postgres wire-protocol mock server (`pg-mock.ts`, `Bun.listen` TCP) and wires it into the test harness so all 13 active `inspect db` subcommands and `inspect report` are covered with `testBehaviour` and `testParity` tests. **Infrastructure added:** - `src/server/pg-mock.ts` — TCP server speaking the full extended query protocol (Parse/Describe/Bind/Execute/Close/Sync) required by pgx v4. Reads fixture JSON from `fixtures/pg/` and serves rows as Postgres wire-format DataRows. - `fixtures/pg/<subcommand>.json` — one fixture file per subcommand with column names and mock row data matching the Go `Result` structs. - `POST /_ctrl/pg-fixture` route on the replay server — lets tests switch the PG mock state before running. - `pgMockPort` injected into `BehaviourFixtures` — tests write a `supabase/config.toml` pointing `db.port` at the mock so `--local` connections are intercepted. **Implementation notes:** - The Parse message payload is parsed to count `$N` placeholders so `ParameterDescription` returns the correct param count (queries like `db-stats` pass 2 args; pgx validates against the server-reported count before executing). - Bool fixture values use single-byte `'t'`/`'f'` (Postgres wire text format) — `pgtype.Bool.DecodeText` requires exactly 1 byte, not the words `"true"`/`"false"`. **Tests per subcommand (× 13) + report:** 1. `renders query results as a table` — connects to mock, asserts exit 0 and a known value in stdout 2. `exits non-zero on connection refused` — uses `localhost:1`, asserts non-zero exit and non-empty stderr 3. `parity: inspect db <subcmd>` — both CLI targets produce identical output against the mock (skipped in record mode)
## What kind of change does this PR introduce? This PR adds e2e test for the `config push` command and the required fixtures for it. For the command to pick up a diff, we're writing a `supabase/config.toml` into the workspace's temp dir. The config is written such that it has diffs in every section, so that every PATCH/PUT API-Call in the CLI is invoked. One thing of note: I could only test the "unlinked project" case with `testParity`, because the `testBehaviour() -> run(..)` function always injects `PROJECT_REF` and assigns it to `env.SUPABASE_PROJECT_ID`, which is picked up by the Go CLI. `testParity` does not inject `PROJECT_REF`. ## What is the current behavior? There are currently no e2e tests for the `config push` command. ## What is the new behavior? - e2e tests for error paths: 401, 403, 404, 409, 422, 429, 500, 502; parity for auth & rate limit tests - test for `--debug` flag - behavior & parity tests for `config push` with updates in every supported `config` section - parity tests for `config push` without a linked project --------- Co-authored-by: Colum Ferry <cferry09@gmail.com>
## What kind of change does this PR introduce? New e2e tests (tier 1 behaviour + parity coverage) for five command groups that were previously untested. ## What is the current behavior? `postgres-config`, `vanity-subdomains`, `encryption`, `backups`, and `snippets` command groups have no automated e2e coverage. ## What is the new behavior? Adds `testBehaviour` and `testParity` tests for all five groups (117 tests total): - **postgres-config**: `get`, `update`, `delete` — config overrides, `--no-restart`, `--replace-existing-overrides`, error injection (401/404/422/429/500) - **vanity-subdomains**: `get`, `check-availability`, `activate`, `delete` — subdomain CRUD, 409 conflict, error injection - **encryption**: `get-root-key`, `update-root-key` — vault root key read/rotate, error injection - **backups**: `list`, `restore` — backup table rendering, PITR restore (201), error injection - **snippets**: `list`, `download` — snippet list/download, error injection All commands are Phase 0 Go proxies. Three tests use `testBehaviour.skipIf(isRecording)` with hand-crafted fixtures for scenarios that cannot be reliably recorded live (interactive `update-root-key`, PITR-disabled project for `backups restore`, nonexistent snippet for `snippets download`). Also fixes a replay server bug where query parameters containing project refs (e.g. `/v1/snippets?project_ref=aaaaaaaaaaaaaaaaaaaa`) were compared literally against fixture placeholders (`<PROJECT_REF>`), causing all `snippets list` behaviour tests to fail in replay mode.
## What kind of change does this PR introduce?
New e2e tests + infrastructure.
## What is the current behavior?
No e2e tests for `start`, `stop`, `status`, `services`, or `seed
buckets`.
## What is the new behavior?
Adds tier-1 e2e tests for the local dev stack commands.
**Infrastructure added:**
- Docker API TCP proxy in the relay server (`setDockerProxyUrl`) so
`DOCKER_HOST` can point at the relay for record/replay of Docker SDK
calls through a Unix socket
- `buildApiResponse` helper that correctly returns empty body for HTTP
204/304/205 responses — without this, `Response.json(null, {status:
204})` sent `"null"` as the body, corrupting the Go Docker client's
connection pool
- `dockerHostUrl` context injected by test setup; record mode wires the
relay to the real Docker socket
- Docker API version path normalisation in `placeholder.ts` (`/v1.47/` →
`/<DOCKER_VERSION>/`) for stable fixture keys across Docker Engine
upgrades
**Tests added:**
- `services`: lists known service images (no Docker needed)
- `status`: exits 1 with "no such container" when stack is not running
- `stop`: succeeds (exit 0) when nothing is running; exits 1 on
`--project-id`+`--all` mutual exclusion
- `start`: exits 1 when Docker is unavailable (unreachable host)
- `seed buckets`: creates buckets defined in config.toml
**Lifecycle tests (`start → status → stop`) are marked `test.todo`** —
the `supabase_vector` container's health check consistently fails when
`supabase start` runs through the TCP relay proxy on this development
machine (vector restarts 9 times before the CLI gives up). These will be
recorded in an environment where the full stack starts cleanly, then the
todos converted to real tests.
## What kind of change does this PR introduce? CI infra. ## What is the current behavior? The cli-e2e suite runs as a single GitHub Actions job (~4 min wall time on PRs / push to main). The `test.yml` workflow has had a `TODO: Shard e2e tests across multiple machines` comment for a while. ## What is the new behavior? The `test-e2e` job is now a 3-way matrix that shards cli-e2e tests via vitest's [`--shard` flag](https://vitest.dev/guide/improving-performance.html#sharding): - **`Run cli-e2e end-to-end tests`** invokes vitest directly (`pnpm --filter @supabase/cli-e2e exec bun --bun vitest run --shard=N/3`) rather than going through `pnpm run` / `nx run-many`. The latter prepends a stray `--` that vitest treats as a positional-argument terminator, silently defeating the shard flag. - **`Build CLI`** step runs before the sharded test step. The ts-legacy harness invokes `bun apps/cli/dist/main-legacy.js`; the `nx run @supabase/cli-e2e:test:e2e` target normally builds @supabase/cli via `dependsOn`, but bypassing nx for sharding skips that dependency, so we build it explicitly. - **`Run other e2e tests (shard 1 only)`** runs `pnpm exec nx run-many -t test:e2e --exclude=@supabase/cli-e2e` so the smaller process-compose e2e suite still runs (once per workflow rather than 3×). - `strategy.fail-fast: false` so one shard failing still reports the others' results. Recording stays a single-job operation (no `--shard` on the `record` script). Parallel shards would race on the shared `fixtures/recorded/` directory. `apps/cli-e2e/AGENTS.md` gets a "Sharding (replay only)" section under "Running the suite" documenting the local invocation and the record-mode caveat. ## Verification - Wall time: 3 parallel shards each running ~⅓ of the 18 cli-e2e files, so the e2e job's wall time drops to ~⅓ of the un-sharded run (~80s per shard vs ~240s). - Local check that the split is correct: each shard's pass count sums to the un-sharded total.
## Summary Adds `edge-runtime` as a first-class service in `@supabase/stack`. The stack now starts Edge Runtime by default in `auto`/Docker-backed flows, exposes it through the local API gateway at `/functions/v1/*`, and reports both the public functions endpoint and direct edge-runtime endpoint in stack info. This PR intentionally only wires the runtime into the stack package; the CLI `functions` commands and real function serving/bundling workflow will be handled in follow-up PRs. ## Changes - Adds `edgeRuntime` stack config, resolved config, default version, service metadata, ports, cleanup targets, and service status wiring. - Adds an Edge Runtime service factory with a generated placeholder bootstrap service that exposes health checks and returns `501 FUNCTIONS_NOT_CONFIGURED` for function requests. - Routes `/functions/v1/*` through the API proxy to Edge Runtime, preserving auth transformation behavior and stripping problematic upstream response headers. - Adds Edge Runtime Docker image resolution and native asset metadata, but keeps Edge Runtime Docker-backed for now while native runtime support remains hidden. - Updates stack metadata/version schemas and CLI tests/helpers to include the new Edge Runtime ports and service version. - Adds Docker e2e coverage that verifies the Edge Runtime container starts and the gateway serves the placeholder response. ## Out Of Scope - No implementation of `supabase functions serve`, bundling, deployment, or per-function routing. - No user-facing native Edge Runtime launch path yet, even though native release asset metadata is present.
## Summary
Adds native next-CLI support for `supabase functions new [slug]`.
This introduces local Edge Function scaffolding for the current
Deno/TypeScript model while keeping project config as overrides, not a
generated manifest. Functions are inferred from the filesystem by
default.
## Changes
- Added `supabase functions new [slug]` under the next CLI root.
- Supports exactly one optional positional slug.
- Prompts for the slug in interactive text mode when omitted.
- Fails cleanly in non-interactive modes when no slug is provided.
- Validates slugs with `^[A-Za-z0-9_-]+$`.
- Creates:
- `supabase/functions/<slug>/index.ts`
- `supabase/functions/<slug>/deno.json`
- Refuses to overwrite an existing `index.ts`.
- Does not create or update `supabase/config.json` /
`supabase/config.toml` for default function settings.
- Added `inferFunctionsManifest` to `@supabase/config`.
- Function manifests are inferred from filesystem shape and overlaid
with config customizations.
- Added per-function `env` support to the config schema.
## Config Model
Default functions are discovered from:
```text
supabase/functions/<slug>/index.ts
supabase/functions/<slug>/deno.json
```
Config is now treated as overrides only. Users only need
`functions.<slug>` entries for non-default behavior, for example:
```json
{
"functions": {
"hello-world": {
"verify_jwt": false
}
}
}
```
9ce4b94 to
c94dc8a
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Merge diverging CLI repos