Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 1 addition & 14 deletions .github/agents/pg-toolbelt.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,18 +188,6 @@ Wait for user approval before implementing.

When implementing a **fix**, **feat**, or any change that affects package behavior (patch/minor/major), add a changeset before considering the work complete. Run `bunx changeset`, select the affected package(s), pick the appropriate bump type, and commit the generated `.changeset/*.md` file with your changes.

<<<<<<< copilot/handle-cascade-dependencies-mv
### Test-Driven Fixes

Every bug fix must land as two commits (or one clearly described TDD history in the commit body):

1. **Red.** Add a test that reproduces the bug and fails against the current code. Run the focused command and paste the failure output into the commit body so reviewers can see the regression shape.
2. **Green.** Apply the minimum code change that makes the red test pass. Do not touch unrelated code in the same commit.

A fix without a failing test first is not complete. If the bug genuinely cannot be reproduced in a test (e.g. a race, a user-environment-only issue), say so explicitly in the PR and explain what manual verification was performed instead.

This rule applies to every `fix(...)` and to any `feat(...)` that changes existing behavior. New `feat(...)` work follows the usual coverage expectations in the _Test Coverage Expectations_ section.
=======
See also **Test-Driven Fixes** below — the regression test must exist (and fail) before the fix that the changeset describes.

### Test-Driven Fixes
Expand All @@ -225,7 +213,6 @@ If a repository policy or reviewer asks for a single squashed commit, keep the R
- Refactors that claim to preserve behavior: if there is doubt, pin the current behavior with a passing test first, then refactor.

**Don't:** write the production code first and then "backfill" a test that already passes. That test cannot prove the fix was necessary.
>>>>>>> main

### Testing Discipline

Expand Down Expand Up @@ -269,7 +256,7 @@ baseline fixtures as part of the upgrade.
- After upgrading the image tags, rerun the focused regression tests before
considering the upgrade done:
- `cd packages/pg-delta && PGDELTA_TEST_POSTGRES_VERSIONS=15,17 bun run test tests/integration/supabase-base-init.test.ts tests/integration/catalog-model.test.ts tests/integration/supabase-dsl-e2e.test.ts`
- `cd packages/pg-delta && PGDELTA_TEST_POSTGRES_VERSIONS=15 bun run test tests/integration/dbdev-roundtrip.test.ts`
- `cd packages/pg-delta && PGDELTA_TEST_POSTGRES_VERSIONS=15 PGDELTA_SUPABASE_PROJECT=dbdev bun run test tests/integration/supabase-project-declarative.test.ts`
- If the sync script or focused tests reveal new schemas, roles, grants, or
comments, update pg-delta’s Supabase handling (for example
`packages/pg-delta/src/core/integrations/supabase.ts` or the relevant
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ dev-debug.log

# Declarative schemas
declarative-schemas/
packages/pg-delta/test-results/


# TypeDoc generated output
Expand Down
247 changes: 0 additions & 247 deletions packages/pg-delta/tests/integration/dbdev-roundtrip.test.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { supabase } from "../../../../../src/core/integrations/supabase.ts";
import { defineSupabaseProjectFixture } from "../../../supabase-project-fixture.ts";

export default defineSupabaseProjectFixture({
id: "dbdev",
displayName: "dbdev",
supabasePostgresVersion: 15,
integration: supabase,
migrationsDir: new URL("./migrations/", import.meta.url),
setRole: "postgres",
skipDefaultPrivilegeSubtraction: true,
candidateRegressionNote:
"Reduce the failing prefix to the smallest migration slice that reproduces the issue, then turn the generated SQL or remaining diff into a focused pg-delta integration test.",
scenarios: {
declarative: {
include: (filename) => filename.startsWith("20220117"),
onApplyError: "fail",
},
progressive: {
// The runner compares stepping main against a *fully* migrated branch. With
// the full history, the plan is a "catch up" to head that cannot be
// applied as one plan (statements like ADD COLUMN without migration-time
// DEFAULT/backfill from later files). Scope to the same prefix as
// declarative so the target branch and incremental main can converge.
include: (filename) => filename.startsWith("20220117"),
onApplyError: "skip",
},
adjacent: {
onApplyError: "skip",
// Migration uses DEFAULT + UPDATE + DROP DEFAULT; the final column has no
// default, so plan/apply from catalog diff cannot replay on non-empty tables.
skipAdjacentPlanApply: (filename) =>
filename === "20231205051816_add_default_version.sql",
},
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { describe, test } from "bun:test";
import { discoverSupabaseProjectFixtures } from "./supabase-project-fixture.ts";
import { runSupabaseProjectAdjacentSmoke } from "./supabase-project-runners.ts";

const fixtures = await discoverSupabaseProjectFixtures();

for (const fixture of fixtures) {
describe(`${fixture.displayName} adjacent smoke (pg${fixture.supabasePostgresVersion})`, () => {
test(
"each individual migration step plans and applies cleanly against the next prefix",
async () => {
await runSupabaseProjectAdjacentSmoke(fixture);
},
30 * 60 * 1000,
);
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { describe, test } from "bun:test";
import { discoverSupabaseProjectFixtures } from "./supabase-project-fixture.ts";
import { runSupabaseProjectDeclarativeRoundtrip } from "./supabase-project-runners.ts";

const fixtures = await discoverSupabaseProjectFixtures();

for (const fixture of fixtures) {
describe(`${fixture.displayName} declarative roundtrip (pg${fixture.supabasePostgresVersion})`, () => {
test(
"exported schema roundtrips to 0 remaining changes with supabase integration",
async () => {
await runSupabaseProjectDeclarativeRoundtrip(fixture);
},
5 * 60 * 1000,
);
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { expect, test } from "bun:test";
import { readdir, stat } from "node:fs/promises";
import path from "node:path";
import { pathToFileURL } from "node:url";

test("dbdev fixture uses the standardized supabase-project layout", async () => {
const projectDir = path.join(
import.meta.dir,
"fixtures/supabase-projects/dbdev",
);
const projectFile = path.join(projectDir, "project.ts");
const migrationsDir = path.join(projectDir, "migrations");

expect(await Bun.file(projectFile).exists()).toBe(true);
expect((await stat(migrationsDir)).isDirectory()).toBe(true);

const module = await import(pathToFileURL(projectFile).href);
const fixture = module.default;
const sqlFiles = (await readdir(migrationsDir))
.filter((file) => file.endsWith(".sql"))
.sort();

expect(fixture.id).toBe("dbdev");
expect(fixture.supabasePostgresVersion).toBe(15);
expect(sqlFiles.length).toBeGreaterThan(0);
expect(sqlFiles[0]).toBe("20220117141357_extensions.sql");
});
Loading
Loading