fix(db): apply the retention swap migrations on Postgres 17

AN
5d ago
+13-13

What & why

A fresh local setup cannot complete today. Two independent reasons, both on the path ./.superset/setup.local.sh walks.

  1. db:migrate stops at 0122_webhook_events_swap_to_short_retention.sql with constraint "webhook_events_swap_id_not_null" for table "webhook_events" does not exist, and the run rolls back, so nothing is applied. Migrations 0122 and 0125 rename the *_not_null constraints their swap tables get, and Postgres only catalogues not-null constraints from version 18 on. The compose file pins postgres:17, where those constraints simply do not exist as catalogued objects, so the renames can never match. The six plus seven statements now run only when the constraint is present: identical outcome on 18, and 17 finishes with the same schema.

  2. Validate .env fails because .env.local.example does not list SERVER_ANTHROPIC_API_KEY, one of the keys apps/api/src/env.ts requires. That template documents itself as "the one list of keys the API requires and the placeholder each gets", so the fake placeholder now sits next to the other Anthropic one.

The alternative for the first point is moving the local image to Postgres 18, which also means mounting the volume at /var/lib/postgresql (the 18 image refuses /var/lib/postgresql/data) and rebuilding every existing local volume. Fixing the two migrations keeps the pinned version working and changes nothing where they already ran.

How I tested it

  • Before: on a clean checkout, ./.superset/setup.local.sh reports failed Validate .env and Apply migrations steps, and bun run db:migrate stops at the rename above, leaving 0 rows in drizzle.__drizzle_migrations.
  • After: with the volume removed and .env recreated from the template, the same script ends with All steps completed successfully!, 128/128 migrations applied, and the dev account seeded.
  • bun drizzle-kit check in packages/db reports "Everything's fine" with the edited files. The migrator only compares each migration.folderMillis against the last created_at and stores the hash without ever comparing it, so editing already-applied migrations cannot affect an environment where they ran.
  • I had no Postgres 18 instance to run against. The 18 path is reasoned from the pg_constraint behaviour rather than executed: there the constraints exist, so the renames still run, unchanged.

Editing migrations 0122 and 0125

AGENTS.md forbids hand-editing packages/db/drizzle/ without explicit user confirmation, so the confirmation is recorded here: it was given on 2026-11-03, with the trade-off above in hand, to keep the guard edits rather than move the local image to Postgres 18.

What the edit is, exactly: the six *_not_null renames in 0122 and the seven in 0125 are unchanged. Each one is wrapped in a DO block that first checks pg_constraint for that name on the table the rename targets. Where the constraint is catalogued (18 and up) the rename runs as it always did; where it is not (17) it is skipped, which leaves the table with the names it already has.

Why not a follow-up migration: 0122 is what fails on a fresh 17, so the run never reaches a later file, and the migrator runs every pending file in one transaction. An environment where these two already ran does not re-run them either: drizzle picks pending migrations by folderMillis and never compares the stored hash.

No database was touched beyond the local docker compose volume setup.local.sh creates. Nothing was applied against a shared or production database, and no statement takes a lock it did not already take: the guard is a catalog read, then the same ALTER TABLE ... RENAME CONSTRAINT.

Checklist

  • PR title follows conventional commits (type(scope): subject)
  • bun run lint and bun run typecheck pass (CI fails on lint warnings too)
  • Migrations edited with the explicit user confirmation recorded above
  • "Allow edits from maintainers" is checked on fork PRs

Summary by cubic

Fixes fresh local setup on Postgres 17 by making the retention swap migrations run on the pinned v17 image and completing the required env template.

  • Migrations 0122 and 0125 now rename the swap tables' not-null constraints only when Postgres catalogues them (18+); on 17 the renames are skipped with the same resulting schema.
  • Each guard also checks the owning table, so a constraint with the same name on another relation can't trigger a failing rename.
  • .env.local.example adds the SERVER_ANTHROPIC_API_KEY placeholder the API requires, fixing the failed Validate .env step.

Summary by CodeRabbit

  • Bug Fixes
    • Improved reliability of database updates: they can now continue when certain optional schema adjustments are unavailable, rather than failing during the update. This helps avoid interruptions when applying changes across environments with differing database states.