alterity 0.0.0 → 1.3.0
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 +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
|