feat(cli): add --project-ref flag to db commands - #6156
Conversation
Adds an optional --project-ref flag to the eight legacy db subcommands that resolve a project ref (push, pull, diff, dump, reset, lint, advisors, query), so e.g. `supabase db push --project-ref <ref>` targets that project without requiring a linked workdir. The flag follows the resolver's existing precedence (flag > SUPABASE_PROJECT_ID > supabase/.temp/project-ref) and errors when combined with a non-linked target instead of being silently ignored.
Supabase CLI previewnpx --yes https://pkg.pr.new/supabase/cli/supabase@a6ef7c65c445989ee8e7eefbde2743773b09249fPreview package for commit |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a6ef7c65c4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| connType, | ||
| dnsResolver, | ||
| password: flags.password ?? Option.none(), | ||
| linkedProjectRef: flags.projectRef, |
There was a problem hiding this comment.
Forward the project override to the delegated pull
When experimental structured-dump mode is enabled, this resolves and checks the connection for flags.projectRef, but delegatePull() later starts the bundled Go command through rebuildDelegateArgs(flags), which neither forwards this TS-only flag nor sets SUPABASE_PROJECT_ID in the child environment. The child therefore falls back to the workdir's linked ref and can pull schema from a different project than the one the parent just resolved; either pass the resolved ref through the environment or reject this flag/mode combination as db diff does.
AGENTS.md reference: apps/cli/AGENTS.md:L249-L255
Useful? React with 👍 / 👎.
| Option.isSome(flags.projectRef) && flags.projectRef.value.length > 0 | ||
| ? flags.projectRef | ||
| : Option.isSome(cliConfig.projectId) | ||
| ? cliConfig.projectId | ||
| : yield* legacyReadProjectRefFile(fs, path, cliConfig.workdir); | ||
| if (Option.isSome(refOpt)) { | ||
| linkedRefForCache = refOpt.value; |
There was a problem hiding this comment.
Validate the ref before scheduling its cache write
For a malformed nonempty --project-ref, this stores the raw value before resolver.resolve() validates and rejects it. Because the cache operation runs in an Effect.ensuring finalizer, a cache miss with credentials still issues an authenticated /v1/projects/<malformed-ref> request—and may write its response—even though ref resolution failed. Resolve and validate through LegacyProjectRefResolver.loadProjectRef() before assigning linkedRefForCache, as the other changed handlers do.
AGENTS.md reference: apps/cli/AGENTS.md:L96-L98
Useful? React with 👍 / 👎.
| * The eight `db` commands' `--project-ref` deliberately leave this unset: | ||
| * unlike `gen types --project-id`'s genuinely ad-hoc target, `db`'s | ||
| * `--project-ref` is meant to have identical workdir credential semantics to | ||
| * `SUPABASE_PROJECT_ID` — it may still reuse the ambient `SUPABASE_DB_PASSWORD` | ||
| * / `--password`, since forcing ad-hoc would silently break existing |
There was a problem hiding this comment.
Fetch the overridden project's pooler configuration
When --project-ref targets an unlinked project from an IPv4-only network, leaving adHocProjectRef false prevents legacyResolveLinkedConn() from fetching that project's primary pooler configuration: it only checks the workdir's saved .temp/pooler-url, which is absent or belongs to another project, and then fails with the IPv6/link suggestion. This breaks the newly tested “without a linked workdir” workflow for the common IPv6-only direct database host case across all eight commands. Decouple pooler selection from ambient-password handling so an explicit ref fetches its own pooler while retaining the intended password precedence.
Useful? React with 👍 / 👎.
| Option.isSome(flags.projectRef) && | ||
| legacyClassifyExplicitRef(from) !== "linked" && | ||
| legacyClassifyExplicitRef(to) !== "linked" |
There was a problem hiding this comment.
Honor --linked in the explicit-mode project-ref guard
For db diff --from local --to migrations --linked --project-ref <ref>, this condition rejects the invocation even though the error explicitly says to use --project-ref with --linked. The subsequent preflight is designed to resolve that linked ref and merge its [remotes.<ref>] configuration into explicit local/migrations references, so the flag is not unused in this scenario. Exclude an explicitly changed --linked target from this guard, in addition to the existing from/to linked exceptions.
AGENTS.md reference: apps/cli/AGENTS.md:L249-L255
Useful? React with 👍 / 👎.
Summary
A Front support ticket surfaced that we tell users
db push --project-ref <ref>works, but the legacy TS shell never accepted the flag. In the Go CLI the linked-ref override was only reachable on db commands via theSUPABASE_PROJECT_IDenv var (Go never registered--project-refon them); the Effect CLI is explicit about which commands take which flags, and thedbfamily was missed when groups likessogot it.This adds an optional
--project-refflag ("Project ref of the Supabase project.") to the eight db subcommands that resolve a project ref: push, pull, diff, dump, reset, lint, advisors, query.Behavior:
LegacyProjectRefResolver.loadProjectRef, keeping the resolver's existing precedence: flag >SUPABASE_PROJECT_ID>supabase/.temp/project-ref. With the flag unset, behavior is unchanged.loadProjectRefcalls, the sharedLegacyDbConfigResolver'slinkedProjectRef, the pooler-fallback path, and dump's pre-connect cache capture), so the connection, the[remotes.<ref>]config merge, the linked-project cache, and Management API paths can never disagree on the ref within one invocation.--linked. Instead of silently ignoring the flag on a non-linked target (a footgun ondb reset), the command errors:--project-ref only applies when targeting the linked project; use it with --linked (not --local or --db-url).db diffkeeps its explicit-mode exception (--from/--to linked) and rejects the flag with the Go-delegating--use-pgadmin/--use-pg-schemaengines rather than dropping it.markFlagTelemetrySafebaseline exists for db commands; the nearest Go registration,cmd/pgdelta_catalog.go, is unmarked).adHocProjectRefdeliberately stays unset so credential semantics match the env-var path (documented inlegacy-db-config.types.ts).Docs updated:
go-cli-porting-status.md(extra-TS-flag notes + missingdb advisors/db queryrows) and the eight commands'SIDE_EFFECTS.md.Follow-up (not in this PR): the
migrationfamily (up/down/list/repair/fetch),seed buckets, andstorage ls/cp/mv/rmshare the same linked-ref chain and still only support the env var/link file.Linked issue
No GitHub issue — raised via a Front support ticket (Supabase maintainer).
🤖 Generated with Claude Code