Skip to content

chore: baseline drizzle migrations against production - #1395

Merged
igboyes merged 3 commits into
mainfrom
chore/drizzle-kit-config
Aug 14, 2026
Merged

chore: baseline drizzle migrations against production#1395
igboyes merged 3 commits into
mainfrom
chore/drizzle-kit-config

Conversation

@igboyes

@igboyes igboyes commented Aug 14, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds packages/data/drizzle.config.ts and the generated baseline migration 0000_baseline.sql, the first steps of taking Postgres migrations over from Alembic. Alembic still owns the schema — nothing here applies a migration, and no behaviour changes.
  • Pins all 54 foreign key constraint names in the schema mirror. Production carries Postgres's default {table}_{column}_fkey, because Alembic never named these itself; inline .references() auto-names them {table}_{col}_{ref}_{refcol}_fk, agreeing with production on columns, referenced table and both referential actions, and disagreeing on every name. foreignKeys.test.ts pins the rule so a table declared with .references() fails by name.
  • The baseline was hand-checked object by object against a schema-only dump of production. Foreign key names were the only real drift; enum member order (4/4), indexes (31/31), primary/unique constraints (78/78), CHECK constraints (11/11), identity sequence names (8/8), column nullability and server defaults all matched.

Why the naming matters: 0000 is stamped as already-applied rather than run, so a wrong name reaches no database. It reaches meta/0000_snapshot.json, which every later generate diffs against — and the first migration to touch a foreign key would emit SQL naming a constraint production does not have.

Two divergences are known and tracked rather than fixed here: 89 unbounded varchar columns are text in the mirror and legacy_history_diff's sequence keeps its pre-rename name (VIR-2986), and the instance_messages trigger has no Drizzle representation (VIR-2987). All three are inert while 0000 is stamped rather than run.

Alembic still owns the schema; this only gives drizzle-kit somewhere to
read it from. Nothing generates or applies a migration yet.

`schema` points at the barrel rather than a glob, so a migration cannot
describe something `createDb` doesn't type the runtime handle against.
`migrations` pins kit's own defaults because production's bookkeeping row
is stamped by hand later, and a moved default would orphan that stamp.
`dbCredentials.url` falls back to an empty string rather than throwing,
since `generate` never connects.

`out` is excluded from biome: drizzle-kit writes its journal and snapshots
with 2-space indent, which would fail `pnpm check` on the first generate.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • Consider separating config for migration-related commands from the generate use case so you can enforce a non-empty VT_POSTGRES_URL for db:migrate while still allowing generate to run with a dummy URL.
  • You might want to centralize the drizzle output directory path (currently ./drizzle) in a shared constant or config, to avoid future mismatches between this file and any tooling/scripts that consume generated artifacts.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Consider separating config for migration-related commands from the `generate` use case so you can enforce a non-empty `VT_POSTGRES_URL` for `db:migrate` while still allowing `generate` to run with a dummy URL.
- You might want to centralize the drizzle output directory path (currently `./drizzle`) in a shared constant or config, to avoid future mismatches between this file and any tooling/scripts that consume generated artifacts.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Production's 54 foreign keys carry Postgres's default name,
`{table}_{column}_fkey`, because Alembic never named them itself. Inline
`.references()` auto-names a constraint `{table}_{col}_{ref}_{refcol}_fk`,
agreeing with production on the columns, the referenced table and both
referential actions, and disagreeing on all 54 names.

Nothing would catch that at apply time. Migration `0000` is stamped as
already-applied rather than run, so a wrong name reaches no database — it
reaches the snapshot every later generate diffs against, and the first
migration to touch a foreign key emits SQL naming a constraint production
does not have.

`foreignKeys.test.ts` derives the expected name for every foreign key in
the barrel and pins the count, so a table declared with `.references()`
fails the suite by name.
@igboyes igboyes changed the title chore: add drizzle-kit config to packages/data chore: baseline drizzle migrations against production Aug 14, 2026
@igboyes
igboyes merged commit 40f4826 into main Aug 14, 2026
23 checks passed
@igboyes
igboyes deleted the chore/drizzle-kit-config branch August 14, 2026 22:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant