migrate_safely 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e2494a037e7a7b6bd5e25eeec717e15dbed6083a
4
+ data.tar.gz: 3a6898bdaa9e22e98da53d5baa27de6ac6648578
5
+ SHA512:
6
+ metadata.gz: 76c71a3e53de068869a0fdeea418d76cf7923f392bd57b4109e221e1ed0da890fa183c4c56b3f09e5722b2d8e8b87c835799506cecde9a51eeffe74ed8363e90
7
+ data.tar.gz: 663f28a1a7fbc96d337cf2462da43fd83c1d869cb8d2d56dbd5ffdbf00360cc22cf786825ca339f5a6c41c0095fe5c2a303ec299512dd6715f8ec4217d8b0e17
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2015 Remind
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,40 @@
1
+ MigrateSafely
2
+ =============
3
+
4
+ MigrateSafely is a [railtie](http://api.rubyonrails.org/classes/Rails/Railtie.html) that
5
+ adds a confirmation prompt to the `rake db:migrate` command to prevent accidental migrations/rollbacks.
6
+
7
+ Example:
8
+
9
+ $ rake db:migrate
10
+
11
+ database: my_database
12
+
13
+ Action Migration ID Migration Name
14
+ --------------------------------------------------
15
+ apply 20150916005809 Migration1
16
+ apply 20150917011452 Migration2
17
+
18
+ Are you sure you want to proceed? [y/n]:
19
+
20
+ Accidental rollback prevention:
21
+
22
+ $ VERSION=foo20150917011452 rake db:migrate # notice the typo in VERSION
23
+
24
+ database: my_database
25
+
26
+ Action Migration ID Migration Name
27
+ --------------------------------------------------
28
+ revert 20150914175134 Migration100
29
+ revert 20150902002737 Migration099
30
+ revert 20150901221908 Migration098
31
+ revert 20150901171434 Migration097
32
+ revert 20150831194113 Migration096
33
+ ...
34
+ revert 20150101004705 Migration001
35
+
36
+ Are you sure you want to proceed? [y/n]:
37
+
38
+ ## License
39
+
40
+ [MIT License](LICENSE)
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ Bundler::GemHelper.install_tasks
8
+
9
+ require 'rake/testtask'
10
+
11
+ Rake::TestTask.new(:test) do |t|
12
+ t.libs << 'lib'
13
+ t.libs << 'test'
14
+ t.pattern = 'test/**/*_test.rb'
15
+ t.verbose = false
16
+ end
17
+
18
+
19
+ task default: :test
@@ -0,0 +1,5 @@
1
+ module MigrateSafely
2
+ end
3
+
4
+ require 'migrate_safely/migration_outliner'
5
+ require 'migrate_safely/railtie' if defined?(Rails)
@@ -0,0 +1,27 @@
1
+ module MigrateSafely
2
+ class MigrationOutliner
3
+ Action = Struct.new(:version, :action, :name)
4
+
5
+ def self.pending_actions(target_version = nil)
6
+ current_version = ActiveRecord::Migrator.current_version
7
+ return [] if current_version == 0 && target_version == 0
8
+
9
+ direction = case
10
+ when target_version.nil?
11
+ :up
12
+ when current_version > target_version
13
+ :down
14
+ else
15
+ :up
16
+ end
17
+
18
+ migrations = ActiveRecord::Migrator.migrations(ActiveRecord::Migrator.migrations_paths)
19
+ runnable_migrations = ActiveRecord::Migrator.new(direction, migrations, target_version).runnable
20
+ action = direction == :up ? "apply" : "revert"
21
+
22
+ runnable_migrations.map do |m|
23
+ Action.new(m.version, action, m.name)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,7 @@
1
+ module MigrateSafely
2
+ class Railtie < Rails::Railtie
3
+ rake_tasks do
4
+ load "migrate_safely/tasks/migrate_safely.rake"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,28 @@
1
+ namespace :migrate_safely do
2
+ task :outline => :environment do
3
+ require 'migrate_safely/migration_outliner'
4
+
5
+ version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil # to_i is intentional, replicates ActiveRecord behavior
6
+ actions = MigrateSafely::MigrationOutliner.pending_actions(version)
7
+
8
+ unless actions.any?
9
+ abort "There are no migrations to be applied or reverted"
10
+ end
11
+
12
+ puts "\ndatabase: #{ActiveRecord::Base.connection_config[:database]}\n\n"
13
+ puts "#{'Action'.center(8)} #{'Migration ID'.ljust(14)} Migration Name"
14
+ puts "-" * 50
15
+ actions.each do |action|
16
+ puts "#{action.action.center(8)} #{action.version.to_s.ljust(14)} #{action.name}"
17
+ end
18
+ puts
19
+ end
20
+
21
+ task :confirm do
22
+ print "Are you sure you want to proceed? [y/n]: "
23
+ input = STDIN.gets.chomp
24
+ abort "Aborting" unless %w(y yes yeah).include?(input.downcase)
25
+ end
26
+ end
27
+
28
+ Rake::Task["db:migrate"].enhance ["migrate_safely:outline", "migrate_safely:confirm"]
@@ -0,0 +1,3 @@
1
+ module MigrateSafely
2
+ VERSION = "0.0.1"
3
+ end
Binary file
@@ -0,0 +1,9 @@
1
+ class TestMigration1 < ActiveRecord::Migration
2
+ def self.up
3
+ puts "test migration1 applied"
4
+ end
5
+
6
+ def self.down
7
+ puts "test migration1 reverted"
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ class TestMigration2 < ActiveRecord::Migration
2
+ def self.up
3
+ puts "test migration2 applied"
4
+ end
5
+
6
+ def self.down
7
+ puts "test migration2 reverted"
8
+ end
9
+ end
10
+
@@ -0,0 +1,11 @@
1
+ class TestMigration3 < ActiveRecord::Migration
2
+ def self.up
3
+ puts "test migration3 applied"
4
+ end
5
+
6
+ def self.down
7
+ puts "test migration3 reverted"
8
+ end
9
+ end
10
+
11
+
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ class MigrateSafelyTest < ActiveSupport::TestCase
4
+ test "truth" do
5
+ assert_kind_of Module, MigrateSafely
6
+ end
7
+ end
@@ -0,0 +1,50 @@
1
+ require 'test_helper'
2
+
3
+ module MigrateSafely
4
+ class MigrationOutlinerTest < ActiveSupport::TestCase
5
+ setup do
6
+ ActiveRecord::Base.connection.begin_transaction(joinable: false)
7
+ end
8
+
9
+ teardown do
10
+ if ActiveRecord::Base.connection.transaction_open?
11
+ ActiveRecord::Base.connection.rollback_transaction
12
+ end
13
+ end
14
+
15
+ test "lists all pending migrations when version is not specified" do
16
+ pending_actions = MigrationOutliner.pending_actions
17
+ assert_equal [
18
+ MigrationOutliner::Action.new(20150918000000, "apply", "TestMigration1"),
19
+ MigrationOutliner::Action.new(20150918000001, "apply", "TestMigration2"),
20
+ MigrationOutliner::Action.new(20150918000002, "apply", "TestMigration3")
21
+ ], pending_actions
22
+ end
23
+
24
+ test "says will apply migrations up to version (inclusive) when the version is newer than current" do
25
+ pending_actions = MigrationOutliner.pending_actions(20150918000001)
26
+ assert_equal [
27
+ MigrationOutliner::Action.new(20150918000000, "apply", "TestMigration1"),
28
+ MigrationOutliner::Action.new(20150918000001, "apply", "TestMigration2")
29
+ ], pending_actions
30
+ end
31
+
32
+ test "says will revert migrations that are newer than version (not inclusive) when version is older than current" do
33
+ ActiveRecord::SchemaMigration.create!(version: "20150918000000")
34
+ ActiveRecord::SchemaMigration.create!(version: "20150918000001")
35
+
36
+ pending_actions = MigrationOutliner.pending_actions(20150918000000)
37
+ assert_equal [
38
+ MigrationOutliner::Action.new(20150918000001, "revert", "TestMigration2")
39
+ ], pending_actions
40
+ end
41
+
42
+ test "returns an empty list of actions if the version is equal to current" do
43
+ current_version = 20150918000000
44
+ ActiveRecord::SchemaMigration.create!(version: current_version.to_s)
45
+
46
+ pending_actions = MigrationOutliner.pending_actions(current_version)
47
+ assert_equal [], pending_actions
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,14 @@
1
+ FIXTURES_ROOT = File.expand_path("../fixtures", __FILE__)
2
+
3
+ require 'active_record'
4
+ require 'active_support/testing/autorun'
5
+ require 'active_support/test_case'
6
+ require 'migrate_safely'
7
+
8
+ ActiveRecord::Base.establish_connection(
9
+ adapter: "sqlite3",
10
+ database: File.join(FIXTURES_ROOT, "db.sqlite3"),
11
+ pool: 1,
12
+ timeout: 5000
13
+ )
14
+ ActiveRecord::Migrator.migrations_paths = [File.join(FIXTURES_ROOT, "migrations")]
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: migrate_safely
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Vlad Yarotsky
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-09-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 4.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 4.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: sqlite3
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Adds a confirmation prompt to rake db:migrate; Lists migrations to be
42
+ applied/reverted before proceeding.
43
+ email:
44
+ - vlad@remind101.com
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - LICENSE
50
+ - README.md
51
+ - Rakefile
52
+ - lib/migrate_safely.rb
53
+ - lib/migrate_safely/migration_outliner.rb
54
+ - lib/migrate_safely/railtie.rb
55
+ - lib/migrate_safely/tasks/migrate_safely.rake
56
+ - lib/migrate_safely/version.rb
57
+ - test/fixtures/db.sqlite3
58
+ - test/fixtures/migrations/20150918000000_test_migration_1.rb
59
+ - test/fixtures/migrations/20150918000001_test_migration_2.rb
60
+ - test/fixtures/migrations/20150918000002_test_migration_3.rb
61
+ - test/migrate_safely_test.rb
62
+ - test/migration_outliner_test.rb
63
+ - test/test_helper.rb
64
+ homepage:
65
+ licenses: []
66
+ metadata: {}
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ requirements: []
82
+ rubyforge_project:
83
+ rubygems_version: 2.4.5
84
+ signing_key:
85
+ specification_version: 4
86
+ summary: Adds a confirmation prompt to rake db:migrate
87
+ test_files:
88
+ - test/fixtures/db.sqlite3
89
+ - test/fixtures/migrations/20150918000000_test_migration_1.rb
90
+ - test/fixtures/migrations/20150918000001_test_migration_2.rb
91
+ - test/fixtures/migrations/20150918000002_test_migration_3.rb
92
+ - test/migrate_safely_test.rb
93
+ - test/migration_outliner_test.rb
94
+ - test/test_helper.rb