A long-lived project that still receives updates
A small Rails utility to ensure all migration files have been tested before they are committed and run in production.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

~> 2.0
~> 10.0

Runtime

>= 2
 Project Readme

Migration Signature

Sign your Rails migrations with file content, so no untested migrations make it out of CI.

About

Have you ever had a migration like the following, which you've tested, run, and are sure behaves normally, which is committed on your branch, and ready to go to production.

class MyMigration < ActiveRecord::Migration[5.2]
  def change
    do_something_safe
  end
end

Then, right before you merge your branch you decide to swap out the method in your migration for another method, forgetting to rollback and run the migration again.

class MyMigration < ActiveRecord::Migration[5.2]
  def change
    do_something_dangerous
  end
end

Because the migration is already 'up' and changes to structure.sql or schema.rb are committed, it's unlikely your test environment will ever re-execute the code in the change method. So the first time your do_something_dangerous method gets executed will be when this migration is run in production.

To get around this issue, Tanda introduced migration 'signatures'. A hash of the migration's AST stored as a comment in the migration file itself.

When the migration file is initially created and run, a signature gets added automatically to the top of the file:

# migration_signature: 22e8a816f8db8d51cec29fca5e8c08f7

class MyMigration < ActiveRecord::Migration[5.2]
  def change
    do_something_safe
  end
end

If the contents of the migration change, the signature will become invalid, meaning we can pick up un-run migrations in CI before sending them to production.

Installation

Add this line to your application's Gemfile:

gem 'migration_signature', group: :development

And then execute:

bundle

Or install it yourself as:

gem install migration_signature

Usage

Migration signatures will automatically be prepended to migration files when the up migration is run. To check the generated signatures match the migration file contents, add the following to your CI pipeline or pre-commit hook:

bundle exec migration_signature check

This command will either exit successfully or exit with code 1 and an error message.

> bundle exec migration_signature check

Missing or invalid migration signature in migration: 20190621040327_my_migration.rb. Please re-run your migration to receive an updated signature.

Configuration

You may wish to ignore specific migration files based on age or other factors. You can configure which migration files get ignored by creating a .migration_signature.yml file in the root of your repo (or from whatever) the working directory is when the gem is invoked.

# .migration_signature.yml
ignore:
  - '/full/path/to/repo/db/migrate/20190621040327_my_migration_1.rb'
  - 'db/migrate/20190621040328_my_migration_2.rb'
  - !ruby/regexp /db\/migrate\/201[2-4].*$/ # ignore migrations from 2012 - 2014