feat(tooling): local Postgres container and db:provision without supabase start

Merged
WC
14h ago
+532-0

Summary

A database-only local Postgres that does not need supabase start or the Supabase CLI:

  • bun run db:up starts one Postgres container for this worktree (supabase/local-db.compose.yml). It uses the same supabase/postgres:17.6.1.143 image supabase start runs, so every extension the baseline migration creates (pg_net, pgmq, supabase_vault, pg_cron, pg_tle, index_advisor, ...) is really there. No migration is edited and no extension is skipped. Port 54328 + worktree offset (unused by config.toml), compose project capgo-db-<worktree hash>.
  • bun run db:provision runs psql inside the container:
    1. supabase/bootstrap.sql as supabase_admin: only what GoTrue and storage-api would add on top of the image (GoTrue columns on auth.users, auth.mfa_factors and its enums, auth.uid/role/email/jwt() in GoTrue's claim order, storage.buckets/objects and the path helpers). Idempotent.
    2. Pending migrations in filename order, each in its own transaction together with its row in supabase_migrations.schema_migrations (the table the Supabase CLI uses). One psql session for all of them; DISCARD ALL between migrations so a session-level SET statement_timeout in one migration does not leak into the next.
    3. seed.sql once, recorded in supabase_migrations.seed_files.
      Re-running is a no-op.
  • bun run db:url, bun run db:down.
  • New CI job Provision local Postgres (no Supabase stack): db:up, db:provision, then db:provision again.

supabase start and all supabase:* scripts are unchanged. The two are separate databases: the Supabase CLI cannot point its stack at an external Postgres, so the app and the vitest integration suites still use supabase start. This path is for work that only needs the database (pgTAP and pure-SQL tests next, checking that a migration applies).

Test plan

  • Unit tests: bunx vitest run tests/local-db.unit.test.ts (migration ordering and name validation, pending selection, script shape, history parsing, seed hash, port band)
  • On the pinned image, locally: bootstrap.sql applied twice without error, then all 205 migrations, then seed.sql (17 auth users, 11 apps, 4 vault secrets, 3 buckets, 34 pgmq queues)
  • CI job Provision local Postgres (no Supabase stack) green: fresh db:up + db:provision + second db:provision
  • Manual: bun run db:up && bun run db:provision && psql "$(bun run -s db:url)" -c 'select count(*) from supabase_migrations.schema_migrations'

Screenshots

Not applicable (tooling only).

Checklist

  • My code follows the code style of this project and passes
    bun run lint:backend && bun run lint.
  • My change requires a change to the documentation. (AGENTS.md section added)
  • I have updated the documentation
    accordingly.
  • My change has adequate E2E test coverage.
  • I have tested my code manually, and I have provided steps how to reproduce
    my tests
  • No GHSA ids, unpublished advisory bodies or PoCs, or embargoed exploit detail in this public PR (title, body, commits, branch name).
  • Security-sensitive authz / OTA / SQL / webhook / path changes reviewed against docs/agent-security-regressions.md.

Autofix with [code]smith
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.

Summary by CodeRabbit

  • Developer Experience
    • Added a standalone local database workflow for setting up, provisioning, checking the connection details for, and shutting down a worktree-specific Postgres database.
    • Database provisioning applies pending migrations and seeds as needed, and supports repeat runs.
    • Automated checks now validate local database provisioning, including a second provisioning run.