Migration intelligence for Rails teams.
Migflow is a Rails engine that mounts at /migflow and gives your team a visual timeline, schema diffs, and audit warnings — so you can understand migration impact before it reaches production.
- Timeline — browse every migration in order, with version, name, and a one-line summary.
- Detail view — inspect raw migration content, schema snapshot, and audit warnings side by side.
- Schema diff — focused and full diff hunks powered by
schema.rbpatches between versions. - Compare mode — pick any two migration versions and see exactly what changed.
- Schema graph — interactive ERD with tables, columns, foreign keys, and diff highlights.
- CI report — generate a Markdown or JSON report of all migrations and gate your pipeline on risk score.
- Ruby >= 3.2
- Rails 7.0 or newer
- A Rails app with migrations in
db/migrateand adb/schema.rb
Tested in CI against every combination below:
| Rails 7.0 | Rails 7.1 | Rails 7.2 | Rails 8.1 | |
|---|---|---|---|---|
| Ruby 3.2 | ✅ | ✅ | ✅ | ✅ |
| Ruby 3.3 | ✅ | ✅ | ✅ | ✅ |
| Ruby 3.4 | ✅ | ✅ | ✅ | ✅ |
| Ruby 4.0 | ✅ | ✅ | ✅ | ✅ |
Add Migflow to your Gemfile:
gem "migflow"bundle installMount the engine in your routes:
# config/routes.rb
mount Migflow::Engine, at: "/migflow"Start your app and open http://localhost:3000/migflow.
All options are set in an initializer:
# config/initializers/migflow.rb
Migflow.configure do |config|
# ...
end| Option | Default | Description |
|---|---|---|
migrations_path |
db/migrate |
Path to the migrations directory |
schema_path |
db/schema.rb |
Path to the schema file |
enabled_rules |
:all |
Audit rules to run. Pass an array of rule name symbols to enable a subset, or :all to run every rule |
expose_raw_content |
true |
Whether to include the migration source code in the API response. Set to false to hide it |
parent_controller |
"ActionController::Base" |
Controller class Migflow inherits from. Set to your app's ApplicationController to inherit authentication helpers |
authentication_hook |
nil |
A lambda run as a before_action on every Migflow request. Use it to enforce authentication |
unauthenticated_redirect |
nil |
A lambda returning the path to redirect to when authentication fails. Required when authentication_hook is set, because host app route helpers must be accessed via main_app.<helper> inside a mounted engine |
Migflow has no authentication out of the box. To protect the dashboard, set parent_controller to inherit your app's auth helpers, provide an authentication_hook to enforce the check, and set unauthenticated_redirect to tell Migflow where to send unauthenticated requests.
Rails 8 built-in Authentication
Migflow.configure do |config|
config.parent_controller = "ApplicationController"
config.authentication_hook = -> { require_authentication }
config.unauthenticated_redirect = -> { main_app.new_session_path }
endDevise
Migflow.configure do |config|
config.parent_controller = "ApplicationController"
config.authentication_hook = -> { authenticate_admin! }
config.unauthenticated_redirect = -> { main_app.new_admin_session_path }
endThe frontend talks to these JSON endpoints under /migflow/api:
| Method | Path | Description |
|---|---|---|
GET |
/migrations |
List all migrations for the timeline |
GET |
/migrations/:version |
Migration detail — warnings and schema patch |
GET |
/diff?from=:version&to=:version |
Schema diff between two versions |
Run the analysis from the command line without starting a server:
# Markdown summary (default)
bundle exec rails migflow:report
# JSON output for downstream tooling
bundle exec rails migflow:report FORMAT=json
# Gate: exit 1 if any migration has risk level high or above
bundle exec rails migflow:report FAIL_ON=high
# Gate: exit 1 if any migration scores 40 or above
bundle exec rails migflow:report FAIL_ON=40
# Write to a file instead of stdout
bundle exec rails migflow:report FORMAT=json OUTPUT=migflow-report.jsonFAIL_ON accepts a level name (low, medium, high) or any integer score. Level names map to their minimum boundary (high → 71, medium → 31, low → 1), so FAIL_ON=medium catches medium and high migrations.
- name: Migration analysis summary
run: bundle exec rails migflow:report FORMAT=markdown >> $GITHUB_STEP_SUMMARY
- name: Gate on high risk
run: bundle exec rails migflow:report FAIL_ON=highA ready-made workflow that triggers on pull requests touching db/migrate/ is included at .github/workflows/ci-report.yml.
Prerequisites: Ruby 3.3, Node 22.
git clone https://github.com/jv4lentim/migflow.git
cd migflow
bin/setupbin/setup installs Ruby and frontend dependencies. After that:
# Run tests
bundle exec rake spec
# Run linter
bundle exec rubocop
# Build frontend assets
cd frontend && npm run build
# Frontend dev server with hot reload (http://localhost:5173)
cd frontend && npm run devAfter rebuilding frontend assets, restart your Rails server to pick up the changes.
Testing against a local Rails app:
# In your app's Gemfile:
gem "migflow", path: "../migflow"- Read-only. Migflow only reads
db/migrate/anddb/schema.rb— it never runs migrations or writes to the database. schema.rbrequired. Projects usingstructure.sqlare not supported yet.- Regex-based DSL parsing.
SnapshotBuilderreplays migration DSL calls with a regex scanner. Highly dynamic migrations (metaprogramming, loops,executewith raw SQL) may produce incomplete snapshots. - No authentication out of the box. See Authentication to protect the dashboard before deploying to a shared environment.
- Single-app only. There is no support for multi-database setups or comparing migrations across separate Rails apps.
Planned in rough priority order:
-
structure.sqlsupport - Baseline / waiver system — suppress known warnings explicitly and traceably
- Cross-branch comparison — diff migrations between two git branches without switching
Have an idea? Open a feature request.
Issues and pull requests are welcome. See CONTRIBUTING.md for the full guide.
This project follows the Contributor Covenant.
Migflow is released under the MIT License.