Repository navigation
chore: production deploy - #7340
supabase-cli-releaser[bot] wants to merge 174 commits into
Conversation
) Removes the last of the Go CLI: the deprecated commands and flags the TypeScript CLI still forwarded to a bundled `supabase-go` binary, and the Go source tree, toolchain and packaging behind them. Targets `next`, so it ships in the next major. The user-facing changes are in the `BREAKING CHANGE` footer at the end, which is what the release notes pick up. ## Notes for reviewers - The removed commands and flags stay registered but hidden, so using one exits 1 with its replacement rather than an unknown-command error. Each records a `RemovedSurfaceError` telemetry fingerprint (`removed_command` / `removed_flag`), so remaining usage can be tracked before the stubs are deleted outright. - `GoProxy` and its wiring in `cli/root.ts` and `shared/cli/run.ts` are deleted. - `apps/cli-go/` is deleted (its `LICENSE` moves to the repo root), along with the Go CI workflows, toolchain entries and Go-specific lint, format, knip, CODEOWNERS and dependabot config. Every platform package ships one `supabase` binary, and the install script removes a leftover `supabase-go`. - The `pkg/v*` tags of `github.com/supabase/cli/pkg` are frozen and protected by a ruleset. [ADR 0030](docs/adr/0030-go-cli-removal.md) records the removal, supersedes ADR 0016, and lists the known external importers of that module. Part of CLI-2432 BREAKING CHANGE: Removed the deprecated commands and flags that still ran through the bundled Go binary, and the `supabase-go` binary itself. If your scripts or CI use any of these, switch to the replacement. Each removed command or flag now exits with code 1 and prints its replacement. - `supabase db remote changes` → `supabase db diff --linked` - `supabase gen keys` → `supabase projects api-keys --project-ref <ref>` - `supabase db diff --use-pg-schema` → omit the flag to use the default engine, or pass `--use-pg-delta` - `supabase functions download --legacy-bundle` → `supabase functions download --use-api`. If that also fails and the Function was deployed with a CLI older than 1.120.0, redeploy it with the current CLI first. - `supabase db branch create`, `delete`, `list` and `switch` → removed with no local replacement. Hosted preview branches are managed with `supabase branches`. - `--create-ticket` (global flag) → removed. Report CLI problems with `supabase issue bug`. - `supabase-go` → no longer installed. Call `supabase` instead. --------- Co-authored-by: Claude Sonnet 5 <[email protected]>
…7064) ## Summary With the Go CLI removed on `next`, the codebase still described and named much of its behaviour in Go terms. This PR removes that, including user-facing error text that quoted Go library errors. Telemetry error identity (error `_tag`s and actionability fingerprints) is unchanged; the committed error-tag snapshot has no diff. **Config loading** - `@supabase/config`'s internal `goViperCompat` → `cliCompat` (still internal-only via `@supabase/config/internal`). - New `apps/cli/src/command-internal/cli-config-load.ts` wraps `loadCliConfig`, `resolveCliConfigValue`, `resolveCliConfigSubtree`, and the config-pull validation decode, always setting `cliCompat: true`. A code-structure guard keeps other `apps/cli` files from bypassing it. - Functions serve/deploy/download now require the CLI loader; the unused strict fallback and its constant `config.go_compat` span attribute are removed. Only `experimental compute` stays on the strict public loader. Whether to drop the lenient behaviour itself is a separate discussion. **Renames** - Go/pflag/cobra/viper-named files and identifiers are renamed for what they do, e.g. `go-json.ts` → `html-safe-json.ts`, `go-output.encoders.ts` → `output.encoders.ts`, `pflag-reconcile.ts` → `argv-flag-reconcile.ts`, `cobra-flag-groups.ts` → `flag-groups.ts`, `viper-env.ts` → `supabase-env.ts`, `*.go-payload.ts` → `*.response-shape.ts`, `FunctionsGoConfigCompat` → `FunctionsLocalConfigLoader`. - `ArgvWorkdirError`, `UrlParseError`, and `TomlEncodeError` keep their previous tag/fingerprint/`name` strings so error tracking is unaffected. - The `go-keyring-base64:` prefix on stored keyring tokens is unchanged (persisted data). **Docs, comments, test titles** - `SIDE_EFFECTS.md` files, CLI docs, `AGENTS.md`, comments, and test titles describe current behaviour instead of comparing against the Go CLI. ADRs are left as historical records. - Corrected two stale doc claims: `packages/stack` does not use the strict config default, and `test db` honours the global `--network-id`. ## Linked issue None; internal cleanup. - [x] I'm a Supabase maintainer. ## Checklist - [x] The PR title follows Conventional Commits. - [x] Tests added or updated for the change. - [x] `pnpm check:all` passes; relevant package tests pass for every touched workspace. 🤖 Generated with [Claude Code](https://claude.com/claude-code) BREAKING CHANGE: `COBRA_COMPLETION_DESCRIPTIONS` is no longer read; set `SUPABASE_COMPLETION_DESCRIPTIONS` to control shell completion descriptions. Error messages that quoted Go library errors are reworded: invalid boolean flag values (e.g. `sso add --skip-url-validation`) now say `expected a boolean` instead of `strconv.ParseBool: …`; invalid unsigned values for `storage cp --jobs` and `db reset --last` now say `expected an unsigned integer` (or `value out of range`) instead of `strconv.ParseUint: …`; oversized migration/seed statements report `scanner: token too long` instead of `bufio.Scanner: token too long`; `gen bearer-jwt` claim and JWK parse errors now read `invalid claims: expected a JSON object, got <kind>`, `invalid claims: number <n> is out of range`, `failed to parse JWK: expected a JSON object, got <kind>`, and `invalid JWK field <field>: expected <type>, got <kind>` instead of `json: cannot unmarshal … into Go value/struct field …`. Config type errors name values by shape: `SUPABASE_PROFILE` files report `expected a YAML mapping at the top level` and `array`/`object` type names, `[db]` glob entries report TOML type names (`local date`, `offset date-time`, `array`, `table`, …) instead of Go type names, and malformed `db lint`/`db advisors` payloads report `invalid <field>: expected <shape>` instead of naming Go types. `SUPABASE_PROFILE` errors are reworded (`unknown keys: …`, `<key> is required`, `<key> must be an http(s) URL`, `unsupported config file type …`, `no profile config file specified`) and multi-line profile errors no longer pad lines with trailing spaces. Config decode errors drop the `decoding failed due to the following error(s):` header and render entries as `<key>: expected a string, got <type>`, `<key>: unknown keys: …`, `<key>: must be one of …`. `failed to unmarshal …` messages (postgres-config, bootstrap templates, functions download) now read `failed to parse …`, `db lint`'s `failed to marshal json:` reads `failed to parse lint result:`, and TOML output errors drop the `toml:` prefix. --------- Co-authored-by: Claude Opus 5.5 <[email protected]>
…7066) ## TL;DR pg-delta becomes the schema diff engine for every project, not only ones created by a recent `supabase init`. A `config.toml` with no `[experimental.pgdelta]` section, or a section that omits `enabled`, now resolves to pg-delta for `db diff`, `db pull`, and `db remote commit`. Migra stays available through a one-line rollback. ```mermaid flowchart LR subgraph Before A1["no [experimental.pgdelta]"] --> M1[migra] B1["enabled = true"] --> P1[pg-delta] C1["SUPABASE_EXPERIMENTAL_PG_DELTA=1"] --> P1 end subgraph After A2["no [experimental.pgdelta]"] --> P2[pg-delta] B2["enabled = false"] --> M2[migra] C2["--use-migra / --diff-engine migra"] --> M2 end ``` ## Why [CLI-1587](https://linear.app/supabase/issue/CLI-1587) opted new projects into pg-delta, but existing projects still diffed with migra unless they edited `config.toml`. This finishes the migration so every project uses the same engine. ## What changed - `[experimental.pgdelta].enabled` defaults to `true` when absent, in the CLI's config reader and in `@supabase/config` (including the published JSON schema). An explicit `enabled = false` still selects migra. - The historical `SUPABASE_EXPERIMENTAL_PG_DELTA` opt-in env var is no longer read. With pg-delta on by default it added nothing, and a stale value would have silently overridden `enabled = false`. `--use-pg-delta` remains the per-run override. - `db schema declarative generate` / `sync` no longer need `--experimental`. They are closed only when `enabled = false` is set and `--experimental` is omitted. - A versionless `db reset --experimental` (and a fresh-volume `start --experimental`) applies `[db.migrations].schema_paths` files only when pg-delta is explicitly disabled. Otherwise it replays migrations and, when `schema_paths` is set, prints a warning naming the `enabled = false` rollback (before the remote reset's confirmation prompt). - `db pull --declarative` writes `[db.migrations].schema_paths` into `config.toml` only when pg-delta is explicitly disabled. - `db diff -f` that finds declarative schema files it did not read prints a note pointing to `supabase db schema declarative sync` (and to `--use-migra` when migra would read those files), including when the diff is empty. Local diffs without `-f` only report the JSON advisory. - The `schema_paths` warning on `db diff` / `db pull` explains that `declarative sync` reads `declarative_schema_path`, not `schema_paths`, and names the `enabled = false` rollback. The declarative-command gate suggests `--experimental` rather than undoing `enabled = false`. - On the stack backend, `--use-migra=false` / `--use-pgadmin=false` are accepted, since they keep pg-delta. - `db diff --use-migra=false` keeps the pg-delta default instead of selecting migra. - Help text, command docs, and `SIDE_EFFECTS.md` contracts describe pg-delta as the default. ## Linked issue Closes [CLI-1588](https://linear.app/supabase/issue/CLI-1588) ## BREAKING CHANGES: pg-delta is now the default schema diff engine for all projects. Generated migration SQL from `db diff`, `db pull`, and `db remote commit` changes for projects that had not opted in. Under pg-delta, `[db.migrations].schema_paths` and declarative files in `supabase/schemas` are no longer inputs to `db diff` or migration-style `db pull`, so the "edit `supabase/schemas`, then `db diff -f`" workflow no longer picks up those edits; use `supabase db schema declarative sync` to generate migrations from declarative schema files. To keep migra, set this in `supabase/config.toml`: ```toml [experimental.pgdelta] enabled = false ``` or pass `--use-migra` (`db diff`) / `--diff-engine migra` (`db pull`) per run. `SUPABASE_EXPERIMENTAL_PG_DELTA` is ignored. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <[email protected]>
# Conflicts: # .github/workflows/cli-go-api-sync.yml # .github/workflows/cli-go-mirror.yml # CONTRIBUTING.md # apps/cli-go/pkg/config/templates/Dockerfile # apps/cli/docs/release-process.md # apps/cli/src/cli/complete.ts # apps/cli/src/command-internal/db-bootstrap/local-container-inputs.ts # apps/cli/src/command-internal/db-bootstrap/shadow-cache.ts # apps/cli/src/command-internal/db-config.integration.test.ts # apps/cli/src/command-internal/db-config.parse.unit.test.ts # apps/cli/src/command-internal/db-config.toml-read.ts # apps/cli/src/command-internal/db-config.toml-read.unit.test.ts # apps/cli/src/command-internal/db-connection.sql-pg.integration.test.ts # apps/cli/src/command-internal/db-connection.sql-pg.unit.test.ts # apps/cli/src/command-internal/db-image.unit.test.ts # apps/cli/src/command-internal/debug-logger.layer.ts # apps/cli/src/command-internal/debug-logger.layer.unit.test.ts # apps/cli/src/command-internal/docker-ids.unit.test.ts # apps/cli/src/command-internal/experimental-gate.unit.test.ts # apps/cli/src/command-internal/global-flags.ts # apps/cli/src/command-internal/go-proxy.layer.ts # apps/cli/src/command-internal/go-proxy.layer.unit.test.ts # apps/cli/src/command-internal/local-project-context.ts # apps/cli/src/command-internal/local-project-context.unit.test.ts # apps/cli/src/command-internal/pg-dump.run.ts # apps/cli/src/command-internal/profile-load.ts # apps/cli/src/command-internal/profile-load.unit.test.ts # apps/cli/src/command-internal/project-environment.unit.test.ts # apps/cli/src/command-internal/stack-shadow-cache.ts # apps/cli/src/command-internal/string-slice-flag.ts # apps/cli/src/command-internal/supabase-env.ts # apps/cli/src/command-internal/viper-env.unit.test.ts # apps/cli/src/commands/db/branch/branch.command.ts # apps/cli/src/commands/db/branch/create/create.command.ts # apps/cli/src/commands/db/branch/delete/delete.command.ts # apps/cli/src/commands/db/branch/list/list.command.ts # apps/cli/src/commands/db/branch/switch/switch.command.ts # apps/cli/src/commands/db/diff/diff.command.ts # apps/cli/src/commands/db/dump/SIDE_EFFECTS.md # apps/cli/src/commands/db/dump/dump.handler.ts # apps/cli/src/commands/db/pull/SIDE_EFFECTS.md # apps/cli/src/commands/db/pull/pull.integration.test.ts # apps/cli/src/commands/db/remote/changes/changes.command.ts # apps/cli/src/commands/db/schema/declarative/generate/generate.integration.test.ts # apps/cli/src/commands/db/schema/declarative/sync/sync.integration.test.ts # apps/cli/src/commands/db/test/SIDE_EFFECTS.md # apps/cli/src/commands/functions/download/download.command.ts # apps/cli/src/commands/gen/keys/keys.command.ts # apps/cli/src/commands/gen/types/types.command.ts # apps/cli/src/commands/gen/types/types.handler.ts # apps/cli/src/commands/start/SIDE_EFFECTS.md # apps/cli/src/commands/start/start.handler.ts # apps/cli/src/commands/storage/cp/cp.command.ts # apps/cli/src/shared/cli/run.unit.test.ts # apps/cli/src/shared/functions/deploy.ts # apps/cli/src/shared/functions/download.ts # apps/cli/src/shared/functions/serve.ts # apps/cli/src/shared/init/project-init.templates.unit.test.ts # apps/cli/src/shared/telemetry/error-actionability.ts # apps/cli/src/telemetry/command-telemetry.unit.test.ts # docs/adr/README.md # knip.jsonc # mise.lock # mise.toml
…ults (#7074) ## Summary Every config value now resolves in one order, in every command: `explicit flag > shell env > project env files > config (config.json over config.toml, a matched [remotes.*] block over the base) > default` Project env files are `.env.<SUPABASE_ENV>.local`, `.env.local`, `.env.<SUPABASE_ENV>` and `.env`. They are read from `supabase/` and then the project root, and `SUPABASE_ENV` defaults to `development`. Before this change, each command family overlaid flags, env and remotes by hand, and the families disagreed: - A matched `[remotes.*]` block beat an explicit `SUPABASE_*` variable. - Some commands ignored variables that others honoured. - `config diff` and `config push` could see different values. - `--password` was silently dropped when combined with `--db-url`. ADR 0001 already defined this order, so this is mostly making the code actually follow it. Closes CLI-1885, closes CLI-2214. The decisions are recorded in [ADR 0031](docs/adr/0031-config-value-precedence.md). ## How it works Before, every command decided for itself where a setting came from, and they didn't agree. Now one service answers "what's the value of X?" for every command, and it always asks the same sources in the same order. ### The problem A setting like "should `db push` seed?" can come from five places: 1. a flag you typed (`--include-seed`) 2. your shell (`export SUPABASE_DB_SEED_ENABLED=true`) 3. a project env file (`supabase/.env`, `.env.local`, ...) 4. `config.toml`, where a matching `[remotes.staging]` block beats the base `[db.seed]` 5. a built-in default Each command family used to walk that list by hand, in its own order, with its own parser. So `db push` and `start` could look at the same setting and get different answers, a remote block could beat your shell env in one command but not another, and `config diff` could show something different from what `config push` would send. ### The service: `CliConfigValues` Think of it as a librarian. You don't go into the stacks yourself; you ask the librarian. It checks the five shelves in one fixed order and hands you the first answer it finds, with a note saying which shelf it came from. ``` flag > shell env > project .env* > config.toml (remote over base) > default ``` A command uses it in three steps. **1. Load the resolved config once per run.** ```ts const configValues = yield* CliConfigValues const resolvedConfig = yield* configValues.load({ workdir, projectRef }) ``` This reads the flags, the env and the env files, parses `config.toml`, picks the matching `[remotes.*]` block, applies the order above and validates the whole config. If anything is invalid (for example `SUPABASE_STUDIO_PORT=abc`), the command stops here, and the error names where the bad value came from. **2. Ask for a value by key.** ```ts const enabled = yield* resolvedConfig.get(CliConfigKeys.db.seed.enabled) // enabled.value → true // enabled.origin → { tier: "shell", envName: "SUPABASE_DB_SEED_ENABLED" } ``` You get the value plus its origin. That origin is what lets the CLI say things like `SUPABASE_AUTH_SITE_URL (shell) overrides auth.site_url in [remotes.staging]` or `(from SUPABASE_API_MAX_ROWS in supabase/.env)`. **3. Bind flags to keys instead of reading them by hand.** ```ts // push.command.ts includeSeed: CliConfigKeys.db.seed.enabled.flag({ name: "include-seed", description: "Include seed data from your config.", }), ``` The flag isn't a separate boolean the handler has to remember to merge in. It is declared as the flag tier of `db.seed.enabled`, so the resolved config already knows about it. ### Where the keys come from `CliConfigKeys` is generated from the config schema (`CliConfigSchema`). Every leaf in `config.toml` becomes a key with: - its path: `db.seed.enabled` - its env name: `SUPABASE_` plus the path in upper snake case, so `SUPABASE_DB_SEED_ENABLED` - a parser chosen from its type: boolean, port, list, and so on Nobody writes the 360 or so keys by hand. Add a field to the schema and it gets an env override and a parser for free. The only hand-written parts are exceptions, such as codec overrides, exclusions and section gates like "SMTP env vars only apply if `[auth.email.smtp]` exists". ### A worked example ```toml [db.seed] enabled = true [remotes.staging] project_id = "abc123" [remotes.staging.db.seed] enabled = false ``` ```bash SUPABASE_DB_SEED_ENABLED=true supabase db push --project-ref abc123 --include-seed ``` | Shelf | Says | Used? | |---|---|---| | flag `--include-seed` | true | ✅ wins | | shell `SUPABASE_DB_SEED_ENABLED` | true | | | project `.env*` | unset | | | `[remotes.staging.db.seed]` | false | | | `[db.seed]` (base) | true | | | default | false | | Seeding is on, from the flag. Without the flag, the shell value wins (still on, origin shell). Before this PR, the remote block's `false` would have beaten the shell variable, which is the headline breaking change. And because seeding is on for a project that matched a remote block that doesn't itself turn seeding on, the CLI asks for confirmation before seeding. ### How it relates to `config.toml` `config.toml` isn't replaced. It's shelf 4. The `@supabase/config` package still parses it, merges the matching remote and decodes it. The service calls those package stages and layers flags and env on top, and commands can no longer call the package loaders directly. The resolved config gives two views of the whole config: - `resolvedConfig.loaded`: what you declared (file plus flags and env), with no defaults. `config push` and `config diff` use this, so push never sends a default you didn't write. - `resolvedConfig.materialized`: the same with defaults applied. Used by things that need a complete config to run, like `start`, local Docker and stack. ### What stops this drifting back - A guard test fails if any file outside the service mentions a `SUPABASE_*` config env name or imports the package config loaders. - `oxlint` bans `process.env` and `Bun.env` across the CLI. - A command that reads config without wiring the service in fails `tsc`. - A contract test checks every key in the registry against the order. ## Design It's a big diff, sorry - but most of it is commands moving onto the new service. The interesting parts are `apps/cli/src/config/cli-config-*.ts`, the guard tests in `code-structure.unit.test.ts` and ADR 0031. If you disagree with any of the behaviour calls in the table below, that's totally fine, I'd rather we settle them here than after `next` ships. - One service. `CliConfigValues` is the only service that resolves values. - `load({ workdir, projectRef })` returns a memoised `ResolvedCliConfig`. - `resolvedConfig.get(key)` returns the value and the tier it came from. - `resolvedConfig.loaded` is the declared config: file, flags and env, with no defaults. `config push` and `config diff` use it. - `resolvedConfig.materialized` is the declared config with defaults applied. - The whole config is decoded on load, so an invalid value fails the command before it does anything. - Generated key registry. The registry is generated from `CliConfigSchema`. Each leaf gets the env name `SUPABASE_` + its upper-snake path, and a codec derived from its type. Section gates, codec overrides and exclusions are hand-written annotations. - Flags. A flag binds to a key with `key.flag(...)`, so "explicitly passed" is part of the type rather than a convention. If two flags set the same key to different values, the first load fails with `CliConfigFlagConflictError`. - Package stages. `@supabase/config/internal` exposes the pipeline stages: parse, merge a selected remote, decode. Only the foundation calls them. - Guardrails: - A code-structure test fails on: - registry env names written as string literals outside the foundation files - imports of the package loaders (`loadCliConfig`, `resolveCliConfigSubtree`, `loadCliProjectEnvironment`) outside the foundation - the old overlay helpers - registry-backed flags declared without `key.flag` - `oxlint` bans `process.env`, `Bun.env`, `globalThis.process` and `env` imported from `node:process` across `apps/cli/src`. - A command that reads config values without `withCliConfigFlags` fails `tsc`. - Visibility: - When a shell or project env value beats a value that the matched `[remotes.*]` block sets, the CLI prints one WARN per key. - `--debug` lists the origin of every non-default value. - `config push` labels env-sourced rows and prints a one-line summary of them, even with `--yes`. - Exceptions kept on purpose: - `CommandSettings` reads `SUPABASE_PROJECT_ID` from the shell only. - `experimental-feature.ts` ignores remotes and env files, because it runs before the project is known. - `db.password` has no env tier. - `secrets set` tolerates an invalid unrelated value, so a broken key doesn't block rotating a secret. - The service-role key isn't scoped to the linked project; only the database password is. ## Behaviour changes | Change | Before | Now | | --- | --- | --- | | Env vs matched remote | A `[remotes.*]` block beat `SUPABASE_*` variables for the keys it set | Flags and env beat the block, with a WARN for each key they override | | `SUPABASE_PROJECT_ID` and a matched remote | The remote's `project_id` named local Docker resources | `SUPABASE_PROJECT_ID` wins | | `--include-seed` and `enabled = false` | A remote's or the base's `[db.seed] enabled = false` won | `--include-seed`, `--sql-paths` or `SUPABASE_DB_SEED_ENABLED=true` override it. `db push` still seeds only with `--include-seed` | | Seed confirmation | None | `db push` and `db reset --linked` ask before seeding a project that matched a `[remotes.*]` block, unless that block itself sets `db.seed.enabled = true`. `--yes` or `SUPABASE_YES` confirms. A non-interactive run without it exits 1 with `SeedConsentRequiredError` before applying anything | | `--password` with `--db-url` or `--local` | Silently ignored by `db push`, `db pull`, `db dump` and `db schema declarative generate` | Exits 1 with a message saying where the password goes instead. `migration list` and `migration repair` now also reject `--local`. `migration squash` targets the local database unless you pass `--linked`, so `squash -p` needs `--linked`. An empty `-p ""` counts as not passed | | `SUPABASE_DB_PASSWORD` for another project | Sent to whichever project was targeted | Withheld when the target differs from the linked project. A notice names both refs and says a temporary login role is used instead. Unlinked directories and same-project targets keep using the variable | | `db diff --use-pg-delta=false` | No effect against env or config | Turns pg-delta off over env and config. The stack backend always uses pg-delta | | `db pull --use-pg-delta` (hidden, deprecated) | Selected the declarative export only | Also turns pg-delta on for the run, so the export leaves `[db.migrations].schema_paths` alone | | `SUPABASE_EXPERIMENTAL_PGDELTA_ENABLED` | Not read | Overrides `[experimental.pgdelta].enabled` like any other key, so `false` selects migra for the run. `SUPABASE_EXPERIMENTAL_PG_DELTA` stays ignored | | Boolean variables | Each reader had its own parser (`SUPABASE_EXPERIMENTAL_STACK` took `0`/`1` only) | One grammar everywhere: `1`, `t`, `T`, `true`, `True`, `TRUE` or `0`, `f`, `F`, `false`, `False`, `FALSE`. Anything else, including mixed case like `tRue`, fails the command | | Invalid config value | Failed only the commands that read it, with a command-specific error | Fails every command that loads the config (including `stop` and `services`) with `CliConfigValueError`, naming the variable or file it came from. `functions new` also stops before writing anything instead of falling back to defaults. `secrets set` is the one exception | | Env applies wherever a key is read | Some readers ignored variables others honoured, e.g. storage and realtime `enabled`, `SUPABASE_API_PORT` in `functions serve`, `SUPABASE_API_SCHEMAS` in `gen types --linked` | One behaviour per key, and validation runs on the effective values. Env for a key inside an optional section (webhooks, SMS providers, captcha, SMTP, ...) still applies only when that section exists | | Ports | `/^\d+$/` in one reader, octal-aware in another | One parser: decimal, `0x`, `0o`, `0b` and `_` separators, max 65535. A leading zero (`054322`) is rejected | | `SUPABASE_REMOTES_<NAME>_PROJECT_ID` | Worked for `db` commands only | Selects the remote in every command, including `secrets set`, `config diff`, `config push` and storage | | Local Docker project id | `start` and `functions` fell back to the project ref; the db readers used the folder name | Always the sanitised folder name, never the ref | | `gen types --local` password | Read `SUPABASE_DB_PASSWORD` | Uses `[db].password`, like every other `--local` command | | `services`, `functions deploy`, `functions download`, `functions serve` | Read `config.toml` only, in places | Read `config.json` first, like every other command | | `config push` and `config diff` | Push sent the declared document; diff read the file on its own | Both apply `SUPABASE_*` and flag overrides and show the same values. Env-sourced rows are labelled, and JSON output carries `origin` | | Default workdir | The walk up from the current directory looked for `supabase/config.toml` only; some commands then climbed again for `config.json` | One walk for every command, stopping at the nearest `supabase/config.toml` or `supabase/config.json`. A nested `config.json` project now wins over an outer `config.toml` one | | `SUPABASE_SERVICES_HOSTNAME` | Read from the project `.env` by `gen types` and seed buckets only, ahead of the shell | Read by every local command, shell first, then project `.env*`. The Docker daemon still comes from the shell environment only | | `[experimental.inspect.rules]` | `inspect report` accepted a single table and non-string rule fields | Rules must be `[[experimental.inspect.rules]]` with string fields, as every other command already required | | `link --password` | Listed in help | Hidden, deprecated and ignored with a warning. It never connected to the database | ### Newly env-overridable keys Four config keys had no `SUPABASE_*` override before and now have one: - `auth.sms.otp_expiry` (`SUPABASE_AUTH_SMS_OTP_EXPIRY`) - `auth.sms.otp_length` (`SUPABASE_AUTH_SMS_OTP_LENGTH`) - `db.network_restrictions.allowed_cidrs` (`SUPABASE_DB_NETWORK_RESTRICTIONS_ALLOWED_CIDRS`) - `db.network_restrictions.allowed_cidrs_v6` (`SUPABASE_DB_NETWORK_RESTRICTIONS_ALLOWED_CIDRS_V6`) ### Error codes - `MigrationPasswordFlagsError` is now `DbPasswordFlagsError`. - Invalid values report `CliConfigValueError` instead of `DbConfigLoadError`, `SeedConfigLoadError`, `StatusConfigLoadError` or `StopConfigLoadError`. - Seeding without consent reports the new `SeedConsentRequiredError`. BREAKING CHANGE: Flags and `SUPABASE_*` environment variables now override config, including a matched `[remotes.<name>]` block. Every value resolves in one order: flag > shell environment > project env files > `config.json`/`config.toml` (a matched remote block over the base) > default. Project env files are `.env.<SUPABASE_ENV>.local`, `.env.local`, `.env.<SUPABASE_ENV>` and `.env`, in `supabase/` and then the project root; `SUPABASE_ENV` defaults to `development`. - If you deploy to a project with a `[remotes.*]` block, any `SUPABASE_*` variable in the job or in those files now beats the block. The CLI warns for each value it overrides. Check `env | grep ^SUPABASE_` in CI and `grep -h ^SUPABASE_ supabase/.env* .env*` in the repo, and set `SUPABASE_ENV` in CI so `.env.development` doesn't apply. - `supabase config push` now pushes those overrides; for example, a `SUPABASE_AUTH_SITE_URL` in `.env.local` replaces the value in `[remotes.production]`. Push labels each env-sourced value, and `supabase config diff` shows the same values. - Seeding a project that matches a `[remotes.*]` block now asks first, unless the block itself sets `db.seed.enabled = true`. `db push --include-seed` and `db reset --linked` exit 1 in CI unless you pass `--yes`. `--include-seed` and `SUPABASE_DB_SEED_ENABLED=true` now override `enabled = false` in the base `[db.seed]` too. `db push` still seeds only with `--include-seed`. - `--password` with `--local` or `--db-url` now exits 1 on `db push`, `db pull`, `db dump`, `db schema declarative generate`, `migration list` and `migration repair`. `migration squash` targets the local database by default, so `migration squash -p` needs `--linked`. Put the password in the URL, or set `[db].password` for the local database. - In a directory linked to project A, `SUPABASE_DB_PASSWORD` is no longer sent to another project (`--project-ref B`). Pass `--password`, or provide an access token so the CLI can create a temporary login role. - An invalid value in config or in a `SUPABASE_*` variable now fails every command that loads project config, including `db push`, `stop` and `services` (for example `SUPABASE_STUDIO_PORT=abc`). The error names the variable or file and reports `CliConfigValueError`. - `SUPABASE_EXPERIMENTAL_PGDELTA_ENABLED` overrides `[experimental.pgdelta].enabled`, so `false` selects migra for the run. Boolean variables, including `SUPABASE_EXPERIMENTAL_STACK`, accept `1`, `t`, `T`, `true`, `True`, `TRUE` or `0`, `f`, `F`, `false`, `False`, `FALSE` and fail on anything else. - `supabase db diff --use-pg-delta=false` now turns pg-delta off even when config or env turns it on. - `supabase gen types --local` uses `[db].password`, not `SUPABASE_DB_PASSWORD`. - `SUPABASE_PROJECT_ID` now names local containers even when a remote block matches. Without a `project_id` in config.toml, local containers and volumes are named after the project folder, not the project ref. Run `supabase stop` before upgrading, or set `project_id`. - Ports with a leading zero (`054322`) are rejected. - `services` and the `functions` commands read `config.json` before `config.toml`. - Without `--workdir`, the CLI uses the nearest directory with `supabase/config.toml` or `supabase/config.json`, so a nested `config.json` project now wins over an outer `config.toml` one. - `inspect report` needs `[[experimental.inspect.rules]]` with string fields; a single `[experimental.inspect.rules]` table now fails. - `supabase link --password` is deprecated and ignored. - Error codes: `MigrationPasswordFlagsError` is now `DbPasswordFlagsError`; invalid values report `CliConfigValueError`; seeding without consent reports `SeedConsentRequiredError`.
#7109) ## Summary This removes four commands that have been deprecated for at least one stable cycle and have a direct replacement. They stay registered but are hidden from help. Running any of them now exits 1 and names the replacement. This uses the same `removedCommand()` tombstone as `db remote changes` and `gen keys`. | Command | Replacement | | -- | -- | | `db remote commit` | `db pull` | | `inspect db total-index-size` | `inspect db index-stats` | | `inspect db total-table-sizes` | `inspect db table-stats` | | `inspect db table-index-sizes` | `inspect db table-stats` | - The tombstones still accept their old flags, so existing invocations reach the removal error instead of a parse error. The inspect tombstones open no DB connection. - Each tombstone records a `RemovedSurfaceError` telemetry fingerprint (`removed_command`), so remaining usage stays visible. - Their handlers, handler tests and per-command docs pages are deleted. SIDE_EFFECTS.md and the `DOCS_EXCLUDED` table are updated. - The pg-delta config description no longer mentions `db remote commit`, and `config.schema.json` is regenerated. - The higher-use `inspect db` aliases (`table-sizes`, `index-sizes`, `cache-hit`, …) are unchanged. The matching "removed in v3" warning text for stable is in #7108 (develop). ## Linked issue Part of CLI-2595 ## Checklist - [x] The PR title follows Conventional Commits. - [x] Tests added or updated: `hidden-flag.unit.test.ts` runs all four tombstones and asserts the removal message and suggestion, and checks they're absent from `inspect db --help`. - [x] From the repository root, `pnpm check:all` passes. 🤖 Generated with [Claude Code](https://claude.com/claude-code) BREAKING CHANGE: `supabase db remote commit` is removed; use `supabase db pull`. `supabase inspect db total-index-size` is removed; use `supabase inspect db index-stats`. `supabase inspect db total-table-sizes` and `supabase inspect db table-index-sizes` are removed; use `supabase inspect db table-stats`. Each removed command exits 1 and prints its replacement. --------- Co-authored-by: Claude Opus 5.5 <[email protected]>
# Conflicts: # .oxlintrc.effect.json # apps/cli-go/pkg/config/templates/Dockerfile # apps/cli/src/command-internal/db-bootstrap/local-db-running.ts # apps/cli/src/command-internal/db-pull-run.ts # apps/cli/src/command-internal/docker-ids.ts # apps/cli/src/command-internal/docker-ids.unit.test.ts # apps/cli/src/command-internal/local-project-context.ts # apps/cli/src/command-internal/pgdelta.ts # apps/cli/src/command-internal/seed-buckets.ts # apps/cli/src/command-internal/storage-content-type.unit.test.ts # apps/cli/src/command-internal/storage-credentials.ts # apps/cli/src/command-internal/storage-url.ts # apps/cli/src/commands/backups/list/list.integration.test.ts # apps/cli/src/commands/backups/restore/restore.integration.test.ts # apps/cli/src/commands/branches/create/create.integration.test.ts # apps/cli/src/commands/branches/delete/delete.integration.test.ts # apps/cli/src/commands/branches/get/get.integration.test.ts # apps/cli/src/commands/branches/list/list.integration.test.ts # apps/cli/src/commands/branches/pause/pause.integration.test.ts # apps/cli/src/commands/branches/update/update.handler.ts # apps/cli/src/commands/completion/bash/bash.integration.test.ts # apps/cli/src/commands/completion/completion-scripts.unit.test.ts # apps/cli/src/commands/completion/fish/fish.integration.test.ts # apps/cli/src/commands/completion/powershell/powershell.integration.test.ts # apps/cli/src/commands/completion/zsh/zsh.integration.test.ts # apps/cli/src/commands/config/config.load.ts # apps/cli/src/commands/config/diff/diff.integration.test.ts # apps/cli/src/commands/config/pull/pull.integration.test.ts # apps/cli/src/commands/config/push/push.handler.ts # apps/cli/src/commands/config/push/push.integration.test.ts # apps/cli/src/commands/db/diff/diff.handler.ts # apps/cli/src/commands/db/pull/pull.integration.test.ts # apps/cli/src/commands/db/remote/commit/SIDE_EFFECTS.md # apps/cli/src/commands/db/remote/commit/commit.command.ts # apps/cli/src/commands/db/remote/commit/commit.handler.ts # apps/cli/src/commands/db/schema/declarative/generate/generate.handler.ts # apps/cli/src/commands/db/schema/declarative/sync/sync.handler.ts # apps/cli/src/commands/db/shared/pgdelta.seam.layer.ts # apps/cli/src/commands/domains/activate/activate.integration.test.ts # apps/cli/src/commands/domains/create/create.integration.test.ts # apps/cli/src/commands/domains/delete/delete.integration.test.ts # apps/cli/src/commands/domains/get/get.integration.test.ts # apps/cli/src/commands/domains/reverify/reverify.integration.test.ts # apps/cli/src/commands/experimental/compute/compute.shared.ts # apps/cli/src/commands/experimental/compute/list/list.integration.test.ts # apps/cli/src/commands/feedback/add/add.integration.test.ts # apps/cli/src/commands/feedback/delete/delete.integration.test.ts # apps/cli/src/commands/functions/delete/delete.integration.test.ts # apps/cli/src/commands/functions/deploy/deploy.integration.test.ts # apps/cli/src/commands/functions/download/download.handler.ts # apps/cli/src/commands/functions/download/download.integration.test.ts # apps/cli/src/commands/functions/list/list.encoders.ts # apps/cli/src/commands/functions/list/list.integration.test.ts # apps/cli/src/commands/functions/new/new.integration.test.ts # apps/cli/src/commands/functions/serve/serve.integration.test.ts # apps/cli/src/commands/gen/bearer-jwt/bearer-jwt.claims.ts # apps/cli/src/commands/gen/bearer-jwt/bearer-jwt.integration.test.ts # apps/cli/src/commands/gen/gen.signing-keys-config.ts # apps/cli/src/commands/gen/signing-key/signing-key.integration.test.ts # apps/cli/src/commands/gen/types/types.integration.test.ts # apps/cli/src/commands/inspect/db/inspect-deprecated.integration.test.ts # apps/cli/src/commands/inspect/db/table-index-sizes/table-index-sizes.command.ts # apps/cli/src/commands/inspect/db/table-index-sizes/table-index-sizes.handler.ts # apps/cli/src/commands/inspect/db/total-index-size/total-index-size.command.ts # apps/cli/src/commands/inspect/db/total-index-size/total-index-size.handler.ts # apps/cli/src/commands/inspect/db/total-table-sizes/total-table-sizes.command.ts # apps/cli/src/commands/inspect/db/total-table-sizes/total-table-sizes.handler.ts # apps/cli/src/commands/logout/logout.integration.test.ts # apps/cli/src/commands/network-bans/get/get.integration.test.ts # apps/cli/src/commands/network-bans/network-bans.experimental-gate.integration.test.ts # apps/cli/src/commands/network-bans/remove/remove.integration.test.ts # apps/cli/src/commands/network-restrictions/get/get.integration.test.ts # apps/cli/src/commands/network-restrictions/network-restrictions.cidr.unit.test.ts # apps/cli/src/commands/network-restrictions/network-restrictions.experimental-gate.integration.test.ts # apps/cli/src/commands/network-restrictions/update/update.integration.test.ts # apps/cli/src/commands/notebooks/notebooks.integration.test.ts # apps/cli/src/commands/orgs/create/create.integration.test.ts # apps/cli/src/commands/orgs/list/list.integration.test.ts # apps/cli/src/commands/postgres-config/delete/delete.command.unit.test.ts # apps/cli/src/commands/postgres-config/postgres-config.experimental-gate.integration.test.ts # apps/cli/src/commands/postgres-config/postgres-config.integration.test.ts # apps/cli/src/commands/postgres-config/update/update.command.unit.test.ts # apps/cli/src/commands/projects/api-keys/api-keys.integration.test.ts # apps/cli/src/commands/projects/create/create.integration.test.ts # apps/cli/src/commands/projects/delete/delete.integration.test.ts # apps/cli/src/commands/projects/list/list.integration.test.ts # apps/cli/src/commands/pull/pull.integration.test.ts # apps/cli/src/commands/secrets/list/list.integration.test.ts # apps/cli/src/commands/secrets/set/set.integration.test.ts # apps/cli/src/commands/secrets/unset/unset.integration.test.ts # apps/cli/src/commands/snippets/download/download.handler.ts # apps/cli/src/commands/snippets/download/download.integration.test.ts # apps/cli/src/commands/snippets/list/list.integration.test.ts # apps/cli/src/commands/ssl-enforcement/get/get.integration.test.ts # apps/cli/src/commands/ssl-enforcement/update/update.integration.test.ts # apps/cli/src/commands/sso/add/add.command.unit.test.ts # apps/cli/src/commands/sso/add/add.handler.ts # apps/cli/src/commands/sso/add/add.integration.test.ts # apps/cli/src/commands/sso/info/info.integration.test.ts # apps/cli/src/commands/sso/list/list.integration.test.ts # apps/cli/src/commands/sso/remove/remove.integration.test.ts # apps/cli/src/commands/sso/show/show.integration.test.ts # apps/cli/src/commands/sso/sso.string-slice-flags.integration.test.ts # apps/cli/src/commands/sso/update/update.command.unit.test.ts # apps/cli/src/commands/sso/update/update.handler.ts # apps/cli/src/commands/sso/update/update.integration.test.ts # apps/cli/src/commands/storage/cp/cp.command.integration.test.ts # apps/cli/src/commands/storage/ls/ls.integration.test.ts # apps/cli/src/commands/storage/rm/rm.integration.test.ts # apps/cli/src/commands/storage/storage.frame.ts # apps/cli/src/commands/vanity-subdomains/vanity-subdomains.integration.test.ts # apps/cli/src/commands/whoami/whoami.integration.test.ts
# Conflicts: # apps/cli/src/command-internal/db-pull-run.ts # apps/cli/src/commands/db/pull/SIDE_EFFECTS.md # apps/cli/src/commands/db/pull/pull.integration.test.ts # apps/cli/src/commands/domains/SIDE_EFFECTS.md # apps/cli/src/commands/domains/activate/activate.integration.test.ts # apps/cli/src/commands/domains/create/create.integration.test.ts # apps/cli/src/commands/domains/delete/delete.integration.test.ts # apps/cli/src/commands/domains/get/get.integration.test.ts # apps/cli/src/commands/domains/reverify/reverify.integration.test.ts # apps/cli/src/telemetry/linked-project-cache.integration.test.ts
# Conflicts: # apps/cli/src/command-internal/db-pull-run.ts # apps/cli/src/command-internal/migrate-and-seed.unit.test.ts # apps/cli/src/command-internal/migration-apply.ts # apps/cli/src/command-internal/migration-apply.unit.test.ts # apps/cli/src/command-internal/migration-history.unit.test.ts # apps/cli/src/command-internal/pgdelta.ts # apps/cli/src/command-internal/pgdelta.unit.test.ts # apps/cli/src/command-internal/seed-ops.unit.test.ts # apps/cli/src/command-internal/seed.unit.test.ts # apps/cli/src/commands/db/diff/diff.integration.test.ts # apps/cli/src/commands/start/start.lifecycle.e2e.test.ts
# Conflicts: # apps/cli-go/pkg/config/templates/Dockerfile # apps/cli/src/commands/bootstrap/bootstrap.handler.ts # apps/cli/src/commands/bootstrap/bootstrap.templates.integration.test.ts # apps/cli/src/commands/db/advisors/advisors.format.ts # apps/cli/src/commands/db/advisors/advisors.integration.test.ts # apps/cli/src/commands/db/diff/diff.integration.test.ts # apps/cli/src/commands/db/dump/dump.handler.ts # apps/cli/src/commands/db/dump/dump.integration.test.ts # apps/cli/src/commands/db/lint/lint.format.ts # apps/cli/src/commands/db/lint/lint.integration.test.ts # apps/cli/src/commands/db/pull/pull.integration.test.ts # apps/cli/src/commands/db/push/push.integration.test.ts # apps/cli/src/commands/db/query/query.format.ts # apps/cli/src/commands/db/query/query.integration.test.ts # apps/cli/src/commands/db/reset/reset.integration.test.ts # apps/cli/src/commands/db/schema/declarative/generate/generate.integration.test.ts # apps/cli/src/commands/db/schema/declarative/sync/sync.integration.test.ts # apps/cli/src/commands/db/shared/pgdelta.seam.integration.test.ts # apps/cli/src/commands/db/start/start.integration.test.ts # apps/cli/src/commands/db/test/test.integration.test.ts # apps/cli/src/commands/experimental/stack/stack-forwarding.integration.test.ts # apps/cli/src/commands/init/init.integration.test.ts # apps/cli/src/commands/inspect/report/report.config.ts # apps/cli/src/commands/link/link.integration.test.ts # apps/cli/src/commands/migration/down/down.integration.test.ts # apps/cli/src/commands/migration/fetch/fetch.integration.test.ts # apps/cli/src/commands/migration/list/list.integration.test.ts # apps/cli/src/commands/migration/migration.integration.test.ts # apps/cli/src/commands/migration/new/new.integration.test.ts # apps/cli/src/commands/migration/repair/repair.integration.test.ts # apps/cli/src/commands/migration/squash/squash.diff.unit.test.ts # apps/cli/src/commands/migration/squash/squash.integration.test.ts # apps/cli/src/commands/seed/buckets/buckets.flags.unit.test.ts # apps/cli/src/commands/seed/buckets/buckets.integration.test.ts # apps/cli/src/commands/services/services.integration.test.ts # apps/cli/src/commands/start/start.gates.ts # apps/cli/src/commands/start/start.handler.ts # apps/cli/src/commands/start/start.integration.test.ts # apps/cli/src/commands/start/start.string-slice-flags.integration.test.ts # apps/cli/src/commands/status/status.command.unit.test.ts # apps/cli/src/commands/status/status.integration.test.ts # apps/cli/src/commands/status/status.string-slice-flags.integration.test.ts # apps/cli/src/commands/stop/stop.integration.test.ts # apps/cli/src/commands/test/new/new.integration.test.ts
# Conflicts: # apps/cli-go/pkg/config/templates/Dockerfile # apps/cli/src/commands/db/advisors/advisors.integration.test.ts # apps/cli/src/commands/db/diff/diff.command.ts # apps/cli/src/commands/db/diff/diff.integration.test.ts # apps/cli/src/commands/db/dump/dump.command.ts # apps/cli/src/commands/db/pull/pull.command.ts # apps/cli/src/commands/db/pull/pull.integration.test.ts # apps/cli/src/commands/db/push/push.command.ts # apps/cli/src/commands/db/push/push.integration.test.ts # apps/cli/src/commands/db/remote/commit/commit.command.ts # apps/cli/src/commands/db/reset/reset.command.ts # apps/cli/src/commands/db/reset/reset.integration.test.ts # apps/cli/src/commands/db/schema/declarative/generate/generate.command.ts # apps/cli/src/commands/db/schema/declarative/generate/generate.integration.test.ts # apps/cli/src/commands/db/schema/declarative/sync/sync.command.ts # apps/cli/src/commands/db/start/start.command.ts # apps/cli/src/commands/db/start/start.integration.test.ts # apps/cli/src/commands/db/test/test.integration.test.ts # apps/cli/src/commands/seed/buckets/buckets.integration.test.ts
# Conflicts: # .github/actions/setup/action.yml # .github/workflows/test.yml # apps/cli-go/pkg/config/templates/Dockerfile # apps/cli/docs/supabase/db/diff.md # apps/cli/docs/supabase/db/pull.md # apps/cli/src/command-internal/db-bootstrap/bootstrap-config.ts # apps/cli/src/command-internal/db-config.toml-read.ts # apps/cli/src/command-internal/db-pull-run.ts # apps/cli/src/command-internal/local-config-values.ts # apps/cli/src/command-internal/local-project-context.ts # apps/cli/src/command-internal/stack-config.ts # apps/cli/src/commands/bootstrap/SIDE_EFFECTS.md # apps/cli/src/commands/bootstrap/bootstrap.handler.ts # apps/cli/src/commands/db/diff/SIDE_EFFECTS.md # apps/cli/src/commands/db/diff/diff.handler.ts # apps/cli/src/commands/db/diff/diff.integration.test.ts # apps/cli/src/commands/db/dump/SIDE_EFFECTS.md # apps/cli/src/commands/db/dump/dump.handler.ts # apps/cli/src/commands/db/push/SIDE_EFFECTS.md # apps/cli/src/commands/db/push/push.handler.ts # apps/cli/src/commands/db/reset/reset.handler.ts # apps/cli/src/commands/db/schema/declarative/generate/generate.handler.ts # apps/cli/src/commands/experimental/stack/start/start.handler.ts # apps/cli/src/commands/gen/types/SIDE_EFFECTS.md # apps/cli/src/commands/gen/types/types.handler.ts # apps/cli/src/commands/migration/down/down.handler.ts # apps/cli/src/commands/services/SIDE_EFFECTS.md # apps/cli/src/commands/services/services-local-stack.ts # apps/cli/src/commands/services/services.handler.ts # apps/cli/src/commands/status/status.handler.ts # apps/cli/src/commands/status/status.integration.test.ts # packages/config/src/io.ts
next removed apps/cli-go, so the Go build, cache, and keyring steps synced from develop fail. Co-Authored-By: Claude Opus 5.5 <[email protected]>
next already removed the deprecated config, env vars and import maps that #7154 warns about, so its warnings, env alias and tests do not apply here. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Remove the pre-renumber Go CLI removal and config precedence ADRs and point config precedence references at ADR 0032. Co-Authored-By: Claude Opus 5.5 <[email protected]>
# Conflicts: # apps/cli/src/command-internal/test-db.integration.test.ts # apps/cli/src/commands/inspect/db/table-index-sizes/table-index-sizes.command.ts # apps/cli/src/commands/inspect/db/total-index-size/total-index-size.command.ts # apps/cli/src/commands/inspect/db/total-table-sizes/total-table-sizes.command.ts # apps/cli/src/commands/inspect/report/report.integration.test.ts # apps/cli/src/commands/migration/list/list.command.ts # apps/cli/src/commands/migration/repair/repair.command.ts # apps/cli/src/commands/migration/squash/squash.command.ts
This adds postgres 17.11.0.011-orioledb-r0 as a new release line. https://github.com/supabase/slim-services/releases/tag/postgres-17.11.0.011-orioledb-r0 Planned after supabase/slim-services published 15.19.0.011-r0. This branch is rewritten from develop whenever a newer relevant release arrives. Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…#7379) ## TL;DR `supabase db advisors --local` / `--db-url` now lints the schemas that `[api]` in `config.toml` exposes, instead of whatever `pgrst.db_schemas` value the connection happens to carry. ## What's fixed? Splinter decides which schemas to lint by reading `pgrst.db_schemas`. The CLI never set it, so: - When it was unset, splinter fell back to `public`, and tables without RLS in other exposed schemas were never reported. - After any transaction on a backend had set it locally, the backend read `''` from then on. A pooled connection could then make `db advisors` report "No issues found" even with unprotected `public` tables. ## How? - `readDbToml` resolves `exposedSchemas` from `[api].schemas` and `[api].enabled` (empty when the Data API is off), with the `SUPABASE_API_SCHEMAS` / `SUPABASE_API_ENABLED` overrides and `[remotes.*]` precedence that `supabase start` uses. `DbConfigResolver` passes it on the `--local` and `--db-url` paths. - `db advisors` runs `select set_config('pgrst.db_schemas', $1, true)` inside its existing rollback transaction, before the lint setup. A Data API that is off sets `''`, so nothing is reported as exposed. - The `db query` agent-mode RLS advisory binds the same schema list as `$1::text[]` instead of reading the setting, and is skipped when the Data API is off. - `--linked` is unchanged; the platform sets the value for hosted projects. Behavior change: a malformed `SUPABASE_API_ENABLED` now fails config loading for commands that resolve the local database config, matching how `SUPABASE_AUTH_ENABLED` and `supabase start` already treat it. ## ref: - CLI-2824
This PR was automatically created to sync API types from the infrastructure repository. Changes were detected after refreshing `apps/cli-go/api/v1-openapi.yaml` from the latest spec from infrastructure, and `apps/cli-go/pkg/api` is regenerated from it. The snapshot diff is the upstream API change and is worth reading: it is marked `linguist-generated`, so GitHub collapses it behind a "Load diff" click rather than hiding it. Co-authored-by: supabase-cli-releaser[bot] <246109035+supabase-cli-releaser[bot]@users.noreply.github.com>
# Conflicts: # apps/cli-go/api/v1-openapi.yaml # apps/cli-go/pkg/api/types.gen.go # apps/cli-go/pkg/config/templates/Dockerfile # apps/cli/src/command-internal/db-bootstrap/local-db-running.ts # apps/cli/src/command-internal/db-bootstrap/start-local-database.ts # apps/cli/src/command-internal/db-config.layer.ts # apps/cli/src/command-internal/db-config.toml-read.ts # apps/cli/src/commands/config/push/push.handler.ts # apps/cli/src/commands/db/advisors/SIDE_EFFECTS.md # apps/cli/src/commands/db/advisors/advisors.integration.test.ts # apps/cli/src/commands/db/query/SIDE_EFFECTS.md # apps/cli/src/commands/db/query/query.handler.ts # apps/cli/src/commands/db/query/query.integration.test.ts # apps/cli/src/commands/db/schema/declarative/generate/SIDE_EFFECTS.md # apps/cli/src/commands/db/schema/declarative/sync/SIDE_EFFECTS.md # apps/cli/src/commands/db/shared/pgdelta.seam.integration.test.ts # apps/cli/src/commands/db/start/SIDE_EFFECTS.md # apps/cli/src/commands/link/SIDE_EFFECTS.md # apps/cli/src/commands/start/SIDE_EFFECTS.md # apps/cli/tests/helpers/command-mocks.ts # packages/config/AGENTS.md # packages/config/README.md
## TL;DR
stops `supabase db reset` randomly failing at `Initialising schema...`
## whats hurting the user(s)?
`supabase db reset` fails at random with `error running container: exit
1`, mostly in CI
it recreated the db while realtime kept running, so docker restarted
realtime mid reset and its migrations collided with the reset's own on
`schema_migrations_pkey`
## now fixed by:
storage, auth, realtime and the pooler are stopped before the db is
removed and started once at the end,
even when the reset fails...
```mermaid
sequenceDiagram
participant R as db reset
participant S as storage, auth, realtime, pooler
participant D as docker
participant DB as db
participant J as init jobs
Note over R,J: before
R->>DB: remove and recreate
DB--xS: connection lost
D->>S: restart (unless-stopped)
par
S->>DB: realtime migrations
and
J->>DB: realtime migrations
end
DB-->>J: schema_migrations_pkey
J-->>R: exit 1, reset fails
Note over R,J: now
R->>S: stop
R->>DB: remove and recreate
J->>DB: init migrations
R->>DB: your migrations + seed
R->>S: start once, reload kong
Note over R,S: same restart on failure or ctrl-c
```
## ref:
- closes: #6915
- closes: #6445
Hosted mutations now refuse in a non-TTY run without --yes, so the live suite's remaining unconfirmed setup and cleanup calls failed with "Confirmation required". Pass --yes to db query (write statements), migration repair and postgres-config delete in the live tests and helpers.
## Summary
- `publish` lists `live-e2e-gate` in `needs`, and that gate only runs
for `stable`/`maintenance`, so it is skipped on `beta` and `next`.
`publish` still runs (`!cancelled()`), but `backfill-release-notes`,
`publish-homebrew` and `publish-scoop` have no status-check function in
their `if:`, so they get an implicit `success()` that is false when an
ancestor was skipped. Result: beta/next GitHub Releases have empty
bodies and Homebrew/Scoop `supabase-beta` stop updating. These three
conditions now start with `!cancelled()`, and brew/scoop also require
`needs.publish.result == 'success'`.
- `backfill-release-notes.yml` reads `inputs.non_blocking`, which is
only declared under `workflow_call`, so a manual `workflow_dispatch`
fails at startup. It now uses `${{ inputs.non_blocking || false }}`,
matching `propose-release-notes.yml`.
## Maintenance branches
This release-infrastructure change needs a cherry-pick to `v2.x` per
`apps/cli/docs/release-process.md`.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
| # A `/ai-review` comment on a pull request starts a review. The resolve job checks who | ||
| # commented, and the one job that can write to the pull request runs code from the default | ||
| # branch only, never from the pull request. | ||
| # jactionlint ignore=dangerous-triggers |
There was a problem hiding this comment.
⚪ Severity: LOW
Any GitHub user can comment exactly /ai-review; the new issue-comment trigger puts that run in the same workflow-level concurrency group as an authorized manual review. With cancel-in-progress, an outsider's run can cancel the active review before resolve checks permissions, suppressing the requested review without starting a replacement.
Helpful? Add 👍 / 👎
💡 Fix Suggestion
Suggestion: Stop untrusted /ai-review comments from sharing the review concurrency group with authorized runs. The fix belongs in the concurrency: block (around lines 42-48), not at line 22.
Option 1 (preferred): in the group expression, give any issue_comment run a unique group (github.run_id) unless the commenter is trusted. Check github.event.comment.author_association against OWNER, MEMBER and COLLABORATOR. Untrusted or non-matching comments then land in their own group and cannot cancel anything. For example, change the condition to:
(github.event_name == 'issue_comment' && (github.event.comment.body != '/ai-review' || !contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association))) && github.run_id || (github.event_name == 'pull_request' && 'auto' || 'review')
Option 2: only cancel in-progress runs when the trigger is trusted, for example cancel-in-progress: ${{ github.event_name != 'issue_comment' }}. This also stops an outsider's comment from cancelling an active review.
Keep the resolve job's permission check as the authoritative authorization gate.
This bumps realtime from v2.149.2-r0 to v2.150.0-r0. https://github.com/supabase/slim-services/releases/tag/realtime-v2.150.0-r0 Planned after supabase/slim-services published v2.150.0-r0. This branch is rewritten from develop whenever a newer relevant release arrives. Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This bumps realtime from v2.150.0-r0 to v2.150.1-r0. https://github.com/supabase/slim-services/releases/tag/realtime-v2.150.1-r0 Planned after supabase/slim-services published v2.150.1-r0. This branch is rewritten from develop whenever a newer relevant release arrives. Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Addresses #7339 ## Problem Between `start` creating a project's Docker network and attaching its first container, the network has no endpoints. Any project-label-filtered `docker network prune` that lands in that window removes it, and `start` then fails with `network supabase_network_<id> not found`. Within one invocation every prune runs before bring-up (stopped-stack recovery) or after it stops (rollback), so the prune in the report most likely came from an overlapping lifecycle command on the same project: an earlier `start` still rolling back, a `stop`, `stop --all`, or a `db start` rollback. ## Change - `start`, `db start` (including the declarative auto-start), and `stop` hold a cross-process lifecycle lock under `$SUPABASE_HOME/locks`: - a per-project lock keyed by the project's Docker label, so checkouts sharing a `project_id` serialize and different projects still run in parallel; - a gate every per-project command holds shared and `stop --all` holds exclusively. - The lock is taken before the first Docker probe and released after any rollback, outside the rollback region, so a waiting command never rolls back another command's resources. - A blocked command prints one waiting line to stderr and fails with an actionable error after 10 minutes; waiting is interruptible. - The lock replaces the per-project start lock from #7369, which it covers. - `@supabase/stack` gains `holdSharedLock` / `holdExclusiveLock` next to `holdLock`. - The `ensureNetwork` doc comment no longer claims the network cannot be removed mid-run. ## Limitations Older CLI binaries, raw `docker` commands, a different `SUPABASE_HOME`, and projects sharing a custom `--network-id` do not participate, and `stop --all` is not queued ahead of a stream of single-project commands (documented in `start`'s `SIDE_EFFECTS.md`). `db reset` and the shadow database still create their network without the lock; that is a separate follow-up. When `$SUPABASE_HOME/locks` cannot be created or a lock file there cannot be opened, these commands continue without the lock and log a debug line. --------- Co-authored-by: 7ttp <[email protected]>
This bumps postgres from 15.19.0.011-r0 to 15.19.0.013-r0. https://github.com/supabase/slim-services/releases/tag/postgres-15.19.0.013-r0 Planned after supabase/slim-services published 15.19.0.013-r0. This branch is rewritten from develop whenever a newer relevant release arrives. Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This adds postgres 17.11.0.013-orioledb-r0 as a new release line. https://github.com/supabase/slim-services/releases/tag/postgres-17.11.0.013-orioledb-r0 Planned after supabase/slim-services published 15.19.0.013-r0. This branch is rewritten from develop whenever a newer relevant release arrives. Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
## Summary The post-release smoke test installs the just-published CLI through `supabase/setup-cli` on ubuntu, macos, windows and Alpine, but only with setup-cli v1 and v2. setup-cli's current major is v3, and its README tells users to use `supabase/setup-cli@v3`, so the major we point people at had no coverage. This adds a `v3` leg to both matrices (the runner matrix and the Alpine job), pinned to `v3.0.1` (`45a513f8…`) the same way v1 and v2 are pinned. Job names keep the `setup-cli vN (runner)` shape. v3 still takes the same `version` input and strips a leading `v`, so the step is identical to the others. The difference is that v3 installs the `supabase` npm package instead of downloading GitHub Release assets, so the smoke test now also covers the npm install path. The `publish` job pushes to npm before the GitHub Release, so the version is already on npm when `setup-cli-smoke` runs. I updated the `version` input description and the two lines in `release-process.md` that describe this job to match. Release logic isn't touched. A dispatch of this workflow on this branch against `3.0.0-beta.14` is green for v1, v2 and v3 on every runner: https://github.com/supabase/cli/actions/runs/40960508203 ## Maintenance branch `v2.x` exists, and `setup-cli-smoke-test.yml` is on the release-infrastructure list in the [release process](https://github.com/supabase/cli/blob/develop/apps/cli/docs/release-process.md), so this needs a cherry-pick to `v2.x` through a `backport/*` PR.
This bumps storage from v1.84.36-r0 to v1.87.0-r0. https://github.com/supabase/slim-services/releases/tag/storage-v1.87.0-r0 Planned after supabase/slim-services published v1.87.0-r0. This branch is rewritten from develop whenever a newer relevant release arrives. Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…able_signup (#7398) ## Summary `enable_signup` under `[auth.email]` and `[auth.sms]` doesn't control signups. `config push` sends it as `external_email_enabled` / `external_phone_enabled`, which turns the whole provider on or off. So setting `[auth.email] enable_signup = false` to stop new signups also stops every existing user signing in with email (password, magic link or OTP), which is what #7055 ran into. The key that blocks new signups is `[auth] enable_signup`. This adds `enabled` as the new name for both keys and deprecates `enable_signup` in those two sections. The old key goes away in v4. - `[auth.email] enabled` and `[auth.sms] enabled` are new, including under `[remotes.<name>.auth.email]` and `[remotes.<name>.auth.sms]`. If a section sets both, `enabled` wins. - While a config still uses the old key, loading it prints a warning on stderr, e.g. `WARN: auth.email.enable_signup is deprecated and will be removed in v4, use auth.email.enabled instead.` - `config push` and `config diff` print a warning when a change turns the email or phone provider off, and point at `[auth] enable_signup` for blocking new signups only. Push prints it before its confirmation question. - `config pull` writes whichever key the file already uses, and `enabled` when it adds the key. - `supabase init` writes `enabled`. - The schema descriptions for these keys and for `[auth] enable_signup` now say what each one does. `enable_signup` stays the name in the decoded config, `ProjectConfig`, the API mapping and the `config diff` / `config pull` JSON `path` until v4, so nothing changes for `@supabase/config` consumers or JSON output. `config pull`'s `document_path` names the key it actually wrote. ### Not covered - `config diff` and `config push` still label the row `auth.email.enable_signup` even when the file uses `enabled`. Renaming the canonical path belongs with removing the old key (CLI-2892). ## Linked issue Closes #7055 (CLI-2658)
…LI-2864) (#7397) ## Summary Since #7366 the config, project-config and `supabase.lock` schemas have `$id`s under `https://supabase.com/schemas/`, but nothing serves them yet. supabase/supabase#52509 sets up `apps/www/public/schemas` in supabase/supabase, and this publishes to it from every stable release. - New `scripts/publish-schemas.ts` copies the newest version of each schema in `apps/docs/public/schemas` to `apps/www/public/schemas` on a `cli/schemas` branch in supabase/supabase. It only opens a PR (or reuses the open one) when a file changed, and arms auto-merge on it - Before pushing, it checks that each schema is a JSON object, declares draft-07, and has an `$id` matching the URL it'll be served from. Lower versions are never written, and it refuses to publish if supabase.com already serves a newer version or the `cli/schemas` branch changes anything else, so a published version can't be modified - `--dry-run` validates and prints what it would publish without touching supabase/supabase. Release dry runs pass it - The clone, branch, commit and PR steps move into `scripts/publish-pull-request.ts`, shared with `publish-docs-spec.ts`. The CLI reference publisher behaves the same as before - The release `docs` job is now "Publish to supabase.com" and runs both publishers, each without stopping the other. A failed publish adds an error annotation and a step summary line, turns the job red and posts to Slack (new `publish-failure` message). The release itself still succeeds Auto-merge still waits on a code-owner approval, since supabase/supabase `master` requires one and the releaser App can't approve its own PR. The schemas path is owned by `@supabase/cli`, so one of us approves and it merges itself. Making it fully hands-off would need the App added as a bypass actor on that ruleset. There's no `v*.x` branch at the minute, so no cherry-pick is needed. ## Linked issue Closes CLI-2864
…7396) ## Summary Adds two properties to every CLI analytics event, `cli_command_executed` included: - `is_eval` is `true` when `SUPABASE_EVAL` is `1` or `true` (case-insensitive), otherwise `false`. supabase/evals#416 already sets `SUPABASE_EVAL=1` on every CLI run in the evals harness, and this is the CLI side that reports it, so eval runs can be kept out of agent usage numbers. - `agent_name` is the detected agent (for example `claude`, `codex` or `cursor_cli`), sent only when `is_agent` is true. It reuses the `AiTool` detection that already drives `is_agent` and the `feedback add` metadata, so usage can be split by harness without decoding `env_signals`. Events from earlier CLI versions don't carry `is_eval`, so queries should treat a missing value as `false`. Both properties are documented in `apps/cli/docs/analytics.md`. ## Linked issue Closes CLI-2716
## TL;DR brings the `apps/cli-e2e` harness under the effect lint ## whats introduced? - `env.ts` reads the environment through `Config` and passes the record mode and staging url to the global setup instead of rewriting `process.env` - the global setup, staging project helpers, fixture loader, pg mock and vitest config run as effect programs - the fixture loader decodes fixtures through a schema, so a hand written fixture missing a field fails at load with its file name, and every committed fixture decodes unchanged - the replay server stays excluded until the last page of this stack ## ref - related: CLI-2878
## TL;DR brings the `apps/cli-e2e` test files and their fixtures under the effect lint ## whats introduced? - `run` and `runNoProjectId` return effects, every test body runs through one `runE2e` edge, and control calls go through one `postControl` helper instead of `fetch` - a test that asks for a runner but passes without running a CLI command now fails, since vitest would otherwise pass a body that returned an unrun effect - the same tests run with the same results ## ref - related: CLI-2879
…7387) ## TL;DR brings the `apps/cli-e2e` replay server under the effect lint, so the allow list covers the whole ## whats introduced? - the server runs on `FileSystem`, `HttpClient` and typed errors with `Bun.serve` as its only edge, and the global setup owns it through a scope - the docker relay uses the `node:http` client from `@effect/platform-node`, because bun's `fetch` sorts response headers and recorded fixtures keep them in arrival order - replay responses and recorded fixture files stay byte for byte the same ps: in record mode the docker relay can send a response chunked where it used to send `content-length`, with the same body bytes, and a failed relay logs its own error instead of the raw socket error ## ref - closes: CLI-2880
Two things have been turning develop's checks red.
1. The hourly API Package Sync has failed every run since 20 Oct. The
Management API spec now sets `contentEncoding: "binary"` on the ESZIP
upload body, and Effect's OpenAPI 3.0 converter rejects
`contentEncoding` and `contentMediaType` because they'd become active
keywords in Draft 2020-12. Both are only annotations and `format:
binary` already says the same thing, so `sanitizeOpenApiSchema` now
drops them. Once this lands, the next sync run should open the backlog
PR for `@supabase/api`.
2. CodeQL flags `js/incomplete-sanitization` in
`apps/cli/scripts/publish.ts`, because `name.replace("/", "%2F")` only
replaces the first slash. It shows up on every develop commit through
the production deploy PR. It's `replaceAll` now - no package name has
more than one slash, so there's no behaviour change.
`v2.x` has the same `publish.ts` line. With no behaviour change I don't
think it needs a backport, unless we want the alert cleared there too.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
This bumps realtime from v2.150.1-r0 to v2.150.2-r0. https://github.com/supabase/slim-services/releases/tag/realtime-v2.150.2-r0 Planned after supabase/slim-services published v2.150.2-r0. This branch is rewritten from develop whenever a newer relevant release arrives. Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…#7414) ## TL;DR brings the last excluded test files under the effect lint ## whats introduced? - the seven test files from the `--remote` and config values work and the `local-db-running` integration test drop their `node:` imports and `process.env` writes for `FileSystem`, `Path`, `Config` and `vi.stubEnv` - the target selection and hosted consent helpers type their error channels as `Error` instead of `unknown` - `goldenJson` becomes an effect, so its four callers yield it - the same tests run with the same results ## ref - related: CLI-2898
apps/cli/testswith effect lint (CLI-2852) (test(cli): coverapps/cli/testswith effect lint (CLI-2852) #7327)