Catch conflicting migrations on PRs: drizzle-kit check + the new check GitHub Action
#5876
Replies: 1 comment 2 replies
|
Hey @dankochetov check catches migrations that conflict with each other. I've been building the complementary piece: migrations that conflict with production uptime. It's a linter over the artifacts drizzle-kit already generates (migration SQL + snapshots) that flags lock/rewrite hazards on Postgres. Reading the snapshots (rather than just raw SQL, the way squawk does) is what kills the false positives: operations on a table created in the same migration are exempt, so bootstrap migrations lint clean. Built v1-first — the Early but working here. Would something like this be useful upstream — a kit command, a separate package, or an input to the check action? Happy to build toward whatever shape fits. |
Uh oh!
There was an error while loading. Please reload this page.
The problem: parallel migrations that merge cleanly and still break
Two branches each run
drizzle-kit generateoff the same migration history. Each branch gets a new migration generated from the same parent. Each PR is correct in isolation, CI is green on both, and since the migrations live in separate folders, git merges them without a single conflict. But if both migrations touch the same database object, the final database state now depends on the order they're applied in. Nothing in the git workflow surfaces this: the history forked silently.Here's a concrete case. The schema has a status enum:
Branch A adds a
bannedstatus.drizzle-kit generateproduces0005_add-banned:Branch B — opened the same day, unaware of A — removes
inactive. Postgres can't drop an enum value, so the generated0005_drop-inactiverecreates the type as branch B knows it:Both PRs merge cleanly — and now the outcome depends on apply order:
('active'), thenbannedis added →('active', 'banned'). Works.bannedis added first, then B's recreate replaces the enum with('active')— thebannedvalue silently disappears. And if any row was already set to'banned', theUSINGcast fails mid-migration in whatever environment applies migrations in that order.Same merged code, three possible databases.
The local answer:
drizzle-kit checkdrizzle-kit checkvalidates your migration history and detects exactly this situation: multiple migrations generated in parallel from the same parent that modify the same database objects. It reports each conflict with the migrations and statements involved, and exits non-zero. In the upcoming release it also gains--output json, emitting a machine-readable report — which is what makes it scriptable in any pipeline.The automated answer: the
checkGitHub ActionWe've added a composite action that wires this into your PR flow: it runs the
drizzle-kitinstalled in your project and posts the result as a single sticky comment that flips between states on every push:Real-world example: dankochetov/drizzle-check-action-test#7.
The step exits non-zero on conflicts, so the job can be made a required status check.
Note
This is all in a pre-release state. The action lives on the
rc4branch (referenced with@rc4), and it depends ondrizzle-kit check --output json, which is not in any published npm release yet — so you can't run this in your project just yet. We'll update this thread once adrizzle-kitpre-release with--output jsonis on npm. In the meantime, this is exactly the stage where feedback shapes the feature — comments and propositions below are very welcome.Using it in your pipeline
Once the
drizzle-kitpre-release is out, wiring it up will look like this:The package manager is auto-detected from the nearest lockfile (
npm,pnpm,yarn, andbunare supported). For non-root configs and monorepos there areconfigandworking-directoryinputs;working-directoryshould point at the package that declaresdrizzle-kit.One more setup step worth doing
A green check can go stale: if another PR with a conflicting migration merges first, nothing re-runs your PR's check, and the conflict would only surface after both land. To close this gap, protect the base branch with both the check as a required status check and "Require branches to be up to date before merging". GitHub then forces the PR to update with the latest base before merging, which re-runs the check against the real merge result.
We'd like your feedback
drizzle-kit check --output json, so the GitHub Action is mostly comment-posting glue. Would you use a first-class equivalent for GitLab CI (MR notes) or Bitbucket Pipelines (reports)? Other CI systems?All reactions