Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
d7a4a40
docs(cli-e2e): document live coverage strategy
jgoux Aug 21, 2026
5863068
test(cli): consolidate live e2e harness
jgoux Aug 21, 2026
37ea3e8
fix(test): bound live provisioning requests
jgoux Aug 21, 2026
f121882
test(cli): collocate live command coverage
jgoux Aug 21, 2026
8063c00
test(cli): cover bulk function deployment
jgoux Aug 21, 2026
25b3aad
test(cli): move live suite ownership into cli
jgoux Aug 21, 2026
dc56c30
test(cli): harden live environment gates
jgoux Aug 21, 2026
7b7e06e
test(cli): use supported gen types target
jgoux Aug 21, 2026
8145ed0
test(cli): scope managed live e2e runs
jgoux Aug 21, 2026
a7b533c
test(cli): simplify live e2e environment
jgoux Aug 21, 2026
faabe4d
test(cli): tighten live e2e lifecycle
jgoux Aug 21, 2026
b2a3946
docs(cli): refresh live e2e contributor guidance
jgoux Aug 21, 2026
eac7177
test(cli): honor live data plane protocol
jgoux Aug 21, 2026
eab3f79
test(cli): harden live e2e lifecycle
jgoux Aug 21, 2026
1c5aeac
test(cli): preserve live e2e cleanup
jgoux Aug 21, 2026
6f64b9a
test(cli): simplify branch cleanup
jgoux Aug 21, 2026
44ffc5a
test(cli): use primary pooler for live database
jgoux Aug 21, 2026
abcbb47
test(cli): avoid duplicate branch cleanup
jgoux Aug 21, 2026
980bb11
test(cli): fix Docker e2e execution
jgoux Aug 21, 2026
f7962cb
chore: merge develop into live e2e branch
jgoux Aug 21, 2026
375c55a
test(cli): align Docker e2e fixtures
jgoux Aug 21, 2026
7e08e3e
test(cli): harden e2e lifecycle checks
jgoux Aug 21, 2026
08aadb1
test(cli): own legacy e2e lifecycle cleanup
jgoux Aug 22, 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
9 changes: 5 additions & 4 deletions .github/workflows/dispatch-cli-e2e-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ name: Dispatch cli-e2e-ci
# Asks the supabase/cli-e2e-ci harness to run the cli `test:live` suite against
# a full supabox stack, built from THIS PR's head commit (CLI-1825 / CLI-1831).
#
# This is distinct from `live-e2e.yml`, which runs the cli-e2e package against
# real staging (api.supabase.green). Here the suite runs against a local supabox
# stack stood up inside the private cli-e2e-ci repo; we only fire the trigger and
# pass our head SHA — cli-e2e-ci checks that SHA out into its `cli` submodule.
# This is distinct from `live-e2e.yml`, which runs the collocated live suite
# against managed staging (api.supabase.green). Here the same `apps/cli` suite
# runs against a local Supabox stack stood up inside the private cli-e2e-ci repo;
# we only fire the trigger and pass our head SHA — cli-e2e-ci checks that SHA out
# into its `cli` submodule.
#
# Opt-in by label to keep the expensive full-stack run off every PR: add the
# `run-live-e2e-ci` label (re-dispatches on each subsequent push while labeled).
Expand Down
33 changes: 8 additions & 25 deletions .github/workflows/live-e2e.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: Live E2E

# Live e2e suite (ADR-0013). Runs the real CLI against the real staging
# Management API + Docker bundler, then invokes the deployed functions over HTTP.
# Live e2e suite. Runs the collocated `apps/cli` tests against the real staging
# Management API + Docker bundler, then invokes deployed functions over HTTP.
#
# Non-blocking by construction: this is a standalone workflow, NOT part of the
# required-checks set, and it never runs on the default PR path of test.yml.
Expand Down Expand Up @@ -99,10 +99,8 @@ jobs:
# Non-secret config is job-level; the staging token is scoped to only the two
# steps that need it (run + cleanup) so build/checkout/docker never see it.
env:
CLI_E2E_MODE: live
CLI_E2E_TARGET_ENV: staging
CLI_E2E_API_URL: https://api.supabase.green
CLI_E2E_PROJECT_HOST: supabase.red
SUPABASE_LIVE_API_URL: https://api.supabase.green
SUPABASE_LIVE_PROJECT_NAME: supabase-cli-live-${{ matrix.target }}
CLI_HARNESS_TARGET: ${{ matrix.target }}
steps:
- name: Checkout
Expand Down Expand Up @@ -131,34 +129,19 @@ jobs:
- name: Docker preflight
run: docker info

- name: Run live e2e (retry up to 3x)
- name: Run live e2e
timeout-minutes: 20
env:
SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_E2E_CLI_LIVE_STAGING_ACCESS_TOKEN }}
run: |
PREFIX="cli-e2e-live-${CLI_HARNESS_TARGET}-${GITHUB_RUN_ID}-"
# GitHub runs this step as `bash -e`; use `if cmd; then` (errexit-exempt)
# so a failing attempt does not abort the step before the retry.
for attempt in 1 2 3; do
echo "::group::live e2e attempt ${attempt}"
if [ "$attempt" -gt 1 ]; then
bash .github/scripts/sweep-live-projects.sh "$PREFIX" || true
fi
if pnpm --filter @supabase/cli-e2e test:e2e:live; then
echo "::endgroup::"
exit 0
fi
echo "::endgroup::"
echo "attempt ${attempt} failed"
done
exit 1
run: pnpm --filter supabase test:live

# Backstop: delete any project this job created that survived a crash.
# The script exits non-zero (failing this step) if any delete failed.
- name: Cleanup leftover projects
if: always()
env:
SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_E2E_CLI_LIVE_STAGING_ACCESS_TOKEN }}
run: bash .github/scripts/sweep-live-projects.sh "cli-e2e-live-${CLI_HARNESS_TARGET}-${GITHUB_RUN_ID}-"
run: bash apps/cli/scripts/sweep-live-projects.sh "supabase-cli-live-${CLI_HARNESS_TARGET}-${GITHUB_RUN_ID}-"

# Record that this beta tested green so the next scheduled run skips it. Needs
# the whole matrix: the marker is saved only if the ts-legacy leg passed (a
Expand Down
129 changes: 76 additions & 53 deletions CONTRIBUTING.md

Large diffs are not rendered by default.

25 changes: 8 additions & 17 deletions apps/cli-e2e/.env.example
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
# cli-e2e environment — copy to `.env.local` (gitignored) and fill in.
# Only the live/record modes need real values; replay mode (the default) needs none.
# cli-e2e replay/record environment — copy to `.env.local` (gitignored) and fill in.
# Replay mode (the default) needs no environment variables.

# Mode: replay (default, no creds) | record (capture fixtures) | live (ADR-0013).
CLI_E2E_MODE=live

# Backend the live/record suite targets. Only `staging` is wired today.
CLI_E2E_TARGET_ENV=staging
# Set RECORD=true (or CLI_E2E_MODE=record) to capture fixtures from staging.
CLI_E2E_MODE=record

# CLI target under test: ts-legacy (the shipped shell, default) | ts-next.
# (The `go` target was retired when the Go CLI was trimmed to the proxied subset.)
CLI_HARNESS_TARGET=ts-legacy

# Staging Management API token. Either name works (the suite also reads
# SUPABASE_E2E_CLI_LIVE_STAGING_ACCESS_TOKEN). Required in record/live mode.
# Staging Management API token. Required in record mode.
SUPABASE_ACCESS_TOKEN=sbp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

# ts-legacy shells out to the bundled Go binary for the proxied commands
Expand All @@ -21,14 +17,9 @@ SUPABASE_ACCESS_TOKEN=sbp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# cd apps/cli-go && go build -o /tmp/supabase-test-binary .
SUPABASE_GO_BINARY=/tmp/supabase-test-binary

# --- Optional overrides (sensible defaults in src/tests/env.ts) ---
# Management API base + per-project host (default to staging: api.supabase.green / supabase.red).
# --- Optional record overrides (sensible defaults in src/tests/env.ts) ---
# Management API base (also accepted as SUPABASE_STAGING_URL).
# CLI_E2E_API_URL=https://api.supabase.green
# CLI_E2E_PROJECT_HOST=supabase.red
# DB password for the ephemeral project (default: random per run).
# DB password for the recording project (default: random per run).
# CLI_E2E_DB_PASSWORD=
# Skip org resolution / region / pick a specific org.
# CLI_E2E_ORG_ID=
# CLI_E2E_REGION=us-east-1
# Leave the ephemeral live project alive after the run (debugging).
# CLI_E2E_KEEP_PROJECT=1
25 changes: 3 additions & 22 deletions apps/cli-e2e/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,18 +141,6 @@ In **record mode**: global setup resolves the org, deletes any orphaned test pro

The pre-recording cleanup deletes projects named `cli-e2e-test`, `my-project`, and `to-delete` so re-recording never hits a 409 name-conflict. Do not add tests that rely on pre-existing named projects existing on staging.

## Live mode (ADR-0013)

`live` is a third mode (`CLI_E2E_MODE=live`) that, unlike replay/record, **does not use the replay server**. The harness is wired straight at the real Management API (`CLI_E2E_API_URL`) and the real Docker socket; tests assert on **real outcomes**.

- Live tests are `src/tests/live/**/*.live.e2e.test.ts`, run only via `vitest.live.config.ts` (the default config excludes them). They `skipIf(!isLive)`, so they are inert on the replay suite.
- Global setup (`tests/live-setup.ts`) provisions **one ephemeral project per run** (`cli-e2e-live-{target}-{runId}-{short}`), waits for `ACTIVE_HEALTHY`, resolves the anon JWT, the IPv4 **session-pooler `dbUrl`** (for `--db-url` DB commands), the functions URL, and a seeded storage bucket, exposing them via `inject()`. It deletes the project on teardown (even on failure). Setup is intentionally **dumb** — no provisioning retry; the CI job re-runs the step on flake.
- Use `testLive` from `src/tests/live/live-context.ts`: `run(cmd)` (direct-wired CLI), `invoke(slug)` (direct HTTP call sending the **anon JWT** in both `Authorization: Bearer` and `apikey`), plus `workspace` (a fresh `supabase init` config so golden paths exercise a generated config), `projectRef`, `anonKey`, `functionsUrl`, `dbUrl`, `storageBucket`. The functions deploy tests call `seedFunctions(workspace.path)` to layer the `deploy-e2e-*` fixtures + their `[functions.*]` config onto the init'd config.
- **Assertion style:** outcome-based — assert `exitCode`/`stdout` substrings and the function's HTTP status + JSON body. This is ID-agnostic, so **no normalization/snapshots by default**. If the CLI's own diagnostic output is ever the assertion target, add a scoped normalizer for that one test — do not make normalization the default.
- **Authoring/CI target is `ts-legacy`** — the only shipped CLI shell. It still shells out to the Go binary for the handful of commands the TS port proxies (`db diff`, `db pull`, `db branch *`, `db remote *`, `gen keys`, `functions download`), so `SUPABASE_GO_BINARY` must point at a built Go binary for those to resolve.
- Retargeting to another env (e.g. `supabox`) is an env swap only: `CLI_E2E_TARGET_ENV` + `CLI_E2E_API_URL` + `CLI_E2E_PROJECT_HOST` + token. Tests assert on function output, not hostnames.
- **CI triggers** (`.github/workflows/live-e2e.yml`): `workflow_dispatch` (manual; the Actions branch picker selects the ref — no free-form `ref` input, so the staging token never reaches arbitrary code) and an hourly `schedule`. There is **no `pull_request` trigger** — run it manually on a PR branch for pre-merge coverage. The scheduled run exercises the `@beta` channel: `develop` is the default branch and the beta release source, so it builds from `develop` source and runs the `ts-legacy` job. A `gate` job skips the run unless the published `supabase@beta` version changed since the last green run (an `actions/cache` marker keyed on the version, written by `finalize` only after the job passes), so a staging project is spent only when there is a new beta to test. Because the marker is written only on a green run, a chronically-failing `@beta` keeps re-running every hour until it goes green or a newer beta supersedes it (intended — the failure stays visible).

## Running the suite

```sh
Expand All @@ -162,18 +150,11 @@ pnpm nx run @supabase/cli-e2e:test:legacy # ts-legacy target
# Record (requires staging access)
SUPABASE_ACCESS_TOKEN=sbp_... SUPABASE_STAGING_URL=https://api.supabase.green \
pnpm nx run @supabase/cli-e2e:record

# Live (requires staging access; creates + deletes a real project; needs Docker).
# Build the Go binary first so newly-added proxy commands resolve (the system
# `supabase` may be stale) — mirrors what CI does.
cd apps/cli-go && go build -o /tmp/supabase-test-binary . && cd -
SUPABASE_GO_BINARY=/tmp/supabase-test-binary \
SUPABASE_ACCESS_TOKEN=sbp_... \
pnpm --filter @supabase/cli-e2e test:e2e:live
```

See `apps/cli-e2e/.env.example` for the full set of live/record env vars (copy to
a gitignored `.env.local`).
See `apps/cli-e2e/.env.example` for replay/record env vars (copy to a gitignored
`.env.local`). Live environment setup is documented in `apps/cli/AGENTS.md` and
`apps/cli/live.env.example`.

After recording, replay must pass with no changes between the two commands.

Expand Down
19 changes: 0 additions & 19 deletions apps/cli-e2e/fixtures/live/functions-config.toml

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

4 changes: 1 addition & 3 deletions apps/cli-e2e/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
"test:e2e": "bun --bun vitest run",
"test:legacy": "CLI_HARNESS_TARGET=ts-legacy bun --bun vitest run",
"test:next": "CLI_HARNESS_TARGET=ts-next bun --bun vitest run",
"test:e2e:live": "CLI_E2E_MODE=live CLI_E2E_TARGET_ENV=staging bun --bun vitest run --config vitest.live.config.ts",
"record": "RECORD=true CLI_HARNESS_TARGET=ts-legacy bun --bun vitest run",
"check:all": "nx run-many -t types:check lint:check fmt:check knip:check --projects=$npm_package_name",
"fix:all": "nx run-many -t lint:fix fmt:fix knip:fix --projects=$npm_package_name"
Expand All @@ -30,9 +29,8 @@
"knip": {
"entry": [
"src/**/*.e2e.test.ts",
"src/**/*.live.e2e.test.ts",
"tests/**/*.ts",
"vitest.live.config.ts"
"vitest.config.ts"
],
"ignore": [
"fixtures/**"
Expand Down
Loading
Loading