diff --git a/lib/annotate_rb/tasks/annotate_models_migrate.rake b/lib/annotate_rb/tasks/annotate_models_migrate.rake index 24559735..908a1e99 100644 --- a/lib/annotate_rb/tasks/annotate_models_migrate.rake +++ b/lib/annotate_rb/tasks/annotate_models_migrate.rake @@ -22,8 +22,11 @@ if defined?(Rails::Application) && Rails.version.split(".").first.to_i >= 6 end end +config = ::AnnotateRb::ConfigLoader.load_config + migration_tasks.each do |task| next unless Rake::Task.task_defined?(task) + next if config[:skip_on_db_migrate] Rake::Task[task].enhance do # This block is ran after `task` completes task_name = Rake.application.top_level_tasks.last # The name of the task that was run, e.g. "db:migrate" diff --git a/spec/integration/annotate_after_migration_spec.rb b/spec/integration/annotate_after_migration_spec.rb index 455bbe54..6a6d0bd1 100644 --- a/spec/integration/annotate_after_migration_spec.rb +++ b/spec/integration/annotate_after_migration_spec.rb @@ -54,4 +54,36 @@ expect(annotated_test_default).to eq(expected_test_default) end end + + context "when skip_on_db_migrate is enabled" do + before do + # Install the rake task hook + _cmd = run_command_and_stop("bin/rails g annotate_rb:install", fail_on_error: true, exit_timeout: command_timeout_seconds) + + # Create config with skip_on_db_migrate enabled + write_file(".annotaterb.yml", "skip_on_db_migrate: true") + end + + it "skips annotation during migration" do + reset_database + + original_test_default = read_file(dummyapp_model("test_default.rb")) + + # Run migration - should NOT trigger annotation due to skip_on_db_migrate + _run_migrations_cmd = run_command_and_stop("bin/rails db:migrate", fail_on_error: true, exit_timeout: command_timeout_seconds) + + # File should remain unchanged + unchanged_test_default = read_file(dummyapp_model("test_default.rb")) + + expect(last_command_started).to be_successfully_executed + expect(unchanged_test_default).to eq(original_test_default) + + # Verify annotation still works when run manually + _manual_cmd = run_command_and_stop("bundle exec annotaterb models", fail_on_error: true, exit_timeout: command_timeout_seconds) + annotated_test_default = read_file(dummyapp_model("test_default.rb")) + expected_test_default = read_file(model_template("test_default.rb")) + + expect(annotated_test_default).to eq(expected_test_default) + end + end end diff --git a/spec/lib/tasks/annotate_models_migrate_spec.rb b/spec/lib/tasks/annotate_models_migrate_spec.rb index fd6cdc2c..77698606 100644 --- a/spec/lib/tasks/annotate_models_migrate_spec.rb +++ b/spec/lib/tasks/annotate_models_migrate_spec.rb @@ -1,64 +1,118 @@ RSpec.describe "ActiveRecord migration rake task hooks" do context "single database" do - before do - Rake.application = Rake::Application.new + shared_context "spec setup with a single database" do |skip_on_db_migrate: false| + before do + allow(AnnotateRb::ConfigLoader).to receive(:load_config).and_return({skip_on_db_migrate:}) - # Stub migration tasks - %w[db:migrate db:migrate:up db:migrate:down db:migrate:reset db:rollback].each do |task| - Rake::Task.define_task(task) + Rake.application = Rake::Application.new + + # Stub migration tasks + %w[db:migrate db:migrate:up db:migrate:down db:migrate:reset db:rollback].each do |task| + Rake::Task.define_task(task) + end + + Rake::Task.define_task("db:migrate:redo") do + Rake::Task["db:rollback"].invoke + Rake::Task["db:migrate"].invoke + end + + Rake.load_rakefile("annotate_rb/tasks/annotate_models_migrate.rake") + + Rake.application.instance_variable_set(:@top_level_tasks, [subject]) end + end + + context "when skip_on_db_migrate is disabled" do + include_context "spec setup with a single database", skip_on_db_migrate: false - Rake::Task.define_task("db:migrate:redo") do - Rake::Task["db:rollback"].invoke - Rake::Task["db:migrate"].invoke + describe "db:migrate" do + it "should annotate model files" do + expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models")) + Rake.application.top_level + end end - Rake.load_rakefile("annotate_rb/tasks/annotate_models_migrate.rake") + describe "db:migrate:up" do + it "should annotate model files" do + expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models")) + Rake.application.top_level + end + end - Rake.application.instance_variable_set(:@top_level_tasks, [subject]) - end + describe "db:migrate:down" do + it "should annotate model files" do + expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models")) + Rake.application.top_level + end + end - describe "db:migrate" do - it "should annotate model files" do - expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models")) - Rake.application.top_level + describe "db:migrate:reset" do + it "should annotate model files" do + expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models")) + Rake.application.top_level + end end - end - describe "db:migrate:up" do - it "should annotate model files" do - expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models")) - Rake.application.top_level + describe "db:rollback" do + it "should annotate model files" do + expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models")) + Rake.application.top_level + end end - end - describe "db:migrate:down" do - it "should annotate model files" do - expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models")) - Rake.application.top_level + describe "db:migrate:redo" do + it "should annotate model files after all migration tasks" do + # Hooked 3 times by db:rollback, db:migrate, and db:migrate:redo tasks + expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models")).exactly(3).times + + Rake.application.top_level + end end end - describe "db:migrate:reset" do - it "should annotate model files" do - expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models")) - Rake.application.top_level + context "when skip_on_db_migrate is enabled" do + include_context "spec setup with a single database", skip_on_db_migrate: true + + describe "db:migrate" do + it "should not annotate model files" do + expect(AnnotateRb::Runner).not_to receive(:run) + Rake.application.top_level + end + end + + describe "db:migrate:up" do + it "should not annotate model files" do + expect(AnnotateRb::Runner).not_to receive(:run) + Rake.application.top_level + end end - end - describe "db:rollback" do - it "should annotate model files" do - expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models")) - Rake.application.top_level + describe "db:migrate:down" do + it "should not annotate model files" do + expect(AnnotateRb::Runner).not_to receive(:run) + Rake.application.top_level + end + end + + describe "db:migrate:reset" do + it "should not annotate model files" do + expect(AnnotateRb::Runner).not_to receive(:run) + Rake.application.top_level + end end - end - describe "db:migrate:redo" do - it "should annotate model files after all migration tasks" do - # Hooked 3 times by db:rollback, db:migrate, and db:migrate:redo tasks - expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models")).exactly(3).times + describe "db:rollback" do + it "should not annotate model files" do + expect(AnnotateRb::Runner).not_to receive(:run) + Rake.application.top_level + end + end - Rake.application.top_level + describe "db:migrate:redo" do + it "should not annotate model files" do + expect(AnnotateRb::Runner).not_to receive(:run) + Rake.application.top_level + end end end end @@ -77,49 +131,89 @@ def stub_rails(version, database_names) end allow(ActiveRecord::Tasks::DatabaseTasks).to receive(:for_each) do |databases, &block| - databases.each { |name, config| block.call(name) } + databases.each { |name, _config| block.call(name) } end end - before do - stub_rails "6.0.0", ["primary"] + shared_context "spec setup with multiple databases" do |skip_on_db_migrate: false| + before do + allow(AnnotateRb::ConfigLoader).to receive(:load_config).and_return({skip_on_db_migrate:}) - Rake.application = Rake::Application.new + stub_rails "6.0.0", ["primary"] - %w[db:migrate db:migrate:up db:migrate:down db:rollback].each do |task| - Rake::Task.define_task("#{task}:primary") - end + Rake.application = Rake::Application.new - Rake.load_rakefile("annotate_rb/tasks/annotate_models_migrate.rake") + %w[db:migrate db:migrate:up db:migrate:down db:rollback].each do |task| + Rake::Task.define_task("#{task}:primary") + end - Rake.application.instance_variable_set(:@top_level_tasks, [subject]) - end + Rake.load_rakefile("annotate_rb/tasks/annotate_models_migrate.rake") - describe "db:migrate:primary" do - it "should annotate model files" do - expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models")) - Rake.application.top_level + Rake.application.instance_variable_set(:@top_level_tasks, [subject]) end end - describe "db:migrate:up:primary" do - it "should annotate model files" do - expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models")) - Rake.application.top_level + context "when skip_on_db_migrate is disabled" do + include_context "spec setup with multiple databases", skip_on_db_migrate: false + + describe "db:migrate:primary" do + it "should annotate model files" do + expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models")) + Rake.application.top_level + end end - end - describe "db:migrate:down:primary" do - it "should annotate model files" do - expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models")) - Rake.application.top_level + describe "db:migrate:up:primary" do + it "should annotate model files" do + expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models")) + Rake.application.top_level + end + end + + describe "db:migrate:down:primary" do + it "should annotate model files" do + expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models")) + Rake.application.top_level + end + end + + describe "db:rollback:primary" do + it "should annotate model files" do + expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models")) + Rake.application.top_level + end end end - describe "db:rollback:primary" do - it "should annotate model files" do - expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models")) - Rake.application.top_level + context "when skip_on_db_migrate is enabled" do + include_context "spec setup with multiple databases", skip_on_db_migrate: true + + describe "db:migrate:primary" do + it "should not annotate model files" do + expect(AnnotateRb::Runner).not_to receive(:run) + Rake.application.top_level + end + end + + describe "db:migrate:up:primary" do + it "should not annotate model files" do + expect(AnnotateRb::Runner).not_to receive(:run) + Rake.application.top_level + end + end + + describe "db:migrate:down:primary" do + it "should not annotate model files" do + expect(AnnotateRb::Runner).not_to receive(:run) + Rake.application.top_level + end + end + + describe "db:rollback:primary" do + it "should not annotate model files" do + expect(AnnotateRb::Runner).not_to receive(:run) + Rake.application.top_level + end end end end