feat: add strong_migrations gem to prevent unsafe migration deploys - #2774
Conversation
21b1648 to
ad9b1eb
Compare
|
@olleolleolle do you think it makes sense to fix all the existing migrations, going all the way back to the dawn of time? |
|
@mroderick At work, we ditch migration files we have used up, after some time. We rely on db/schema.rb instead, rather than a group of migration files in order. So, a step could be: find a migration file that needs a fix, and remove it AND its predecessors. |
So, you keep the migrations around in case you need to run the Do you use tools like |
Yeah, something like that - we don’t have a schedule for these “lose the migration files” events. We do it when it “feels right”.
We don’t use a squasher tool. |
…oduction Install strong_migrations 2.8.0 and configure it to analyze all migrations from 2026-01-01 onwards. Target PostgreSQL 16 (Heroku production version). Wrap existing 2026 migrations that violate safety rules with `safety_assured` blocks — these were already deployed and are acknowledged as reviewed. No migration logic is changed. Violations wrapped: - execute SQL with DELETE (duplicate cleanup) - update_all inside migration (sponsor backfill) - add_index without algorithm: :concurrently - remove_index without algorithm: :concurrently - drop_table (meeting_talks removal) - data cleanup loops inside schema migrations
ad9b1eb to
3118952
Compare
What
Adds the strong_migrations gem to block dangerous migration patterns before they reach production.
Scope
start_after = 20260101000000)Existing violations acknowledged
Six 2026 migrations already deployed contain patterns strong_migrations flags. Each is wrapped in
safety_assured { ... }— no logic changes, just marking them as reviewed:executewith DELETE for duplicate cleanupupdate_allinside a schema migration for data backfilladd_indexwithoutalgorithm: :concurrentlyremove_indexwithoutalgorithm: :concurrentlydrop_tableonmeeting_talksdelete_all) inside schema migrationsReviewer hint: it's a lot easier to review this part of the PR, if you hide the whitespace changes 😄
What this prevents going forward
algorithm: :concurrentlyon large tablesdrop_table/remove_columnwithout a staged removal processexecuteSQL without review