fix(dev): match local Postgres to 18 with pre-migrate version gate, seed missing Anthropic server key

OF
1mo ago
+9-2

Fixes #7803

What & why

Fresh-checkout ./.superset/setup.local.sh ends with Failed steps: Validate .env, and before that bun run db:migrate fails outright against the local Docker Postgres. Two independent gaps:

  1. Local Postgres (17) vs. production (18). Migrations 0122 and 0125 rename named NOT NULL constraints (webhook_events_swap_*_not_null, automation_events_swap_*_not_null). Those only exist in pg_constraint on PG 18+; on 17 RENAME CONSTRAINT fails, the whole migrate run rolls back, and the local DB ends up empty.
  2. Unseedable required env key. SERVER_ANTHROPIC_API_KEY is required by 5 env schemas (packages/trpc, apps/api, apps/web, apps/admin, apps/marketing), but .env.local.example only had ANTHROPIC_API_KEY. Since step_seed_env_placeholders seeds from the example, no re-run could ever satisfy validation.

Changes

  • docker-compose.yml — image: postgres:17 → postgres:18; data mount moved to /var/lib/postgresql (the 18 image relocated PGDATA to a versioned subdir and won't start with the old /data mount — confirmed against the official image docs). No other version pins exist in the repo.
  • .superset/setup.local.sh (local_migrate) — fail-fast gate before db:migrate: reads SHOW server_version_num via compose exec and aborts below 180000 with a message pointing at teardown.local.sh + re-setup, instead of a rolled-back empty database.
  • .env.local.example — added SERVER_ANTHROPIC_API_KEY=sk-ant-fake-local-dev next to the existing fake Anthropic key.
  • Deliberately untouched: packages/db/drizzle/0122 + 0125 already ran in production, so per AGENTS.md they stay as-is; the fix is local-parity plus the version gate.

How I tested it

  • bash -n + docker compose config clean.
  • Spun a scratch PG 18.6 stack from the edited compose file: booted healthy in ~4s on the new mount, version gate passes (180006).
  • Ran the real bun run db:migrate against it: migrations applied successfully, 50 public tables, journal hashes recorded. Scratch stack torn down.
  • Ran a full ./.superset/setup.local.sh on this checkout: stack healthy, migrations applied, dev account seeded — then reproduced the .env validation failure, applied the example fix, and re-ran validation standalone → green.

Heads-up for reviewers / local devs

  • Existing volumes hold PG 17 data, which PG 18 cannot read. Run ./.superset/teardown.local.sh (already down -vs) and re-run setup. This wipes local dev data — seeding (db:seed-dev) restores the dev account.
  • .env files created from the old example lack the new key; re-running setup seeds it automatically, or append SERVER_ANTHROPIC_API_KEY=sk-ant-fake-local-dev manually.

Checklist

  • PR title follows conventional commits (type(scope): subject)
  • bun run lint and bun run typecheck pass (CI fails on lint warnings too)
  • "Allow edits from maintainers" is checked on fork PRs

Summary by cubic

Fixes #7803: fresh-checkout ./.superset/setup.local.sh failed in two independent places — db:migrate errored against local Postgres 17 (production runs 18, and migrations rename constraints that only exist on PG 18+), and env validation could never pass because required SERVER_ANTHROPIC_API_KEY was missing from the example env. Local Postgres now matches 18, migrations fail fast when the version is below 18, and the example env seeds the missing key.

Migration

  • Existing volumes hold PG 17 data that PG 18 can't read — run ./.superset/teardown.local.sh and re-run setup (wipes local dev data; db:seed-dev restores the dev account).
  • Existing .env files need SERVER_ANTHROPIC_API_KEY=sk-ant-fake-local-dev added, or re-run setup to seed it.

Summary by CodeRabbit

  • Local Development
    • The local database now runs PostgreSQL 18. Setup checks the database version before applying migrations and stops with an error if the version is unsupported or cannot be verified.
  • Configuration
    • The example environment settings now include a placeholder for the server-side Anthropic API key.