ci(migrations): skip db:migrate on merges that change no migration files#5225
ci(migrations): skip db:migrate on merges that change no migration files#5225waleedlatif1 wants to merge 1 commit into
Conversation
Every push to main/staging ran db:migrate against the production/staging database even when the merge changed no schema, so a no-op migration would dial the DB and fail whenever it was at its connection limit (53300, slots reserved for SUPERUSER) — red-X'ing UI-only merges. Add a detect-migrations job (dorny/paths-filter on packages/db/migrations/**) and pass the result into the reusable migrations workflow, which now skips the apply step when no migration files changed. The migrate job still runs so downstream build/deploy jobs that need it are never skipped, and the flag defaults to 'true' so manual dispatch and any unknown value always apply migrations — the gate only ever skips a provably-empty change.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
PR SummaryLow Risk Overview
Reviewed by Cursor Bugbot for commit 358a957. Configure here. |
Greptile SummaryThis PR adds a CI gate for production and staging migrations. The main changes are:
Confidence Score: 5/5This looks safe to merge after considering the deploy-path hardening note.
.github/workflows/ci.yml Important Files Changed
Reviews (1): Last reviewed commit: "ci(migrations): skip db:migrate on merge..." | Re-trigger Greptile |
| migrate: | ||
| name: Migrate DB | ||
| needs: [test-build] | ||
| needs: [test-build, detect-migrations] |
There was a problem hiding this comment.
When detect-migrations fails before producing an output, the new needs edge cancels migrate, and build-amd64 cannot run because it needs migrate. That makes a checkout or paths-filter infrastructure failure block the whole main/staging deploy path, even though the safe fallback should be to run migrations rather than skip the deploy.
|
Closing in favor of addressing the root cause — connection-slot capacity / the migration role not being able to use reserved slots — rather than gating migrations in CI. |
Summary
Every push to
main/stagingrandb:migrateagainst the production/staging database even when the merge changed no schema. A no-op migration still opens a connection and takes the advisory lock, so it fails any time the DB is at its connection limit —53300: remaining connection slots are reserved for roles with the SUPERUSER attribute— red-X'ing UI-only merges (e.g. a recent docs/component-only merge to staging).This adds a path-based gate so the apply step runs only when migration files actually changed.
Changes
ci.yml: newdetect-migrationsjob (dorny/paths-filteronpackages/db/migrations/**, mirroring the existingcheck-docs-changesjob). Its output is passed into the reusable migrations workflow.migrations.yml: newmigrations_changedinput; the versioned-apply step is skipped when it is'false'.Why it's safe (no deploy breakage, no skipped migrations)
migratejob still runs on every push to main/staging, so downstream jobs thatneed: [migrate](the image build/deploy) are never skipped. Only the DB-touching step is gated.'true'and only ever skips on a literal'false'. Manualworkflow_dispatch(no input) and any unknown/empty value therefore always apply migrations — the gate can only skip a provably-empty change, never a real one.dev(db:push) path is unchanged.Best practice
Path-filtering migration jobs so they run only when migration files change is a widely recommended CI/CD pattern; the universal requirement both schools of thought agree on is idempotency (apply only pending migrations), which this repo's
migrate.tsalready satisfies. Sources in the PR thread.Follow-up (separate, infra)
The underlying failure is connection-slot exhaustion: the non-superuser migration role can't use
superuser_reserved_connections. Real migrations can still hit this under load — worth giving the migration path dedicated/reserved capacity. Not addressed here.Type of Change
Testing
migratestill gates the build vianeeds). Behavior is exercised on the next push to staging.Checklist