Skip to content

feat(db): add --use-shadow-db flag to test db command#4871

Open
lightstrike wants to merge 3 commits intosupabase:developfrom
lightstrikelabs:lightstrikelabs/feat/test-with-shadow-db
Open

feat(db): add --use-shadow-db flag to test db command#4871
lightstrike wants to merge 3 commits intosupabase:developfrom
lightstrikelabs:lightstrikelabs/feat/test-with-shadow-db

Conversation

@lightstrike
Copy link

Runs pgTAP tests against an ephemeral shadow database built from migrations, keeping the local dev database untouched. Reuses the existing CreateShadowDatabase/MigrateShadowDatabase machinery from db diff. Uses host networking so pg_prove can reach the shadow container via 127.0.0.1:<shadow_port>.

What kind of change does this PR introduce?

Feature — adds a new --use-shadow-db flag to both supabase db test and supabase test db.

What is the current behavior?

supabase db test (and supabase test db) always runs pgTAP tests against the local development database. This means:

  • Tests that write data or alter schema pollute the dev environment.
  • There is no built-in way to run tests against a clean, migration-derived database.
  • Developers must manually reset their local DB after destructive test runs.

What is the new behavior?

When --use-shadow-db is passed, the CLI:

  1. Spins up an ephemeral shadow container via CreateShadowDatabase (same machinery used by db diff).
  2. Applies all migrations with MigrateShadowDatabase.
  3. Overrides the pg_prove connection to point at the shadow container using host networking (127.0.0.1:<shadow_port>).
  4. Runs pgTAP tests against the shadow database.
  5. Tears down the shadow container when finished (via defer DockerRemove).

The local dev database is never touched.

Files changed (5):

  • cmd/db.go — flag wiring on dbTestCmd
  • cmd/test.go — mirror flag on testDbCmd
  • internal/db/test/test.go — shadow DB lifecycle + host networking
  • internal/db/test/test_test.go — updated call sites with false param
  • pkg/config/templates/config.toml — updated shadow_port doc comment

Additional context

Prior art: ephemeral test databases in other frameworks

Using a dedicated, disposable database for test runs is a well-established pattern across mature frameworks:

Framework Approach
Django Automatically creates a test_<dbname> database, applies all migrations, runs tests inside transactions for per-test isolation, and destroys the DB afterward (docs).
Rails Maintains a permanent test environment with its own database defined in database.yml. The schema is loaded from db/schema.rb (or structure.sql) before each test run, and each test is wrapped in a transaction that rolls back (guide).
Laravel Supports SQLite :memory: databases or a dedicated MySQL/Postgres test DB. The RefreshDatabase trait migrates or transaction-wraps each test automatically (docs).
Prisma Has an explicit shadow database concept — a temporary DB created/destroyed during prisma migrate dev to detect schema drift and validate migrations. For integration tests, Prisma recommends Docker-based ephemeral databases (docs).

The --use-shadow-db flag brings the Supabase CLI in line with this industry-standard practice: tests run against a clean, ephemeral database built from migrations, leaving development data untouched.

Why a flag (not the default)?

The flag is opt-in to ensure safe backwards compatibility — existing workflows that expect tests to run against the local dev database continue to work unchanged. Once the shadow DB path has been validated in real-world usage and deemed stable, we recommend making it the default behavior (with an opt-out flag if needed).

Runs pgTAP tests against an ephemeral shadow database built from
migrations, keeping the local dev database untouched. Reuses the
existing CreateShadowDatabase/MigrateShadowDatabase machinery from
db diff. Uses host networking so pg_prove can reach the shadow
container via 127.0.0.1:<shadow_port>.
@lightstrike lightstrike requested a review from a team as a code owner February 19, 2026 01:28
@coderabbitai
Copy link

coderabbitai bot commented Feb 19, 2026

No actionable comments were generated in the recent review. 🎉


📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added a --use-shadow-db option to run tests against a temporary, isolated shadow database.
    • Health responses now include a replication_connected field to expose replication status.
  • Documentation

    • Added docs and examples describing the shadow DB workflow, usage guidance, and config notes for the shadow DB port.

Walkthrough

Adds a new --use-shadow-db flag to the test CLI and updates internal/db/test.Run to accept a boolean useShadowDb. When true, Run provisions a temporary shadow Postgres container, waits for it to become healthy, applies migrations, overrides the DB connection to point at the shadow instance, runs tests against it, and removes the container afterwards. Call sites were updated to pass the new parameter (existing tests pass false).

Sequence Diagram(s)

sequenceDiagram
    participant CLI as Test CLI
    participant Runner as internal/db/test.Run
    participant Diff as internal/db/diff
    participant Start as internal/db/start
    participant Docker as Docker Engine
    participant DB as Shadow Postgres

    CLI->>Runner: Run(ctx, args, config, useShadowDb=true, fs)
    alt useShadowDb == true
        Runner->>Diff: CreateShadowDatabase()
        Diff->>Docker: Launch container (shadow_port)
        Docker->>DB: Start DB instance
        Diff-->>Runner: Return shadow connection info

        Runner->>Start: WaitForHealthyService(shadow host, port)
        Start->>DB: Health probe
        DB-->>Start: Healthy
        Start-->>Runner: Ready

        Runner->>Diff: MigrateShadowDatabase(shadow conn)
        Diff->>DB: Apply migrations
        DB-->>Diff: Migrations applied

        Runner->>Runner: Override config -> shadow conn
        Runner->>DB: Run tests (pgTAP / queries)
        DB-->>Runner: Test results

        Runner->>Docker: Defer DockerRemove(container)
        Docker->>DB: Stop & remove container
    else useShadowDb == false
        Runner->>Runner: Use provided config / run tests against configured DB
    end
    Runner-->>CLI: Return test results
Loading

Comment @coderabbitai help to get the list of available commands and usage tips.

@coveralls
Copy link

coveralls commented Feb 19, 2026

Pull Request Test Coverage Report for Build 22208754227

Warning: This coverage report may be inaccurate.

This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.

Details

  • 5 of 32 (15.63%) changed or added relevant lines in 3 files are covered.
  • 60 unchanged lines in 3 files lost coverage.
  • Overall coverage decreased (-0.1%) to 61.657%

Changes Missing Coverage Covered Lines Changed/Added Lines %
cmd/test.go 0 1 0.0%
cmd/db.go 0 3 0.0%
internal/db/test/test.go 5 28 17.86%
Files with Coverage Reduction New Missed Lines %
cmd/db.go 1 0.0%
internal/utils/git.go 5 57.14%
internal/start/start.go 54 65.94%
Totals Coverage Status
Change from base Build 22142437948: -0.1%
Covered Lines: 7709
Relevant Lines: 12503

💛 - Coveralls

Document the --use-shadow-db flag in the CLI man page with usage details, shadow port config, and CI guidance. Add a shadow-db example to examples.yaml and fix the stale shadow_port comment in testdata/config.toml to match the production template.
Running go generate picks up the upstream OpenAPI spec change that added ReplicationConnected to V1ServiceHealthResponseInfo1. Fixes the codegen CI check.
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.

2 participants

Comments