diff --git a/CHANGELOG.md b/CHANGELOG.md index bd47114..f760bb1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## [0.7.6] - 2024-07-05 +- Added UI +- Added environment variable `ACTUAL_DB_SCHEMA_UI_ENABLED` to enable/disable the UI in specific environments +- Added configuration option `ActualDbSchema.config[:ui_enabled]` to enable/disable the UI in specific environments + ## [0.7.5] - 2024-06-20 - Added db:rollback_migrations:manual task to manually rolls back phantom migrations one by one diff --git a/README.md b/README.md index 052c9fc..f1e46ac 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,35 @@ The gem offers the following rake tasks that can be manually run according to yo - `rails db:rollback_branches:manual` - run it to manually rolls back phantom migrations one by one. - `rails db:phantom_migrations` - displays a list of phantom migrations. +## Accessing the UI + +The UI for managing migrations is enabled automatically. To access the UI, simply navigate to the following URL in your web browser: +``` +http://localhost:3000/rails/phantom_migrations +``` +This page displays a list of phantom migrations for each database connection and provides options to view details and rollback them. + +## UI options + +By default, the UI is enabled in the development environment. If you prefer to enable the UI for another environment, you can do so in two ways: + +### 1. Using Environment Variable + +Set the environment variable `ACTUAL_DB_SCHEMA_UI_ENABLED` to `true`: + +```sh +export ACTUAL_DB_SCHEMA_UI_ENABLED=true +``` + +### 2. Using Initializer +Add the following line to your initializer file (`config/initializers/actual_db_schema.rb`): + +```ruby +ActualDbSchema.config[:ui_enabled] = true +``` + +> With this option, the UI can be disabled for all environments or be enabled in specific ones. + ## Disabling Automatic Rollback By default, the automatic rollback of migrations is enabled. If you prefer to perform manual rollbacks, you can disable the automatic rollback in two ways: diff --git a/app/assets/stylesheets/actual_db_schema/styles.css b/app/assets/stylesheets/actual_db_schema/styles.css new file mode 100644 index 0000000..4c4346e --- /dev/null +++ b/app/assets/stylesheets/actual_db_schema/styles.css @@ -0,0 +1,68 @@ +body { + margin: 8px; + background-color: #fff; + color: #333; +} + +body, p, td { + font-family: helvetica, verdana, arial, sans-serif; + font-size: 13px; + line-height: 18px; +} + +h2 { + padding-left: 10px; +} + +table { + margin: 0; + border-collapse: collapse; + + thead tr { + border-bottom: 2px solid #ddd; + } + + tbody { + tr { + border-bottom: 1px solid #ddd; + } + + tr:nth-child(odd) { + background: #f2f2f2; + } + } + + td { + padding: 14px 30px; + } +} + +.button { + font-weight: bold; + color: #000; + border: none; + padding: 5px 10px; + text-align: center; + text-decoration: none; + display: inline-block; + margin: 0 2px; + cursor: pointer; + border-radius: 4px; + transition: background-color 0.3s; + background: none; +} + +.button:hover { + color: #fff; + background-color: #000; +} + +.button-container { + display: flex; +} + +pre { + background-color: #f7f7f7; + padding: 10px; + border: 1px solid #ddd; +} diff --git a/app/controllers/actual_db_schema/phantom_migrations_controller.rb b/app/controllers/actual_db_schema/phantom_migrations_controller.rb new file mode 100644 index 0000000..2734075 --- /dev/null +++ b/app/controllers/actual_db_schema/phantom_migrations_controller.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +module ActualDbSchema + # Controller to display the list of phantom migrations for each database connection. + class PhantomMigrationsController < ActionController::Base + def index; end + + def show + render file: "#{Rails.root}/public/404.html", layout: false, status: :not_found unless phantom_migration + end + + def rollback + ActualDbSchema::Migration.rollback(params[:id], params[:database]) + redirect_to phantom_migrations_path + end + + private + + helper_method def phantom_migrations + @phantom_migrations ||= ActualDbSchema::Migration.all + end + + helper_method def phantom_migration + @phantom_migration ||= ActualDbSchema::Migration.find(params[:id], params[:database]) + end + end +end diff --git a/app/views/actual_db_schema/phantom_migrations/index.html.erb b/app/views/actual_db_schema/phantom_migrations/index.html.erb new file mode 100644 index 0000000..f749a64 --- /dev/null +++ b/app/views/actual_db_schema/phantom_migrations/index.html.erb @@ -0,0 +1,45 @@ + + + + Phantom Migrations + <%= stylesheet_link_tag 'actual_db_schema/styles', media: 'all' %> + + +
+

Phantom Migrations

+ <% if phantom_migrations.present? %> + + + + + + + + + + + + + <% phantom_migrations.each do |migration| %> + + + + + + + + + <% end %> + +
StatusMigration IDNameBranchDatabaseActions
<%= migration[:status] %><%= migration[:version] %><%= migration[:name] %><%= migration[:branch] %><%= migration[:database] %> +
+ <%= link_to '👁 Show', phantom_migration_path(id: migration[:version], database: migration[:database]), class: 'button' %> + <%= button_to '⎌ Rollback', rollback_phantom_migration_path(id: migration[:version], database: migration[:database]), method: :post, class: 'button' %> +
+
+ <% else %> +

No phantom migrations found.

+ <% end %> +
+ + diff --git a/app/views/actual_db_schema/phantom_migrations/show.html.erb b/app/views/actual_db_schema/phantom_migrations/show.html.erb new file mode 100644 index 0000000..96681cf --- /dev/null +++ b/app/views/actual_db_schema/phantom_migrations/show.html.erb @@ -0,0 +1,45 @@ + + + + Phantom Migration Details + <%= stylesheet_link_tag 'actual_db_schema/styles', media: 'all' %> + + +
+

Phantom Migration <%= phantom_migration[:name] %> Details

+ + + + + + + + + + + + + + + + + + + + + + + +
Status<%= phantom_migration[:status] %>
Migration ID<%= phantom_migration[:version] %>
Branch<%= phantom_migration[:branch] %>
Database<%= phantom_migration[:database] %>
Path<%= phantom_migration[:filename] %>
+ +

Migration Code

+
+
<%= File.read(phantom_migration[:filename]) %>
+
+
+ <%= link_to '← Back', phantom_migrations_path, class: 'button' %> + <%= button_to '⎌ Rollback', rollback_phantom_migration_path(id: params[:id], database: params[:database]), method: :post, class: 'button' %> +
+
+ + diff --git a/config/routes.rb b/config/routes.rb new file mode 100644 index 0000000..5d5d42e --- /dev/null +++ b/config/routes.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +ActualDbSchema::Engine.routes.draw do + resources :phantom_migrations, only: %i[index show] do + member do + post :rollback + end + end +end diff --git a/lib/actual_db_schema.rb b/lib/actual_db_schema.rb index 314002a..b51cd45 100644 --- a/lib/actual_db_schema.rb +++ b/lib/actual_db_schema.rb @@ -1,10 +1,13 @@ # frozen_string_literal: true +require "actual_db_schema/engine" require "active_record/migration" require "csv" require_relative "actual_db_schema/git" require_relative "actual_db_schema/store" require_relative "actual_db_schema/version" +require_relative "actual_db_schema/migration" +require_relative "actual_db_schema/migration_context" require_relative "actual_db_schema/patches/migration_proxy" require_relative "actual_db_schema/patches/migrator" require_relative "actual_db_schema/patches/migration_context" @@ -17,8 +20,6 @@ module ActualDbSchema raise NotImplementedError, "ActualDbSchema is only supported in Rails" unless defined?(Rails) - require "railtie" - class << self attr_accessor :config, :failed end @@ -26,7 +27,8 @@ class << self self.failed = [] self.config = { enabled: Rails.env.development?, - auto_rollback_disabled: ENV["ACTUAL_DB_SCHEMA_AUTO_ROLLBACK_DISABLED"].present? + auto_rollback_disabled: ENV["ACTUAL_DB_SCHEMA_AUTO_ROLLBACK_DISABLED"].present?, + ui_enabled: Rails.env.development? || ENV["ACTUAL_DB_SCHEMA_UI_ENABLED"].present? } def self.migrated_folder @@ -58,17 +60,16 @@ def self.migrations_paths end end - def self.migration_filename(fullpath) - fullpath.split("/").last + def self.db_config + if ActiveRecord::Base.respond_to?(:connection_db_config) + ActiveRecord::Base.connection_db_config.configuration_hash + else + ActiveRecord::Base.connection_config + end end - def self.for_each_db_connection - configs = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env) - configs.each do |db_config| - config = db_config.respond_to?(:config) ? db_config.config : db_config - ActiveRecord::Base.establish_connection(config) - yield - end + def self.migration_filename(fullpath) + fullpath.split("/").last end end diff --git a/lib/actual_db_schema/commands/base.rb b/lib/actual_db_schema/commands/base.rb index 055f35e..fc49684 100644 --- a/lib/actual_db_schema/commands/base.rb +++ b/lib/actual_db_schema/commands/base.rb @@ -4,6 +4,12 @@ module ActualDbSchema module Commands # Base class for all commands class Base + attr_reader :context + + def initialize(context) + @context = context + end + def call unless ActualDbSchema.config.fetch(:enabled, true) raise "ActualDbSchema is disabled. Set ActualDbSchema.config[:enabled] = true to enable it." @@ -17,22 +23,6 @@ def call def call_impl raise NotImplementedError end - - def context - @context ||= fetch_migration_context.tap do |c| - c.extend(ActualDbSchema::Patches::MigrationContext) - end - end - - def fetch_migration_context - ar_version = Gem::Version.new(ActiveRecord::VERSION::STRING) - if ar_version >= Gem::Version.new("7.2.0") || - (ar_version >= Gem::Version.new("7.1.0") && ar_version.prerelease?) - ActiveRecord::Base.connection_pool.migration_context - else - ActiveRecord::Base.connection.migration_context - end - end end end end diff --git a/lib/actual_db_schema/commands/list.rb b/lib/actual_db_schema/commands/list.rb index a45f644..e36c9ee 100644 --- a/lib/actual_db_schema/commands/list.rb +++ b/lib/actual_db_schema/commands/list.rb @@ -19,20 +19,11 @@ def preambule puts "\nPhantom migrations\n\n" puts "Below is a list of irrelevant migrations executed in unmerged branches." puts "To bring your database schema up to date, the migrations marked as \"up\" should be rolled back." - database_path = db_config[:database] - puts "\ndatabase: #{database_path}\n\n" + puts "\ndatabase: #{ActualDbSchema.db_config[:database]}\n\n" puts header.join(" ") puts "-" * separator_width end - def db_config - if ActiveRecord::Base.respond_to?(:connection_db_config) - ActiveRecord::Base.connection_db_config.configuration_hash - else - ActiveRecord::Base.connection_config - end - end - def separator_width header.map(&:length).sum + (header.size - 1) * 2 end @@ -66,14 +57,14 @@ def line_for(status, version) ].join(" ") end - def branch_for(version) - metadata.fetch(version, {})[:branch] || "unknown" - end - def metadata @metadata ||= ActualDbSchema::Store.instance.read end + def branch_for(version) + metadata.fetch(version, {})[:branch] || "unknown" + end + def longest_branch_name @longest_branch_name ||= metadata.values.map { |v| v[:branch] }.compact.max_by(&:length) || "unknown" diff --git a/lib/actual_db_schema/commands/rollback.rb b/lib/actual_db_schema/commands/rollback.rb index e0fb7ef..3ea0850 100644 --- a/lib/actual_db_schema/commands/rollback.rb +++ b/lib/actual_db_schema/commands/rollback.rb @@ -4,9 +4,9 @@ module ActualDbSchema module Commands # Rolls back all phantom migrations class Rollback < Base - def initialize(manual_mode: false) + def initialize(context, manual_mode: false) @manual_mode = manual_mode || manual_mode_default? - super() + super(context) end private diff --git a/lib/actual_db_schema/engine.rb b/lib/actual_db_schema/engine.rb new file mode 100644 index 0000000..a245b27 --- /dev/null +++ b/lib/actual_db_schema/engine.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +module ActualDbSchema + # It isolates the namespace to avoid conflicts with the main application. + class Engine < ::Rails::Engine + isolate_namespace ActualDbSchema + + initializer "actual_db_schema.initialize" do |app| + if ActualDbSchema.config[:ui_enabled] + app.routes.append do + mount ActualDbSchema::Engine => "/rails" + end + + app.config.assets.precompile += %w[actual_db_schema/styles.css] + end + end + end +end diff --git a/lib/actual_db_schema/migration.rb b/lib/actual_db_schema/migration.rb new file mode 100644 index 0000000..a3a9ad6 --- /dev/null +++ b/lib/actual_db_schema/migration.rb @@ -0,0 +1,88 @@ +# frozen_string_literal: true + +module ActualDbSchema + # The Migration class is responsible for managing and retrieving migration information + class Migration + include Singleton + + Migration = Struct.new(:status, :version, :name, :branch, :database, :filename, keyword_init: true) + + def self.all + instance.all + end + + def self.find(version, database) + instance.find(version, database) + end + + def self.rollback(version, database) + instance.rollback(version, database) + end + + def all + migrations = [] + + MigrationContext.instance.each do |context| + indexed_migrations = context.migrations.index_by { |m| m.version.to_s } + + context.migrations_status.each do |status, version| + migration = indexed_migrations[version] + migrations << build_migration_struct(status, migration) if migration && status == "up" + end + end + + migrations + end + + def find(version, database) + MigrationContext.instance.each do |context| + next unless ActualDbSchema.db_config[:database] == database + + migration = find_migration_in_context(context, version) + return migration if migration + end + nil + end + + def rollback(version, database) + MigrationContext.instance.each do |context| + next unless ActualDbSchema.db_config[:database] == database + + if context.migrations.detect { |m| m.version.to_s == version } + context.run(:down, version.to_i) + break + end + end + end + + private + + def build_migration_struct(status, migration) + Migration.new( + status: status, + version: migration.version.to_s, + name: migration.name, + branch: branch_for(migration.version), + database: ActualDbSchema.db_config[:database], + filename: migration.filename + ) + end + + def find_migration_in_context(context, version) + migration = context.migrations.detect { |m| m.version.to_s == version } + return unless migration + + status = context.migrations_status.detect { |_s, v| v.to_s == version }&.first || "unknown" + build_migration_struct(status, migration) + end + + def branch_for(version) + metadata.fetch(version.to_s, {})[:branch] || "unknown" + end + + def metadata + @metadata ||= {} + @metadata[ActualDbSchema.db_config[:database]] ||= ActualDbSchema::Store.instance.read + end + end +end diff --git a/lib/actual_db_schema/migration_context.rb b/lib/actual_db_schema/migration_context.rb new file mode 100644 index 0000000..dd5fd01 --- /dev/null +++ b/lib/actual_db_schema/migration_context.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +module ActualDbSchema + # The class manages connections to each database and provides the appropriate migration context for each connection. + class MigrationContext + include Singleton + + def each + configs.each do |db_config| + establish_connection(db_config) + yield context + end + end + + private + + def establish_connection(db_config) + config = db_config.respond_to?(:config) ? db_config.config : db_config + ActiveRecord::Base.establish_connection(config) + end + + def configs + ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env) + end + + def context + ar_version = Gem::Version.new(ActiveRecord::VERSION::STRING) + context = if ar_version >= Gem::Version.new("7.2.0") || + (ar_version >= Gem::Version.new("7.1.0") && ar_version.prerelease?) + ActiveRecord::Base.connection_pool.migration_context + else + ActiveRecord::Base.connection.migration_context + end + context.extend(ActualDbSchema::Patches::MigrationContext) + end + end +end diff --git a/lib/actual_db_schema/patches/migration_context.rb b/lib/actual_db_schema/patches/migration_context.rb index 5645aac..aa8b30e 100644 --- a/lib/actual_db_schema/patches/migration_context.rb +++ b/lib/actual_db_schema/patches/migration_context.rb @@ -52,7 +52,7 @@ def show_info_for(migration) puts "\n[ActualDbSchema] A phantom migration was found and is about to be rolled back." puts "Please make a decision from the options below to proceed.\n\n" puts "Branch: #{branch_for(migration.version.to_s)}" - puts "Database: #{db_config[:database]}" + puts "Database: #{ActualDbSchema.db_config[:database]}" puts "Version: #{migration.version}\n\n" puts File.read(migration.filename) end @@ -69,14 +69,6 @@ def migrate(migration) migrator.migrate end - def db_config - @db_config ||= if ActiveRecord::Base.respond_to?(:connection_db_config) - ActiveRecord::Base.connection_db_config.configuration_hash - else - ActiveRecord::Base.connection_config - end - end - def branch_for(version) metadata.fetch(version, {})[:branch] || "unknown" end diff --git a/lib/railtie.rb b/lib/railtie.rb deleted file mode 100644 index d64c247..0000000 --- a/lib/railtie.rb +++ /dev/null @@ -1,15 +0,0 @@ -# frozen_string_literal: true - -require "rails" - -module ActualDbSchema - # Load the task into Rails app - class Railtie < Rails::Railtie - railtie_name :actual_db_schema - - rake_tasks do - path = File.expand_path(__dir__) - Dir.glob("#{path}/tasks/**/*.rake").each { |f| load f } - end - end -end diff --git a/lib/tasks/db.rake b/lib/tasks/db.rake index 3379f06..2c42b8f 100644 --- a/lib/tasks/db.rake +++ b/lib/tasks/db.rake @@ -4,8 +4,8 @@ namespace :db do desc "Rollback migrations that were run inside not a merged branch." task rollback_branches: :load_config do ActualDbSchema.failed = [] - ActualDbSchema.for_each_db_connection do - ActualDbSchema::Commands::Rollback.new.call + ActualDbSchema::MigrationContext.instance.each do |context| + ActualDbSchema::Commands::Rollback.new(context).call end end @@ -13,16 +13,16 @@ namespace :db do desc "Manually rollback phantom migrations one by one" task manual: :load_config do ActualDbSchema.failed = [] - ActualDbSchema.for_each_db_connection do - ActualDbSchema::Commands::Rollback.new(manual_mode: true).call + ActualDbSchema::MigrationContext.instance.each do |context| + ActualDbSchema::Commands::Rollback.new(context, manual_mode: true).call end end end desc "List all phantom migrations - non-relevant migrations that were run inside not a merged branch." task phantom_migrations: :load_config do - ActualDbSchema.for_each_db_connection do - ActualDbSchema::Commands::List.new.call + ActualDbSchema::MigrationContext.instance.each do |context| + ActualDbSchema::Commands::List.new(context).call end end diff --git a/test/controllers/actual_db_schema/phantom_migrations_controller_test.rb b/test/controllers/actual_db_schema/phantom_migrations_controller_test.rb new file mode 100644 index 0000000..c33840a --- /dev/null +++ b/test/controllers/actual_db_schema/phantom_migrations_controller_test.rb @@ -0,0 +1,134 @@ +# frozen_string_literal: true + +require_relative "../../test_helper" +require_relative "../../../app/controllers/actual_db_schema/phantom_migrations_controller" + +module ActualDbSchema + class PhantomMigrationsControllerTest < ActionController::TestCase + def setup + @utils = TestUtils.new + @app = Rails.application + routes_setup + Rails.logger = Logger.new($stdout) + ActionController::Base.view_paths = [File.expand_path("../../../app/views/", __dir__)] + active_record_setup + @utils.cleanup(TestingState.db_config) + @utils.prepare_phantom_migrations(TestingState.db_config) + end + + def routes_setup + @routes = @app.routes + Rails.application.routes.draw do + get "/rails/phantom_migrations" => "actual_db_schema/phantom_migrations#index", as: "phantom_migrations" + get "/rails/phantom_migration/:id" => "actual_db_schema/phantom_migrations#show", as: "phantom_migration" + post "/rails/phantom_migration/:id/rollback" => "actual_db_schema/phantom_migrations#rollback", + as: "rollback_phantom_migration" + end + ActualDbSchema::PhantomMigrationsController.include(@routes.url_helpers) + end + + def active_record_setup + ActiveRecord::Base.configurations = { "test" => TestingState.db_config } + ActiveRecord::Tasks::DatabaseTasks.database_configuration = { "test" => TestingState.db_config } + end + + test "GET #index returns a successful response" do + get :index + assert_response :success + assert_select "table" do + assert_select "tbody" do + assert_select "tr" do |rows| + rows.each do |row| + assert_no_match(/down/, row.text) + end + end + assert_select "tr" do + assert_select "td", text: "up" + assert_select "td", text: "20130906111511" + assert_select "td", text: "FirstPrimary" + assert_select "td", text: @utils.branch_for("20130906111511") + assert_select "td", text: "tmp/primary.sqlite3" + end + assert_select "tr" do + assert_select "td", text: "up" + assert_select "td", text: "20130906111512" + assert_select "td", text: "SecondPrimary" + assert_select "td", text: @utils.branch_for("20130906111512") + assert_select "td", text: "tmp/primary.sqlite3" + end + assert_select "tr" do + assert_select "td", text: "up" + assert_select "td", text: "20130906111514" + assert_select "td", text: "FirstSecondary" + assert_select "td", text: @utils.branch_for("20130906111514") + assert_select "td", text: "tmp/secondary.sqlite3" + end + assert_select "tr" do + assert_select "td", text: "up" + assert_select "td", text: "20130906111515" + assert_select "td", text: "SecondSecondary" + assert_select "td", text: @utils.branch_for("20130906111515") + assert_select "td", text: "tmp/secondary.sqlite3" + end + end + end + end + + test "GET #index when all migrations is down returns a not found text" do + @utils.run_migrations + get :index + assert_response :success + assert_select "p", text: "No phantom migrations found." + end + + test "GET #show returns a successful response" do + get :show, params: { id: "20130906111511", database: "tmp/primary.sqlite3" } + assert_response :success + assert_select "h2", text: "Phantom Migration FirstPrimary Details" + assert_select "table" do + assert_select "tr" do + assert_select "th", text: "Status" + assert_select "td", text: "up" + end + assert_select "tr" do + assert_select "th", text: "Migration ID" + assert_select "td", text: "20130906111511" + end + assert_select "tr" do + assert_select "th", text: "Database" + assert_select "td", text: "tmp/primary.sqlite3" + end + assert_select "tr" do + assert_select "th", text: "Branch" + assert_select "td", text: @utils.branch_for("20130906111511") + end + end + end + + test "GET #show returns a 404 response if migration not found" do + get :show, params: { id: "nil", database: "tmp/primary.sqlite3" } + assert_response :not_found + end + + test "POST #rollback changes migration status to down and hide migration with down status" do + post :rollback, params: { id: "20130906111511", database: "tmp/primary.sqlite3" } + assert_response :redirect + get :index + assert_select "table" do + assert_select "tbody" do + assert_select "tr" do |rows| + rows.each do |row| + assert_no_match(/down/, row.text) + end + end + assert_select "tr" do + assert_select "td", text: "up" + assert_select "td", text: "20130906111512" + assert_select "td", text: "SecondPrimary" + assert_select "td", text: @utils.branch_for("20130906111512") + end + end + end + end + end +end diff --git a/test/dummy_app/db/secondary_schema.rb b/test/dummy_app/db/secondary_schema.rb index be9176e..b200061 100644 --- a/test/dummy_app/db/secondary_schema.rb +++ b/test/dummy_app/db/secondary_schema.rb @@ -2,13 +2,14 @@ # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. # -# This file is the source Rails uses to define your schema when running `bin/rails -# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to +# This file is the source Rails uses to define your schema when running `rails +# db:schema:load`. When creating a new database, `rails db:schema:load` tends to # be faster and is potentially less error prone than running all of your # migrations from scratch. Old migrations may fail to apply correctly if those # migrations use external dependencies or application code. # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2013_09_06_111515) do +ActiveRecord::Schema.define(version: 2013_09_06_111515) do + end diff --git a/test/dummy_app/public/404.html b/test/dummy_app/public/404.html new file mode 100644 index 0000000..e69de29 diff --git a/test/support/test_utils.rb b/test/support/test_utils.rb index c00d4b9..36f270d 100644 --- a/test/support/test_utils.rb +++ b/test/support/test_utils.rb @@ -141,6 +141,10 @@ def migrated_files(db_config = nil) end end + def branch_for(version) + metadata.fetch(version.to_s, {})[:branch] + end + private def cleanup_call(prefix_name = nil) @@ -189,4 +193,8 @@ def applied_migrations_call def run_sql(sql) ActiveRecord::Base.connection.execute(sql) end + + def metadata + ActualDbSchema::Store.instance.read + end end