Skip to content

fix(cli): provision platform baseline in declarative baseline catalog#5521

Merged
jgoux merged 4 commits into
developfrom
claude/cli-1601-baseline-catalog-parity
Jun 9, 2026
Merged

fix(cli): provision platform baseline in declarative baseline catalog#5521
jgoux merged 4 commits into
developfrom
claude/cli-1601-baseline-catalog-parity

Conversation

@avallete

@avallete avallete commented Jun 9, 2026

Copy link
Copy Markdown
Member

Refs CLI-1601 — https://linear.app/supabase/issue/CLI-1601/support-auth-dependencies-in-shadow-db-migrations

Follow-up to #5515. That PR taught the declarative apply path to provision the Supabase platform baseline (auth/storage/realtime) on the shadow before applying declarative schemas. This fixes a gap it left in the generatesync-with-no-migrations handoff.

The bug

getGenerateBaselineCatalogRef exports .temp/pgdelta/catalog-baseline-<version>.json immediately after creating the shadow — before any platform setup runs — so the cached baseline represents a bare postgres image.

That same file is reused by getMigrationsCatalogRef as the diff source when there are zero local migrations. After #5515, the declarative target is built on top of the platform baseline. So a no-migration sync diffs:

  • source: bare postgres image
  • target: platform baseline + declarative schema

instead of the intended:

  • source: platform baseline
  • target: platform baseline + declarative schema

Platform-managed objects (auth, storage, realtime, grants, functions, …) no longer cancel and surface as spurious additions in the generated migration — e.g. a single declarative public.profiles table referencing auth.users produces a migration that also tries to create the auth/storage/realtime platform objects.

The fix

Provision the platform baseline in getGenerateBaselineCatalogRef before exporting, so the baseline catalog consistently means "platform baseline, no user migrations" — identical to diff.MigrateShadowDatabase with zero migrations, and in parity with the declarative target. The now-redundant second setupShadowDatabase call in Generate's cache-warm path is removed since the reused shadow already has the baseline (it was previously provisioning the platform twice).

This also fixes a latent generate issue: with a bare baseline, generate would have emitted platform schemas into the user's declarative files.

Tests

  • TestGetGenerateBaselineCatalogRefSetsUpPlatformBaseline — pins the setup-before-export ordering.
  • TestGenerateThenSyncWithNoMigrationsCancelsPlatformObjects — full generate → no-migration sync flow through the public command functions, asserting only the user's table is generated and platform objects cancel. Docker/pg-delta seams are stubbed (the established cli-go pattern), so it runs in the standard go test ./... CI job. diff.DiffPgDeltaRef is now an injectable package var to allow diffing through the public path without the real pg-delta runtime.

https://claude.ai/code/session_01ACrX8NXcsYLENnCRXAub3S


Generated by Claude Code

claude added 2 commits June 9, 2026 10:42
The baseline catalog (catalog-baseline-<version>.json) was exported from a
bare shadow database before any platform setup ran. That same catalog is
reused by getMigrationsCatalogRef as the diff source when there are zero
local migrations. After the declarative target started provisioning the
Supabase platform baseline (auth/storage/realtime), the no-migrations sync
diffed an empty-image source against a platform-baseline + declarative
target, so platform-managed objects surfaced as spurious additions/drops in
generated migrations.

Provision the platform baseline in getGenerateBaselineCatalogRef before
exporting, so the baseline catalog consistently represents "platform
baseline, no user migrations" — identical to MigrateShadowDatabase with zero
migrations and in parity with the declarative target. The now-redundant
second setup call in Generate's cache-warm path is removed since the reused
shadow already has the baseline.

RED before fix:
  expected: []string{"setup", "export"}
  actual  : []string{"export"}
Add a full-flow test driving Generate -> DiffDeclarativeToMigrations with no
local migrations through the public command functions. It models pg-delta
catalog content by shadow setup/apply state and stubs the Docker/pg-delta
seams (the established cli-go pattern), so it runs in the standard
`go test ./...` CI job.

The test pins the regression fixed in the previous commit: generate must
write the baseline catalog from the platform baseline, and a no-migration
sync must reuse it as the diff source so platform-managed objects
(auth/storage/realtime) cancel out instead of leaking into the generated
migration.

To diff through the public path without the real pg-delta runtime,
diff.DiffPgDeltaRef is now an injectable package var (diffPgDeltaRef),
matching the existing exportCatalog / declarativeExportRef / applyDeclarative
seams.

RED (pre-fix wiring) — generated migration leaked platform objects:
  "create auth;\ncreate public.profiles;\ncreate realtime;\ncreate storage;\n"
  should not contain "create auth;"
GREEN (with fix) — only "create public.profiles;" is generated.
@avallete avallete requested a review from a team as a code owner June 9, 2026 10:47
@coveralls

coveralls commented Jun 9, 2026

Copy link
Copy Markdown

Coverage Report for CI Build 27204703528

Coverage increased (+0.3%) to 64.618%

Details

  • Coverage increased (+0.3%) from the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • 152 coverage regressions across 2 files.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

152 previously-covered lines in 2 files lost coverage.

File Lines Losing Coverage Coverage
internal/db/declarative/declarative.go 147 55.18%
internal/utils/git.go 5 53.33%

Coverage Stats

Coverage Status
Relevant Lines: 16254
Covered Lines: 10503
Line Coverage: 64.62%
Coverage Strength: 7.11 hits per line

💛 - Coveralls

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9f63a3c80f

ℹ️ 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".

Comment thread apps/cli-go/internal/db/declarative/declarative.go
Comment thread apps/cli-go/internal/db/declarative/declarative.go
Comment thread apps/cli-go/internal/db/declarative/declarative.go
@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Supabase CLI preview

npx --yes https://pkg.pr.new/supabase@5521

Preview package for commit d264376.

The platform baseline catalog is produced by SetupDatabase (initSchema +
ApplyApiPrivileges + vault secrets + supabase/roles.sql), so its contents
are a function of the Postgres image AND the project inputs setup consumes —
not the image alone. The cache key was still only the image version token,
which meant:

- A bare baseline written by a pre-fix CLI (keyed by the same token) was
  reused as the no-migration sync source, re-leaking platform objects until
  .temp/pgdelta was cleared.
- Changing auto_expose_new_tables, vault secrets, or roles.sql after a
  generate left sync reusing a baseline built from the old config.

Key the baseline catalog by a hash of the image token plus those setup
inputs (baselineCatalogKey), resolved through a single baselineCatalogPath
helper used by both the generate writer and the no-migration sync reader.
Old bare-baseline filenames no longer match, so they are never reused, and
config/roles changes self-invalidate the cache.

Addresses Codex review feedback on #5521.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3dfa1ca491

ℹ️ 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".

Comment thread apps/cli-go/internal/db/declarative/declarative.go
Comment thread apps/cli-go/internal/db/declarative/declarative.go Outdated
Comment thread apps/cli-go/internal/db/declarative/declarative.go Outdated
The previous commit keyed only the baseline catalog by setup inputs, which
left its sibling caches inconsistent and able to pair a freshly keyed source
with a stale snapshot from a different platform setup:

- baselineCatalogKey ignored the auth/storage/realtime service toggles that
  gate initSchema, so toggling a service on the same image reused a stale
  baseline.
- The zero-migration branch of getMigrationsCatalogRef fell through to the
  migrations-hash cache (pgcache), which is not setup-aware, so an old
  empty-migrations snapshot could be reused as the no-migration sync source.
- The warmed declarative target catalog was keyed only by the declarative
  SQL hash, so a setup change with unchanged SQL paired a fresh source
  baseline with a stale target.

Introduce a single setupInputsToken (image + service toggles + api +
vault + roles.sql) and thread it through all three caches: the baseline
key, a new declarativeCatalogCacheKey for the warmed target, and the
zero-migration path now reads/writes the setup-keyed baseline instead of
the migrations-hash cache. Every catalog in the flow is "platform baseline +
{nothing | migrations | declarative}", so each cache now self-invalidates on
setup changes.

Addresses follow-up Codex review feedback on #5521.
@jgoux jgoux merged commit 82e6d06 into develop Jun 9, 2026
28 checks passed
@jgoux jgoux deleted the claude/cli-1601-baseline-catalog-parity branch June 9, 2026 12:35
mxcl pushed a commit to automic-vault/supabase-cli that referenced this pull request Jun 11, 2026
…supabase#5521)

Refs CLI-1601 —
https://linear.app/supabase/issue/CLI-1601/support-auth-dependencies-in-shadow-db-migrations

Follow-up to supabase#5515. That PR taught the declarative apply path to
provision the Supabase platform baseline (auth/storage/realtime) on the
shadow before applying declarative schemas. This fixes a gap it left in
the `generate` → `sync`-with-no-migrations handoff.

## The bug

`getGenerateBaselineCatalogRef` exports
`.temp/pgdelta/catalog-baseline-<version>.json` immediately after
creating the shadow — **before** any platform setup runs — so the cached
baseline represents a bare postgres image.

That same file is reused by `getMigrationsCatalogRef` as the diff
**source** when there are zero local migrations. After supabase#5515, the
declarative **target** is built on top of the platform baseline. So a
no-migration `sync` diffs:

- source: bare postgres image
- target: platform baseline + declarative schema

instead of the intended:

- source: platform baseline
- target: platform baseline + declarative schema

Platform-managed objects (`auth`, `storage`, `realtime`, grants,
functions, …) no longer cancel and surface as spurious additions in the
generated migration — e.g. a single declarative `public.profiles` table
referencing `auth.users` produces a migration that also tries to create
the `auth`/`storage`/`realtime` platform objects.

## The fix

Provision the platform baseline in `getGenerateBaselineCatalogRef`
**before** exporting, so the baseline catalog consistently means
"platform baseline, no user migrations" — identical to
`diff.MigrateShadowDatabase` with zero migrations, and in parity with
the declarative target. The now-redundant second `setupShadowDatabase`
call in `Generate`'s cache-warm path is removed since the reused shadow
already has the baseline (it was previously provisioning the platform
twice).

This also fixes a latent `generate` issue: with a bare baseline,
`generate` would have emitted platform schemas into the user's
declarative files.

## Tests

- `TestGetGenerateBaselineCatalogRefSetsUpPlatformBaseline` — pins the
setup-before-export ordering.
- `TestGenerateThenSyncWithNoMigrationsCancelsPlatformObjects` — full
generate → no-migration sync flow through the public command functions,
asserting only the user's table is generated and platform objects
cancel. Docker/pg-delta seams are stubbed (the established cli-go
pattern), so it runs in the standard `go test ./...` CI job.
`diff.DiffPgDeltaRef` is now an injectable package var to allow diffing
through the public path without the real pg-delta runtime.

https://claude.ai/code/session_01ACrX8NXcsYLENnCRXAub3S

---
_Generated by [Claude
Code](https://claude.ai/code/session_01ACrX8NXcsYLENnCRXAub3S)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants