aboutsummaryrefslogtreecommitdiffstats
path: root/railties
diff options
context:
space:
mode:
authorschneems <richard.schneeman@gmail.com>2015-08-14 11:31:33 -0500
committerschneems <richard.schneeman@gmail.com>2016-01-07 18:01:05 -0600
commit900bfd94a9c3c45484d88aa69071b7a52c5b04b4 (patch)
tree9f28b1f0acf2f74143ec7806bd89081430f6f306 /railties
parent89f776402dbaca581ef4bb342bb89db922124c7a (diff)
downloadrails-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.rb2
-rw-r--r--railties/test/application/loading_test.rb6
-rw-r--r--railties/test/application/rake/dbs_test.rb6
-rw-r--r--railties/test/application/rake_test.rb20
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)