You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(cli): skip pg_dump in db pull when using pg-delta diff engine (#5255)
## What
Switches `supabase db pull --diff-engine pg-delta` to drive its initial
pull from pg-delta's catalog diff instead of `pg_dump`, and lands the
supporting plumbing (remote TLS handling, debug bundles, and a local
pg-delta dev workflow) needed to make that path reliable against Cloud.
Closes CLI-1472.
## Why
The legacy initial-pull pipeline is `pg_dump` → restore into a local
shadow → diff. That round-trip silently destroys ownership for any
object the local `postgres` role can't assume: `pg_dump` emits `ALTER
... OWNER TO supabase_admin` (etc.), the restore runs as a non-superuser
so the owner is dropped, and every restored object then reports `owner =
postgres`. pg-delta's supabase integration filter drops platform-managed
objects by `owner ∈ SUPABASE_SYSTEM_ROLES`, so once the owner signal is
gone those objects leak into the user's migration file and break
`supabase db reset` (CLI-1469 FDW ACLs, CLI-1470 Wasm wrappers).
pg-delta already speaks `pg_catalog` directly via `extractCatalog`,
preserving ownership, so diffing the remote catalog against an empty
shadow produces a clean initial migration without `pg_dump` in the loop.
## What changed
### Initial-pull routing
- `db pull` no longer runs `dumpRemoteSchema` on the initial pull when
the pg-delta diff engine is selected; the shadow diff is the sole
producer of the migration file (`internal/db/pull/pull.go`,
`cmd/db.go`).
- `shouldUseDeclarativePgDeltaPull` makes explicit `--diff-engine
pg-delta` keep the migration-file workflow even when
`[experimental.pgdelta] enabled = true` would otherwise default to the
declarative export path.
- New `swallowInitialInSync` / `ensureMigrationWritten` helpers
distinguish "pg-delta produced no statements" from "pg_dump already
wrote content", so an empty pg-delta result still surfaces `No schema
changes found` correctly.
### Diff plumbing
- `DiffDatabase` now returns a `DatabaseDiff` struct (`SQL` plus an
optional debug capture) rather than a bare string; callers in `diff.go`
and `pull.go` updated accordingly.
- Removed the now-unused `diffWithStream` and its golangci exclusion.
- The diff template (`templates/pgdelta.ts`) sets
`skipDefaultPrivilegeSubtraction: true` and emits structured diagnostics
under `PGDELTA_DEBUG`.
### Remote TLS handling for pg-delta
- New `internal/gen/types/pgdelta_conn.go`: `PreparePgDeltaPostgresRef`
writes the CA bundle into the workspace, forces `sslmode=verify-ca` +
`sslrootcert`, and always uses the embedded bundle for Supabase-hosted
hosts even when the SSL probe is skipped (e.g. `--debug`). Source/target
now use distinct `PGDELTA_SOURCE_SSLROOTCERT` /
`PGDELTA_TARGET_SSLROOTCERT` env vars. `pgdelta.go` and
`pgcache/cache.go` refactored onto this helper.
### Debug bundles for empty pulls
- New `PGDELTA_DEBUG` flag (separate from `--debug`; keeps SSL on). When
a pg-delta pull returns zero statements, the CLI writes a bundle under
`supabase/.temp/pgdelta/debug/<timestamp>/`: `source-catalog.json`,
`target-catalog.json`, `pgdelta-stderr.txt`, `connection.txt`
(redacted), and `error.txt`, plus a per-schema catalog object summary to
stderr (`internal/db/diff/pgdelta_debug.go`,
`internal/db/pull/pgdelta_pull_debug.go`).
- `DiffPgDeltaRefDetailed` surfaces edge-runtime stderr;
`declarative.DebugBundle` gains inline-catalog, stderr, and
connection-info fields.
### Local pg-delta dev workflow
- `PGDELTA_NPM_REGISTRY` (`pkg/config/pgdelta_local.go`,
`internal/utils/pgdelta_local.go`) routes Deno's
`npm:@supabase/pg-delta` resolution through a local Verdaccio registry.
The edge-runtime helper gained composable `WithExtraFile` /
`WithExtraEnv` options to drop a scoped `.npmrc` and forward
`NPM_CONFIG_REGISTRY`; all pg-delta edge-runtime calls now pass
`PgDeltaNpmRegistryOption()`. Documented in `CONTRIBUTING.md`.
### Version, build, and docs
- `DefaultPgDeltaNpmVersion` bumped to `1.0.0-alpha.27`.
- `apps/cli/package.json` adds a `build:go-sidecar` step that copies the
Go binary into `dist/`.
- `docs/supabase/db/pull.md` documents the new initial-pull behavior,
the experimental declarative default, the direct-connection
recommendation for `--db-url`, and the `PGDELTA_DEBUG` workflow.
## Reviewer notes
- The FDW/server ACL and `CREATE FOREIGN DATA WRAPPER` suppression rules
in `@supabase/pg-delta` become defense-in-depth on this path rather than
load-bearing.
- Scope is schema-only / migration generation: `supabase db dump` and
the declarative export path still use `pg_dump` / the existing flows.
https://claude.ai/code/session_016o7U7hiut6dkkhfbSJgKv4
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Julien Goux <hi@jgoux.dev>
Copy file name to clipboardExpand all lines: apps/cli-go/CONTRIBUTING.md
+49Lines changed: 49 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -41,3 +41,52 @@ go test ./... -race -v -count=1 -failfast
41
41
## API client
42
42
43
43
The Supabase API client is generated from OpenAPI spec. See [our guide](api/README.md) for updating the client and types.
44
+
45
+
## Testing local pg-delta builds
46
+
47
+
To exercise unpublished `@supabase/pg-delta` changes inside CLI edge-runtime scripts (`db pull`, `db diff`, `db push`, etc.), publish a local build via Verdaccio in [pg-toolbelt](https://github.com/supabase/pg-toolbelt) and point the CLI at that registry.
48
+
49
+
### 1. Start Verdaccio (pg-toolbelt)
50
+
51
+
```sh
52
+
cd pg-toolbelt
53
+
bun run verdaccio:start
54
+
```
55
+
56
+
Verdaccio listens on `http://localhost:4873`. `@supabase/*` packages you publish locally are served from local storage; other `@supabase/*` dependencies (for example `@supabase/pg-topo`) are proxied to npmjs.
This publishes a fresh `0.0.0-local.<timestamp>` version and restores `package.json` afterward. The version file tells the CLI which npm version to request (`EffectivePgDeltaNpmVersion`).
68
+
69
+
Re-run whenever you change pg-delta source.
70
+
71
+
### 3. Run the CLI against the local registry
72
+
73
+
Set `PGDELTA_NPM_REGISTRY` to a URL reachable **from inside the edge-runtime Docker container**:
Then run any pg-delta-backed command, for example:
85
+
86
+
```sh
87
+
supabase db pull --db-url "$DATABASE_URL" --diff-engine pg-delta
88
+
```
89
+
90
+
When set, the CLI injects a scoped `.npmrc` and forwards `NPM_CONFIG_REGISTRY` into the edge-runtime container (`PgDeltaNpmRegistryOption` in `internal/utils/pgdelta_local.go`).
91
+
92
+
Unset `PGDELTA_NPM_REGISTRY` to return to the npmjs version pinned in config / `supabase/.temp/pgdelta-version`.
Copy file name to clipboardExpand all lines: apps/cli-go/docs/supabase/db/pull.md
+26-2Lines changed: 26 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,6 +8,30 @@ Requires your local project to be linked to a remote database by running `supaba
8
8
9
9
Optionally, a new row can be inserted into the migration history table to reflect the current state of the remote database.
10
10
11
-
If no entries exist in the migration history table, `pg_dump` will be used to capture all contents of the remote schemas you have created. Otherwise, this command will only diff schema changes against the remote database, similar to running `db diff --linked`.
11
+
If no entries exist in the migration history table, the default diff engine uses `pg_dump` to capture all contents of the remote schemas you have created. Otherwise, this command will only diff schema changes against the remote database, similar to running `db diff --linked`.
12
12
13
-
Pass `--diff-engine pg-delta` to keep the migration-file `db pull` workflow while using pg-delta for the shadow diff step. Pass `--use-pg-delta` to switch to the declarative pg-delta export workflow instead.
13
+
Pass `--diff-engine pg-delta` to keep the migration-file `db pull` workflow while using pg-delta for the shadow diff step. On initial pull, pg-delta replaces `pg_dump` and produces the full migration from the shadow diff alone. Pass `--use-pg-delta` to switch to the declarative pg-delta export workflow instead.
14
+
15
+
When `[experimental.pgdelta] enabled = true` is set in `config.toml`, `db pull` defaults to the declarative export path. Explicit `--diff-engine pg-delta` still selects the migration-file workflow.
16
+
17
+
When pulling from a remote database with `--db-url`, prefer a direct connection (`db.<project-ref>.supabase.co:5432`) over the connection pooler so pg-delta can introspect the full catalog reliably.
18
+
19
+
## Debugging empty pg-delta pulls
20
+
21
+
If `db pull --diff-engine pg-delta` reports `No schema changes found` but you expect schema output, set `PGDELTA_DEBUG=1` before running the command. Unlike `--debug`, this keeps SSL enabled for remote Supabase connections.
22
+
23
+
```sh
24
+
PGDELTA_DEBUG=1 supabase db pull --db-url "$DATABASE_URL" --diff-engine pg-delta
25
+
```
26
+
27
+
When pg-delta returns zero statements, the CLI writes a debug bundle under `supabase/.temp/pgdelta/debug/<timestamp>/`:
Catalog files are not written during normal `db pull` runs. The `.temp/pgdelta` directory is also used by migration catalog caching (`db push`, local `db start`) when `[experimental.pgdelta] enabled = true`.
36
+
37
+
For TLS tracing without disabling SSL, use `SUPABASE_SSL_DEBUG=true` alongside `PGDELTA_DEBUG=1`.
0 commit comments