mirror of
https://github.com/discourse/discourse.git
synced 2024-11-24 17:15:32 +08:00
40fa96777d
This moves us away from the delayed drops pattern which was problematic on two counts. First, it uses a hardcoded "delay for" duration which may be too short for certain deployment strategies. Second, delayed drop doesn't ensure that it only runs after the latest application code has been deployed. If the migration runs and the application code fails to deploy, running the migration after "delay for" has been met will cause the application to blow up. The new strategy allows post deployment migrations to be skipped if the env `SKIP_POST_DEPLOYMENT_MIGRATIONS` is provided. ``` SKIP_POST_DEPLOYMENT_MIGRATIONS=1 rake db:migrate -> deploy app servers SKIP_POST_DEPLOYMENT_MIGRATIONS=0 rake db:migrate ``` To aid with the generation of a post deployment migration, a generator has been added. Simply run `rails generate post_migration`.
126 lines
3.0 KiB
Ruby
126 lines
3.0 KiB
Ruby
require 'rails_helper'
|
|
require_dependency 'migration/safe_migrate'
|
|
|
|
describe Migration::SafeMigrate do
|
|
before do
|
|
Migration::SafeMigrate::SafeMigration.disable_safe!
|
|
end
|
|
|
|
after do
|
|
Migration::SafeMigrate.disable!
|
|
Migration::SafeMigrate::SafeMigration.enable_safe!
|
|
end
|
|
|
|
def capture_stdout
|
|
old_stdout = $stdout
|
|
io = StringIO.new
|
|
$stdout = io
|
|
yield
|
|
io.string
|
|
ensure
|
|
$stdout = old_stdout
|
|
end
|
|
|
|
def migrate_up(path)
|
|
migrations = ActiveRecord::MigrationContext.new(path).migrations
|
|
ActiveRecord::Migrator.new(:up, migrations, migrations.first.version).run
|
|
end
|
|
|
|
it "bans all table removal" do
|
|
Migration::SafeMigrate.enable!
|
|
|
|
path = File.expand_path "#{Rails.root}/spec/fixtures/db/migrate/drop_table"
|
|
|
|
output = capture_stdout do
|
|
expect(lambda do
|
|
migrate_up(path)
|
|
end).to raise_error(StandardError)
|
|
end
|
|
|
|
expect(output).to include("rails g post_migration")
|
|
|
|
expect { User.first }.not_to raise_error
|
|
expect(User.first).not_to eq(nil)
|
|
end
|
|
|
|
it "bans all table renames" do
|
|
Migration::SafeMigrate.enable!
|
|
|
|
path = File.expand_path "#{Rails.root}/spec/fixtures/db/migrate/rename_table"
|
|
|
|
output = capture_stdout do
|
|
expect(lambda do
|
|
migrate_up(path)
|
|
end).to raise_error(StandardError)
|
|
end
|
|
|
|
expect { User.first }.not_to raise_error
|
|
expect(User.first).not_to eq(nil)
|
|
|
|
expect(output).to include("rails g post_migration")
|
|
end
|
|
|
|
it "bans all column removal" do
|
|
Migration::SafeMigrate.enable!
|
|
|
|
path = File.expand_path "#{Rails.root}/spec/fixtures/db/migrate/remove_column"
|
|
|
|
output = capture_stdout do
|
|
expect(lambda do
|
|
migrate_up(path)
|
|
end).to raise_error(StandardError)
|
|
end
|
|
|
|
expect(output).to include("rails g post_migration")
|
|
|
|
expect(User.first).not_to eq(nil)
|
|
expect { User.first.username }.not_to raise_error
|
|
end
|
|
|
|
it "bans all column renames" do
|
|
Migration::SafeMigrate.enable!
|
|
|
|
path = File.expand_path "#{Rails.root}/spec/fixtures/db/migrate/rename_column"
|
|
|
|
output = capture_stdout do
|
|
expect(lambda do
|
|
migrate_up(path)
|
|
end).to raise_error(StandardError)
|
|
end
|
|
|
|
expect(output).to include("rails g post_migration")
|
|
|
|
expect(User.first).not_to eq(nil)
|
|
expect { User.first.username }.not_to raise_error
|
|
end
|
|
|
|
it "supports being disabled" do
|
|
Migration::SafeMigrate.enable!
|
|
Migration::SafeMigrate.disable!
|
|
|
|
path = File.expand_path "#{Rails.root}/spec/fixtures/db/migrate/drop_table"
|
|
|
|
output = capture_stdout do
|
|
migrate_up(path)
|
|
end
|
|
|
|
expect(output).to include("drop_table(:users)")
|
|
end
|
|
|
|
describe 'for a post deployment migration' do
|
|
it 'should not ban unsafe migrations' do
|
|
user = Fabricate(:user)
|
|
Migration::SafeMigrate::SafeMigration.enable_safe!
|
|
|
|
path = File.expand_path "#{Rails.root}/spec/fixtures/db/post_migrate/drop_table"
|
|
|
|
output = capture_stdout do
|
|
migrate_up(path)
|
|
end
|
|
|
|
expect(output).to include("drop_table(:users)")
|
|
expect(user.reload).to eq(user)
|
|
end
|
|
end
|
|
end
|