perf(cli): reuse shadow baseline cache in migration squash and pgadmin diff - #6220
Conversation
## Summary - settle chained managed identity recovery from the latest discovery state - keep branch-scoped transitions isolated while preserving conflict evidence - preserve marker, Git config, and service error semantics across recovery races ## Context This follows PR #6202 and Linear CLI-2108. It addresses confirmed pre-wiring edge cases around interrupted branch recovery, rename-plus-move settlement, folder-to-Git marker reporting, duplicated Git config values, and service shutdown races. Automatic recovery remains internal and bounded. Explicit recovery operations and fail-closed ambiguity behavior are unchanged.
## TL;DR fixes `supabase test db` reporting success on a run that executed zero tests, which was caused by passing `pg_prove`'s exit code straight through when it prints `Result: NOTESTS` and still exits 0 and is now fixed by watching the TAP summary for that verdict and failing with a msg naming the paths that were searched. A typo'd path, an empty tests directory, and a bind mount the Docker daemon resolved against a different filesystem than the CLI all hit this, so CI could stay green while testing nothing. The TAP stream on stdout is unchanged, the diagnostic goes to stderr, and the new exit 1 is recorded in the Go divergence because Go exits 0 here... ## ref: - closes: #6206
## TL;DR In text mode the CLI wrote to stdout with `process.stdout.write` and ignored its return value, so it never waited for a slow reader. Piping a large payload into a slower consumer made Node queue the whole thing in memory, which `supabase db dump` can turn into an OOM on a big database. Writing through the `Stdio` sink is better than hand-checking that return value because the sink already waits for `drain` and handles stream errors, the json and stream-json layers were always doing exactly that, and the old Go CLI had the same behaviour from blocking `os.Stdout` syscall. Text mode was the only outlier, so this removes the inconsistency instead of adding another special case, and all three layers now share one writer. Output bytes and ordering are unchanged.... ## ref: - spotted in: #6210
## Summary - centralize workspace metadata derivation and first-start settlement policy in focused pure modules - remove the obsolete Promise path canonicalizer and share the Git lock retry schedule - strengthen deterministic recovery-race coverage, close a SQLite test handle leak, and correct architecture documentation This is a maintainability follow-up to #6214. It deliberately keeps the broader `packages/stack` decomposition out of scope so that work can be designed separately.
…n diff The two remaining shadow-database consumers still provisioned bare, uncached shadows. Both now acquire through `legacyWithShadowDatabase` (`shadow-cache.ts`), the same seam `db diff`'s native branch and `db pull`'s migration path already use, so a key-matching PGDATA snapshot is restored in a few seconds instead of cold-provisioning the platform baseline every run. `migration squash` keeps its dump/apply/dump sequence intact by resuming at the baseline seam: `legacyOpenShadowBaselineSession` — Go's `SetupShadowDatabase`/`MigrateShadowDatabase` shared prologue, extracted from `shadow-database.ts` so all three compositions share one implementation — hands back the still-open session, and squash's before-dump / apply-migrations / after-dump / full-dump steps are unchanged. Unlike diff/pull it passes no `webhooks` override, matching its long-standing config-following `SetupDatabase` call, so it keys to its own snapshots. `db diff --use-pgadmin` becomes structurally identical to the native branch: same cached acquire, same forced-on `webhooks: "enabled"` policy (so it shares the native branch's tars), with `legacyMigrateShadowDatabase` now told whether the cluster already carries the baseline. A warm shadow skips `SetupDatabase`, so `Initialising schema...` / `Seeding globals from roles.sql...` no longer print and the PG15+ one-shot migrate jobs do not run — progress text reflects the work actually performed. Everything else, including the dumped artifacts and the differ output, is unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Supabase CLI previewnpx --yes https://pkg.pr.new/supabase/cli/supabase@d6289e62c2e0685e53de5dd402153eabec34242cPreview package for commit |
💡 Codex ReviewWhen AGENTS.md reference: apps/cli/AGENTS.md:L524-L526 cli/apps/cli/src/legacy/shared/db-bootstrap/health-check.ts Lines 585 to 588 in d6289e6 When the published port blackholes TCP connections rather than refusing them, each probe can consume its full 2-second connect timeout, while this schedule still permits AGENTS.md reference: apps/cli/AGENTS.md:L53-L56 When When another live test runs later in the same Vitest worker, this direct ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
Summary
Stacked on #6215 (← #6203 ← #6184 ← #6102).
migration squashanddb diff --use-pgadminwere the last two shadow-database consumers still provisioning bare cold shadows — every run re-paid the full platform baseline (init schema + the PG15+ realtime/storage/auth one-shot migrate jobs, ~15s) that the shadow-baseline cache already eliminates fordb diff/db pull. Both now provision throughlegacyWithShadowDatabaseand warm-restore the cached pg_data tar when eligible.The shared prologue (connect → prelude →
legacySetupDatabase, with the warm/cold/cold-snapshotting branches) is extracted intolegacyOpenShadowBaselineSessioninshadow-database.ts;legacySetupShadowDatabaseand the migrate path delegate to it, and squash calls it directly so its pre-migration auth/storage dumps stay exactly at the baseline seam. Squash keys config-following (its baseline always followedconfig.toml); pgadmin keyswebhooks: "enabled"to share the legacy migra branch's forced-pg_nettars.Two defects surfaced while wiring this in, both fixed here:
db pullanddb diff's native branch hardcoded{ webhooks: "enabled" }as the cache-key opts even in pg-delta next mode, where the actual provisioning (legacyMigrateNextShadowDatabase) followsconfig.toml. On a project with webhooks disabled, a cold next-mode run published apg_net-less tar under the "enabled" key — which the newly cached pgadmin branch (and the reverse direction) could then silently warm-restore. The key opts now follow the migration mode at all call sites;legacyResolveMigrationsCatalogRefinlegacy-pgdelta.cache.tshad the same drift (keyed config-following, provisioned forced-on) and is fixed too. A regression test asserts a next-mode diff and a pgadmin diff on a webhooks-disabled config never share tars (verified failing pre-fix).legacyWaitForHealthyServices(Docker HEALTHCHECK, first probe at t+10s, ~6.5s pure wait) instead of thelegacyWaitForShadowReadyconnect probe every other cached consumer uses. Swapped, so the warm restore actually lands its win. The now-deadneverHealthymock knob is deleted; the interrupt/timeout tests model a connect-refusing shadow instead.Test-helper cleanups ride along: a shared
withLegacyShadowCacheEnabledintests/helpers/legacy-mocks.tsreplaces per-file env stash/restore copies, and the squash test useslegacyShadowBaselineCacheDirinstead of a hand-built path.Transcript note: on a warm hit both commands skip the
Initialising schema.../Seeding globals from roles.sql...lines, matching the existing warm behavior ofdb diff/db pull. All dumps, migration-replay lines, and result output are unchanged.Linked issue
Closes #
open-for-contributionlabel (or I'm a Supabase maintainer).Checklist
fix(cli): …).pnpm check:allandpnpm testpass for the workspace(s) I touched.🤖 Generated with Claude Code