alterity 0.0.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/alterity.rb +92 -1
- data/lib/alterity/configuration.rb +50 -0
- data/lib/alterity/default_configuration.rb +15 -0
- data/lib/alterity/mysql_client_additions.rb +13 -0
- data/lib/alterity/railtie.rb +30 -0
- data/lib/alterity/version.rb +2 -2
- data/spec/alterity_spec.rb +55 -1
- data/spec/bin/custom_config.rb +26 -0
- data/spec/bin/rails_app_migration_test.sh +71 -0
- data/spec/bin/test_custom_config_result.rb +20 -0
- data/spec/spec_helper.rb +4 -0
- metadata +18 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: af06f20537df45280990abc9fd8c2235741b6aa22de270bbcb06684f80994d46
|
4
|
+
data.tar.gz: b345349594c6408775596e9189ca494671168f9b2acfecaeb9352aaa52d1b4b8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6d012764dfd32b2002ce51f6c94b9d8cc83836e947211bb7271166c674f19ba8f61f6683fcab6a8d30cd9668103d2abc4a73477105a35004a1af662aa13612b9
|
7
|
+
data.tar.gz: a094fff01bebad3fee84a8391918105f5f5f0c0b0707d8b935ef05b378b27f667751b601addfe77657b14ac48c428230d9cda4e76a34ad0e206b4d961d7812b2
|
data/lib/alterity.rb
CHANGED
@@ -1,4 +1,95 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require "rails"
|
4
|
+
require "alterity/configuration"
|
5
|
+
require "alterity/mysql_client_additions"
|
6
|
+
require "alterity/railtie"
|
7
|
+
|
8
|
+
class Alterity
|
9
|
+
class << self
|
10
|
+
def process_sql_query(sql, &block)
|
11
|
+
case sql.tr("\n", " ").strip
|
12
|
+
when /^alter\s+table\s+(?<table>.+?)\s+(?<updates>.+)/i
|
13
|
+
table = $~[:table]
|
14
|
+
updates = $~[:updates]
|
15
|
+
if updates.split(",").all? { |s| s =~ /^\s*drop\s+foreign\s+key/i } ||
|
16
|
+
updates.split(",").all? { |s| s =~ /^\s*add\s+constraint/i }
|
17
|
+
block.call
|
18
|
+
elsif updates =~ /drop\s+foreign\s+key/i || updates =~ /add\s+constraint/i
|
19
|
+
# ADD CONSTRAINT / DROP FOREIGN KEY have to go to the original table,
|
20
|
+
# other alterations need to got to the new table.
|
21
|
+
raise "[Alterity] Can't change a FK and do something else in the same query. Split it."
|
22
|
+
else
|
23
|
+
execute_alter(table, updates)
|
24
|
+
end
|
25
|
+
when /^create\s+index\s+(?<index>.+?)\s+on\s+(?<table>.+?)\s+(?<updates>.+)/i
|
26
|
+
execute_alter($~[:table], "ADD INDEX #{$~[:index]} #{$~[:updates]}")
|
27
|
+
when /^create\s+unique\s+index\s+(?<index>.+?)\s+on\s+(?<table>.+?)\s+(?<updates>.+)/i
|
28
|
+
execute_alter($~[:table], "ADD UNIQUE INDEX #{$~[:index]} #{$~[:updates]}")
|
29
|
+
when /^drop\s+index\s+(?<index>.+?)\s+on\s+(?<table>.+)/i
|
30
|
+
execute_alter($~[:table], "DROP INDEX #{$~[:index]}")
|
31
|
+
else
|
32
|
+
block.call
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# hooks
|
37
|
+
def before_running_migrations
|
38
|
+
state.migrating = true
|
39
|
+
set_database_config
|
40
|
+
prepare_replicas_dsns_table
|
41
|
+
end
|
42
|
+
|
43
|
+
def after_running_migrations
|
44
|
+
state.migrating = false
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def execute_alter(table, updates)
|
50
|
+
altered_table = table.delete("`")
|
51
|
+
alter_argument = %("#{updates.gsub('"', '\\"').gsub('`', '\\\`')}")
|
52
|
+
prepared_command = config.command.call(altered_table, alter_argument).to_s.gsub(/\n/, "\\\n")
|
53
|
+
puts "[Alterity] Will execute: #{prepared_command}"
|
54
|
+
system(prepared_command) || raise("[Alterity] Command failed")
|
55
|
+
end
|
56
|
+
|
57
|
+
def set_database_config
|
58
|
+
db_config_hash = ActiveRecord::Base.connection_db_config.configuration_hash
|
59
|
+
%i[host port database username password].each do |key|
|
60
|
+
config[key] = db_config_hash[key]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Optional: Automatically set up table PT-OSC will monitor for replica lag.
|
65
|
+
def prepare_replicas_dsns_table
|
66
|
+
return if config.replicas_dsns_table.blank?
|
67
|
+
|
68
|
+
dsns = config.replicas_dsns.dup
|
69
|
+
# Automatically remove master
|
70
|
+
dsns.reject! { |dsn| dsn.split(",").include?("h=#{config.host}") }
|
71
|
+
|
72
|
+
database = config.replicas_dsns_database
|
73
|
+
table = "#{database}.#{config.replicas_dsns_table}"
|
74
|
+
connection = ActiveRecord::Base.connection
|
75
|
+
connection.execute "CREATE DATABASE IF NOT EXISTS #{database}"
|
76
|
+
connection.execute <<~SQL
|
77
|
+
CREATE TABLE IF NOT EXISTS #{table} (
|
78
|
+
id INT(11) NOT NULL AUTO_INCREMENT,
|
79
|
+
parent_id INT(11) DEFAULT NULL,
|
80
|
+
dsn VARCHAR(255) NOT NULL,
|
81
|
+
PRIMARY KEY (id)
|
82
|
+
) ENGINE=InnoDB
|
83
|
+
SQL
|
84
|
+
connection.execute "TRUNCATE #{table}"
|
85
|
+
return if dsns.empty?
|
86
|
+
|
87
|
+
connection.execute <<~SQL
|
88
|
+
INSERT INTO #{table} (dsn) VALUES
|
89
|
+
#{dsns.map { |dsn| "('#{dsn}')" }.join(',')}
|
90
|
+
SQL
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
reset_state_and_configuration
|
4
95
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Alterity
|
4
|
+
Configuration = Struct.new(
|
5
|
+
:command,
|
6
|
+
:host, :port, :database, :username, :password,
|
7
|
+
:replicas_dsns_database, :replicas_dsns_table, :replicas_dsns
|
8
|
+
)
|
9
|
+
CurrentState = Struct.new(:migrating, :disabled)
|
10
|
+
cattr_accessor :state
|
11
|
+
cattr_accessor :config
|
12
|
+
|
13
|
+
class << self
|
14
|
+
def reset_state_and_configuration
|
15
|
+
self.config = Configuration.new
|
16
|
+
class << config
|
17
|
+
def replicas(database:, table:, dsns:)
|
18
|
+
return ArgumentError.new("database & table must be present") if database.blank? || table.blank?
|
19
|
+
|
20
|
+
self.replicas_dsns_database = database
|
21
|
+
self.replicas_dsns_table = table
|
22
|
+
self.replicas_dsns = dsns.uniq.map do |dsn|
|
23
|
+
parts = dsn.split(",")
|
24
|
+
# automatically add default port
|
25
|
+
parts << "P=3306" unless parts.any? { |part| part.start_with?("P=") }
|
26
|
+
parts.join(",")
|
27
|
+
end.compact
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
self.state = CurrentState.new
|
32
|
+
load "#{__dir__}/default_configuration.rb"
|
33
|
+
end
|
34
|
+
|
35
|
+
def configure
|
36
|
+
yield config
|
37
|
+
end
|
38
|
+
|
39
|
+
def command=(new_command)
|
40
|
+
config.command = new_command
|
41
|
+
end
|
42
|
+
|
43
|
+
def disable
|
44
|
+
state.disabled = true
|
45
|
+
yield
|
46
|
+
ensure
|
47
|
+
state.disabled = false
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Alterity.configure do |config|
|
4
|
+
config.command = lambda { |altered_table, alter_argument|
|
5
|
+
parts = ["pt-online-schema-change"]
|
6
|
+
parts << %(-h "#{config.host}") if config.host.present?
|
7
|
+
parts << %(-P "#{config.port}") if config.port.present?
|
8
|
+
parts << %(-u "#{config.username}") if config.username.present?
|
9
|
+
parts << %(--password "#{config.password.gsub('"', '\\"')}") if config.password.present?
|
10
|
+
parts << "--execute"
|
11
|
+
parts << "D=#{config.database},t=#{altered_table}"
|
12
|
+
parts << "--alter #{alter_argument}"
|
13
|
+
parts.join(" ")
|
14
|
+
}
|
15
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "mysql2"
|
4
|
+
|
5
|
+
class Alterity
|
6
|
+
module MysqlClientAdditions
|
7
|
+
def query(sql, options = {})
|
8
|
+
return super(sql, options) unless Alterity.state.migrating
|
9
|
+
|
10
|
+
Alterity.process_sql_query(sql) { super(sql, options) }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Alterity
|
4
|
+
class Railtie < Rails::Railtie
|
5
|
+
railtie_name :alterity
|
6
|
+
|
7
|
+
rake_tasks do
|
8
|
+
namespace :alterity do
|
9
|
+
task :intercept_table_alterations do
|
10
|
+
Alterity.before_running_migrations
|
11
|
+
Rake::Task["alterity:stop_intercepting_table_alterations"].reenable
|
12
|
+
::Mysql2::Client.prepend(Alterity::MysqlClientAdditions)
|
13
|
+
end
|
14
|
+
|
15
|
+
task :stop_intercepting_table_alterations do
|
16
|
+
Rake::Task["alterity:intercept_table_alterations"].reenable
|
17
|
+
Alterity.after_running_migrations
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
unless %w[1 true].include?(ENV["DISABLE_ALTERITY"])
|
22
|
+
["migrate", "migrate:up", "migrate:down", "migrate:redo", "rollback"].each do |task|
|
23
|
+
Rake::Task["db:#{task}"].enhance(["alterity:intercept_table_alterations"]) do
|
24
|
+
Rake::Task["alterity:stop_intercepting_table_alterations"].invoke
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/alterity/version.rb
CHANGED
data/spec/alterity_spec.rb
CHANGED
@@ -1,5 +1,59 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
RSpec.describe Alterity do
|
4
|
-
|
4
|
+
describe ".process_sql_query" do
|
5
|
+
it "executes command on table altering queries" do
|
6
|
+
[
|
7
|
+
["ALTER TABLE `users` ADD `col` VARCHAR(255)", "`users`", "ADD `col` VARCHAR(255)"],
|
8
|
+
["ALTER TABLE `users` ADD `col0` INT(11), DROP `col1`", "`users`", "ADD `col0` INT(11), DROP `col1`"],
|
9
|
+
["CREATE INDEX `idx_users_on_col` ON `users` (col)", "`users`", "ADD INDEX `idx_users_on_col` (col)"],
|
10
|
+
["CREATE UNIQUE INDEX `idx_users_on_col` ON `users` (col)", "`users`", "ADD UNIQUE INDEX `idx_users_on_col` (col)"],
|
11
|
+
["DROP INDEX `idx_users_on_col` ON `users`", "`users`", "DROP INDEX `idx_users_on_col`"],
|
12
|
+
["alter table users drop col", "users", "drop col"],
|
13
|
+
[" ALTER TABLE\n users\n DROP col", "users", "DROP col"],
|
14
|
+
].each do |(query, expected_table, expected_updates)|
|
15
|
+
puts query.inspect
|
16
|
+
expected_block = proc {}
|
17
|
+
expect(expected_block).not_to receive(:call)
|
18
|
+
expect(Alterity).to receive(:execute_alter).with(expected_table, expected_updates)
|
19
|
+
Alterity.process_sql_query(query, &expected_block)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it "ignores non-altering queries" do
|
24
|
+
[
|
25
|
+
"select * from users",
|
26
|
+
"insert into users values (1)",
|
27
|
+
"delete from users",
|
28
|
+
"begin",
|
29
|
+
"SHOW CREATE TABLE `users`",
|
30
|
+
"SHOW TABLE STATUS LIKE `users`",
|
31
|
+
"SHOW KEYS FROM `users`",
|
32
|
+
"SHOW FULL FIELDS FROM `users`",
|
33
|
+
"ALTER TABLE `installment_events` DROP FOREIGN KEY _fk_rails_0123456789",
|
34
|
+
"ALTER TABLE `installment_events` DROP FOREIGN KEY _fk_rails_0123456789, DROP FOREIGN KEY _fk_rails_9876543210",
|
35
|
+
"ALTER TABLE `installment_events` ADD CONSTRAINT `fk_rails_0cb5590091` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)",
|
36
|
+
"ALTER TABLE `installment_events` ADD CONSTRAINT `fk_rails_0cb5590091` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE",
|
37
|
+
].each do |query|
|
38
|
+
expected_block = proc {}
|
39
|
+
expect(expected_block).to receive(:call)
|
40
|
+
expect(Alterity).not_to receive(:execute_alter)
|
41
|
+
Alterity.process_sql_query(query, &expected_block)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
it "raises an error if mixing FK change and other things" do
|
46
|
+
expected_block = proc {}
|
47
|
+
expect(expected_block).not_to receive(:call)
|
48
|
+
expect(Alterity).not_to receive(:execute_alter)
|
49
|
+
query = "ALTER TABLE `installment_events` ADD `col` VARCHAR(255), DROP FOREIGN KEY _fk_rails_0123456789"
|
50
|
+
expect do
|
51
|
+
Alterity.process_sql_query(query, &expected_block)
|
52
|
+
end.to raise_error(/FK/)
|
53
|
+
query = "ALTER TABLE `installment_events` ADD `col` VARCHAR(255), ADD CONSTRAINT `fk_rails_0cb5590091` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)"
|
54
|
+
expect do
|
55
|
+
Alterity.process_sql_query(query, &expected_block)
|
56
|
+
end.to raise_error(/FK/)
|
57
|
+
end
|
58
|
+
end
|
5
59
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Alterity.configure do |config|
|
4
|
+
config.command = lambda { |altered_table, alter_argument|
|
5
|
+
string = config.to_h.slice(
|
6
|
+
*%i[host port username database replicas_dsns_database replicas_dsns_table replicas_dsns]
|
7
|
+
).to_s
|
8
|
+
system("echo '#{string}' > /tmp/custom_command_result.txt")
|
9
|
+
system("echo '#{altered_table}' >> /tmp/custom_command_result.txt")
|
10
|
+
system("echo '#{alter_argument}' >> /tmp/custom_command_result.txt")
|
11
|
+
}
|
12
|
+
|
13
|
+
config.replicas(
|
14
|
+
database: "percona",
|
15
|
+
table: "replicas_dsns",
|
16
|
+
dsns: [
|
17
|
+
"h=host1",
|
18
|
+
"h=host2",
|
19
|
+
# we may encounter an app where the replica host is actually pointing to master;
|
20
|
+
# pt-osc doesn't deal well with this and will wait forever.
|
21
|
+
# So we're testing here that Alterity will detect that this is master (same as config.host),
|
22
|
+
# and will not insert it into the `replicas_dsns` table.
|
23
|
+
"h=#{ENV['MYSQL_HOST']}"
|
24
|
+
]
|
25
|
+
)
|
26
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
set -euox pipefail
|
4
|
+
|
5
|
+
unset BUNDLE_GEMFILE # because we're going to create a new rails app here and use bundler
|
6
|
+
|
7
|
+
sudo apt install percona-toolkit
|
8
|
+
|
9
|
+
# Fixes: `Cannot connect to MySQL: Cannot get MySQL var character_set_server: DBD::mysql::db selectrow_array failed: Table 'performance_schema.session_variables' doesn't exist [for Statement "SHOW VARIABLES LIKE 'character_set_server'"] at /usr/local/Cellar/percona-toolkit/3.3.0/libexec/bin/pt-online-schema-change line 2415.`
|
10
|
+
mysql -h $MYSQL_HOST -u $MYSQL_USERNAME -e 'set @@global.show_compatibility_56=ON'
|
11
|
+
|
12
|
+
gem install rails -v $RAILS_VERSION
|
13
|
+
|
14
|
+
rails new testapp \
|
15
|
+
--skip-action-mailer \
|
16
|
+
--skip-action-mailbox \
|
17
|
+
--skip-action-text \
|
18
|
+
--skip-active-job \
|
19
|
+
--skip-active-storage \
|
20
|
+
--skip-puma \
|
21
|
+
--skip-action-cable \
|
22
|
+
--skip-sprockets \
|
23
|
+
--skip-spring \
|
24
|
+
--skip-listen--skip-javascript \
|
25
|
+
--skip-turbolinks \
|
26
|
+
--skip-jbuilder--skip-test \
|
27
|
+
--skip-system-test \
|
28
|
+
--skip-bootsnap \
|
29
|
+
--skip-javascript \
|
30
|
+
--skip-webpack-install
|
31
|
+
|
32
|
+
cd testapp
|
33
|
+
|
34
|
+
# Sanity check:
|
35
|
+
# echo 'gem "mysql2"' >> Gemfile
|
36
|
+
|
37
|
+
echo 'gem "alterity", path: "../"' >> Gemfile
|
38
|
+
|
39
|
+
bundle
|
40
|
+
|
41
|
+
# Local machine test
|
42
|
+
# echo 'development:
|
43
|
+
# adapter: mysql2
|
44
|
+
# database: alterity_test' > config/database.yml
|
45
|
+
# bundle e rails db:drop db:create
|
46
|
+
|
47
|
+
echo 'development:
|
48
|
+
adapter: mysql2
|
49
|
+
database: <%= ENV.fetch("MYSQL_DATABASE") %>
|
50
|
+
host: <%= ENV.fetch("MYSQL_HOST") %>
|
51
|
+
username: <%= ENV.fetch("MYSQL_USERNAME") %>' > config/database.yml
|
52
|
+
|
53
|
+
bundle e rails g model shirt
|
54
|
+
|
55
|
+
bundle e rails g migration add_color_to_shirts color:string
|
56
|
+
|
57
|
+
# Test default configuration works as expected
|
58
|
+
bundle e rails db:migrate --trace
|
59
|
+
bundle e rails runner 'Shirt.columns.map(&:name).include?("color") || exit(1)'
|
60
|
+
|
61
|
+
# Now test custom command and replication setup
|
62
|
+
cp ../spec/bin/custom_config.rb config/initializers/alterity.rb
|
63
|
+
|
64
|
+
bundle e rails g migration add_color2_to_shirts color2:string
|
65
|
+
|
66
|
+
bundle e rails db:migrate --trace
|
67
|
+
|
68
|
+
ruby ../spec/bin/test_custom_config_result.rb
|
69
|
+
|
70
|
+
# Also testing what's in replicas_dsns, also checking that master was detected and removed.
|
71
|
+
bundle e rails runner 'res=ActiveRecord::Base.connection.execute("select dsn from percona.replicas_dsns").to_a.flatten;p(res); res == ["h=host1,P=3306", "h=host2,P=3306"] || exit(1)'
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
result = File.read("/tmp/custom_command_result.txt").downcase.strip
|
4
|
+
|
5
|
+
expected_result = %({:host=>"127.0.0.1", :port=>nil, :username=>"root", :database=>"alterity_test", :replicas_dsns_database=>"percona", :replicas_dsns_table=>"replicas_dsns", :replicas_dsns=>["h=host1,P=3306", "h=host2,P=3306", "h=127.0.0.1,P=3306"]}
|
6
|
+
shirts
|
7
|
+
"ADD \\`color2\\` VARCHAR(255)").downcase.strip
|
8
|
+
|
9
|
+
puts "Expected custom config result:"
|
10
|
+
puts expected_result
|
11
|
+
p expected_result.chars.map(&:hex)
|
12
|
+
|
13
|
+
puts "Custom config result:"
|
14
|
+
puts result
|
15
|
+
p result.chars.map(&:hex)
|
16
|
+
|
17
|
+
if result != expected_result
|
18
|
+
puts "=> mismatch"
|
19
|
+
exit(1)
|
20
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,55 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: alterity
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Maximin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-05-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: mysql2
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
20
|
-
- - "<"
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: '8'
|
19
|
+
version: '0.3'
|
23
20
|
type: :runtime
|
24
21
|
prerelease: false
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
26
23
|
requirements:
|
27
24
|
- - ">="
|
28
25
|
- !ruby/object:Gem::Version
|
29
|
-
version: '
|
30
|
-
- - "<"
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: '8'
|
26
|
+
version: '0.3'
|
33
27
|
- !ruby/object:Gem::Dependency
|
34
|
-
name:
|
28
|
+
name: rails
|
35
29
|
requirement: !ruby/object:Gem::Requirement
|
36
30
|
requirements:
|
37
|
-
- - "~>"
|
38
|
-
- !ruby/object:Gem::Version
|
39
|
-
version: '0.5'
|
40
31
|
- - ">="
|
41
32
|
- !ruby/object:Gem::Version
|
42
|
-
version:
|
33
|
+
version: '6.1'
|
43
34
|
type: :runtime
|
44
35
|
prerelease: false
|
45
36
|
version_requirements: !ruby/object:Gem::Requirement
|
46
37
|
requirements:
|
47
|
-
- - "~>"
|
48
|
-
- !ruby/object:Gem::Version
|
49
|
-
version: '0.5'
|
50
38
|
- - ">="
|
51
39
|
- !ruby/object:Gem::Version
|
52
|
-
version:
|
40
|
+
version: '6.1'
|
53
41
|
description: Execute your ActiveRecord migrations with Percona's pt-online-schema-change.
|
54
42
|
email:
|
55
43
|
- gems@chrismaximin.com
|
@@ -58,8 +46,15 @@ extensions: []
|
|
58
46
|
extra_rdoc_files: []
|
59
47
|
files:
|
60
48
|
- lib/alterity.rb
|
49
|
+
- lib/alterity/configuration.rb
|
50
|
+
- lib/alterity/default_configuration.rb
|
51
|
+
- lib/alterity/mysql_client_additions.rb
|
52
|
+
- lib/alterity/railtie.rb
|
61
53
|
- lib/alterity/version.rb
|
62
54
|
- spec/alterity_spec.rb
|
55
|
+
- spec/bin/custom_config.rb
|
56
|
+
- spec/bin/rails_app_migration_test.sh
|
57
|
+
- spec/bin/test_custom_config_result.rb
|
63
58
|
- spec/spec_helper.rb
|
64
59
|
homepage: https://github.com/gumroad/alterity
|
65
60
|
licenses:
|
@@ -89,4 +84,7 @@ specification_version: 4
|
|
89
84
|
summary: Execute your ActiveRecord migrations with Percona's pt-online-schema-change.
|
90
85
|
test_files:
|
91
86
|
- spec/alterity_spec.rb
|
87
|
+
- spec/bin/custom_config.rb
|
88
|
+
- spec/bin/rails_app_migration_test.sh
|
89
|
+
- spec/bin/test_custom_config_result.rb
|
92
90
|
- spec/spec_helper.rb
|