diff options
author | schneems <richard.schneeman@gmail.com> | 2015-08-14 11:31:33 -0500 |
---|---|---|
committer | schneems <richard.schneeman@gmail.com> | 2016-01-07 18:01:05 -0600 |
commit | 900bfd94a9c3c45484d88aa69071b7a52c5b04b4 (patch) | |
tree | 9f28b1f0acf2f74143ec7806bd89081430f6f306 /railties | |
parent | 89f776402dbaca581ef4bb342bb89db922124c7a (diff) | |
download | rails-900bfd94a9c3c45484d88aa69071b7a52c5b04b4.tar.gz rails-900bfd94a9c3c45484d88aa69071b7a52c5b04b4.tar.bz2 rails-900bfd94a9c3c45484d88aa69071b7a52c5b04b4.zip |
Prevent destructive action on production database
This PR introduces a key/value type store to Active Record that can be used for storing internal values. It is an alternative implementation to #21237 cc @sgrif @matthewd.
It is possible to run your tests against your production database by accident right now. While infrequently, but as an anecdotal data point, Heroku receives a non-trivial number of requests for a database restore due to this happening. In these cases the loss can be large.
To prevent against running tests against production we can store the "environment" version that was used when migrating the database in a new internal table. Before executing tests we can see if the database is a listed in `protected_environments` and abort. There is a manual escape valve to force this check from happening with environment variable `DISABLE_DATABASE_ENVIRONMENT_CHECK=1`.
Diffstat (limited to 'railties')
-rw-r--r-- | railties/test/application/bin_setup_test.rb | 2 | ||||
-rw-r--r-- | railties/test/application/loading_test.rb | 6 | ||||
-rw-r--r-- | railties/test/application/rake/dbs_test.rb | 6 | ||||
-rw-r--r-- | railties/test/application/rake_test.rb | 20 |
4 files changed, 27 insertions, 7 deletions
diff --git a/railties/test/application/bin_setup_test.rb b/railties/test/application/bin_setup_test.rb index 1bdced02e9..c96bbe4c70 100644 --- a/railties/test/application/bin_setup_test.rb +++ b/railties/test/application/bin_setup_test.rb @@ -28,7 +28,7 @@ module ApplicationTests assert_not File.exist?("tmp/restart.txt") `bin/setup 2>&1` assert_equal 0, File.size("log/my.log") - assert_equal '["articles", "schema_migrations"]', list_tables.call + assert_equal '["articles", "schema_migrations", "internal_metadatas"]', list_tables.call assert File.exist?("tmp/restart.txt") end end diff --git a/railties/test/application/loading_test.rb b/railties/test/application/loading_test.rb index 2cc599ca6f..40abaf860d 100644 --- a/railties/test/application/loading_test.rb +++ b/railties/test/application/loading_test.rb @@ -116,11 +116,11 @@ class LoadingTest < ActiveSupport::TestCase require "#{rails_root}/config/environment" setup_ar! - assert_equal [ActiveRecord::SchemaMigration], ActiveRecord::Base.descendants + assert_equal [ActiveRecord::SchemaMigration, ActiveRecord::InternalMetadata], ActiveRecord::Base.descendants get "/load" - assert_equal [ActiveRecord::SchemaMigration, Post], ActiveRecord::Base.descendants + assert_equal [ActiveRecord::SchemaMigration, ActiveRecord::InternalMetadata, Post], ActiveRecord::Base.descendants get "/unload" - assert_equal [ActiveRecord::SchemaMigration], ActiveRecord::Base.descendants + assert_equal [ActiveRecord::SchemaMigration, ActiveRecord::InternalMetadata], ActiveRecord::Base.descendants end test "initialize cant be called twice" do diff --git a/railties/test/application/rake/dbs_test.rb b/railties/test/application/rake/dbs_test.rb index 0b0fb50fe1..47ab65e57b 100644 --- a/railties/test/application/rake/dbs_test.rb +++ b/railties/test/application/rake/dbs_test.rb @@ -85,7 +85,7 @@ module ApplicationTests test 'db:drop failure because database does not exist' do Dir.chdir(app_path) do - output = `bin/rake db:drop 2>&1` + output = `bin/rake db:drop:_unsafe --trace 2>&1` assert_match(/does not exist/, output) assert_equal 0, $?.exitstatus end @@ -222,14 +222,14 @@ module ApplicationTests assert_equal '["posts"]', list_tables[] `bin/rake db:schema:load` - assert_equal '["posts", "comments", "schema_migrations"]', list_tables[] + assert_equal '["posts", "comments", "schema_migrations", "internal_metadatas"]', list_tables[] app_file 'db/structure.sql', <<-SQL CREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar(255)); SQL `bin/rake db:structure:load` - assert_equal '["posts", "comments", "schema_migrations", "users"]', list_tables[] + assert_equal '["posts", "comments", "schema_migrations", "internal_metadatas", "users"]', list_tables[] end end diff --git a/railties/test/application/rake_test.rb b/railties/test/application/rake_test.rb index 1d3550add9..cf4e5ddbf6 100644 --- a/railties/test/application/rake_test.rb +++ b/railties/test/application/rake_test.rb @@ -24,6 +24,26 @@ module ApplicationTests assert $task_loaded end + def test_the_test_rake_task_is_protected_when_previous_migration_was_production + Dir.chdir(app_path) do + output = `bin/rails generate model product name:string; + env RAILS_ENV=production bin/rake db:create db:migrate; + env RAILS_ENV=production bin/rake db:test:prepare test 2>&1` + + assert_match /ActiveRecord::ProtectedEnvironmentError/, output + end + end + + def test_not_protected_when_previous_migration_was_not_production + Dir.chdir(app_path) do + output = `bin/rails generate model product name:string; + env RAILS_ENV=test bin/rake db:create db:migrate; + env RAILS_ENV=test bin/rake db:test:prepare test 2>&1` + + refute_match /ActiveRecord::ProtectedEnvironmentError/, output + end + end + def test_environment_is_required_in_rake_tasks app_file "config/environment.rb", <<-RUBY SuperMiddleware = Struct.new(:app) |