culturecode_stagehand 0.1.4 → 0.2.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/stagehand/cache.rb +12 -0
- data/lib/stagehand/configuration.rb +6 -0
- data/lib/stagehand/{helpers.rb → database.rb} +36 -19
- data/lib/stagehand/engine.rb +3 -1
- data/lib/stagehand/key.rb +23 -0
- data/lib/stagehand/production.rb +1 -2
- data/lib/stagehand/schema/statements.rb +5 -3
- data/lib/stagehand/schema.rb +29 -18
- data/lib/stagehand/staging/auditor.rb +64 -0
- data/lib/stagehand/staging/checklist.rb +71 -49
- data/lib/stagehand/staging/synchronizer.rb +12 -0
- data/lib/stagehand/staging.rb +1 -0
- data/lib/stagehand/version.rb +1 -1
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 80028dbb24f83c131a67022d24ab3c84dc64edb7
|
4
|
+
data.tar.gz: c307e846e18fafc50f6987e9208b2dd6601d753c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8e1f6ceba25e85f6dd598b2b6ce52ca9c36e09af45ed327a7ef56a5799c8a57b2e9d76f2d8aa7d52c32783de0008c78adfc8900847127a15bea19cb6c6d76c32
|
7
|
+
data.tar.gz: d1c21179ad1014dd99208ca1936ab57306aaa76a6ecb070d3fb4306dd606649afc632f5005972388e767ebfddd5586820a917000f79690507361145dbf66c562
|
@@ -19,6 +19,12 @@ module Stagehand
|
|
19
19
|
def ghost_mode?
|
20
20
|
!!Rails.configuration.x.stagehand.ghost_mode
|
21
21
|
end
|
22
|
+
|
23
|
+
# Returns true if the production and staging connections are the same.
|
24
|
+
# Use case: Front-end devs may not have a second database set up as they are only concerned with the front end
|
25
|
+
def single_connection?
|
26
|
+
staging_connection_name == production_connection_name
|
27
|
+
end
|
22
28
|
end
|
23
29
|
|
24
30
|
# EXCEPTIONS
|
@@ -1,30 +1,24 @@
|
|
1
1
|
module Stagehand
|
2
|
-
module
|
2
|
+
module Database
|
3
3
|
extend self
|
4
4
|
|
5
|
-
|
6
|
-
case staging_record
|
7
|
-
when Staging::CommitEntry
|
8
|
-
id = staging_record.record_id || staging_record.id
|
9
|
-
table_name = staging_record.table_name || staging_record.class.table_name
|
10
|
-
when ActiveRecord::Base
|
11
|
-
id = staging_record.id
|
12
|
-
table_name = staging_record.class.table_name
|
13
|
-
else
|
14
|
-
id = staging_record
|
15
|
-
table_name = options[:table_name]
|
16
|
-
end
|
5
|
+
@@connection_name_stack = [Rails.env.to_sym]
|
17
6
|
|
18
|
-
|
7
|
+
def connected_to_production?
|
8
|
+
current_connection_name == Configuration.production_connection_name
|
9
|
+
end
|
19
10
|
|
20
|
-
|
11
|
+
def connected_to_staging?
|
12
|
+
current_connection_name == Configuration.staging_connection_name
|
21
13
|
end
|
22
|
-
end
|
23
14
|
|
24
|
-
|
25
|
-
|
15
|
+
def staging_connection
|
16
|
+
StagingProbe.connection
|
17
|
+
end
|
26
18
|
|
27
|
-
|
19
|
+
def production_connection
|
20
|
+
ProductionProbe.connection
|
21
|
+
end
|
28
22
|
|
29
23
|
def with_connection(connection_name)
|
30
24
|
different = !Configuration.ghost_mode? && current_connection_name != connection_name.to_sym
|
@@ -53,5 +47,28 @@ module Stagehand
|
|
53
47
|
def current_connection_name
|
54
48
|
@@connection_name_stack.last
|
55
49
|
end
|
50
|
+
|
51
|
+
|
52
|
+
# CLASSES
|
53
|
+
|
54
|
+
class StagingProbe < ActiveRecord::Base
|
55
|
+
self.abstract_class = true
|
56
|
+
|
57
|
+
def self.init_connection
|
58
|
+
establish_connection(Configuration.staging_connection_name)
|
59
|
+
end
|
60
|
+
|
61
|
+
init_connection
|
62
|
+
end
|
63
|
+
|
64
|
+
class ProductionProbe < ActiveRecord::Base
|
65
|
+
self.abstract_class = true
|
66
|
+
|
67
|
+
def self.init_connection
|
68
|
+
establish_connection(Configuration.production_connection_name)
|
69
|
+
end
|
70
|
+
|
71
|
+
init_connection
|
72
|
+
end
|
56
73
|
end
|
57
74
|
end
|
data/lib/stagehand/engine.rb
CHANGED
@@ -9,11 +9,13 @@ module Stagehand
|
|
9
9
|
# These require the rails application to be intialized because configuration variables are used
|
10
10
|
initializer "stagehand.load_modules" do
|
11
11
|
require "stagehand/configuration"
|
12
|
+
require "stagehand/cache"
|
13
|
+
require "stagehand/key"
|
14
|
+
require "stagehand/database"
|
12
15
|
require "stagehand/controller_extensions"
|
13
16
|
require "stagehand/staging"
|
14
17
|
require "stagehand/schema"
|
15
18
|
require "stagehand/production"
|
16
|
-
require "stagehand/helpers"
|
17
19
|
end
|
18
20
|
end
|
19
21
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Stagehand
|
2
|
+
module Key
|
3
|
+
extend self
|
4
|
+
|
5
|
+
def generate(staging_record, options = {})
|
6
|
+
case staging_record
|
7
|
+
when Staging::CommitEntry
|
8
|
+
id = staging_record.record_id || staging_record.id
|
9
|
+
table_name = staging_record.table_name || staging_record.class.table_name
|
10
|
+
when ActiveRecord::Base
|
11
|
+
id = staging_record.id
|
12
|
+
table_name = staging_record.class.table_name
|
13
|
+
else
|
14
|
+
id = staging_record
|
15
|
+
table_name = options[:table_name]
|
16
|
+
end
|
17
|
+
|
18
|
+
raise 'Invalid input' unless table_name && id
|
19
|
+
|
20
|
+
return [table_name, id]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/stagehand/production.rb
CHANGED
@@ -56,7 +56,6 @@ module Stagehand
|
|
56
56
|
|
57
57
|
def prepare_to_modify(table_name)
|
58
58
|
raise "Can't prepare to modify production records without knowning the table_name" unless table_name.present?
|
59
|
-
Record.establish_connection(Configuration.production_connection_name) and @connection_established = true unless @connection_established
|
60
59
|
Record.table_name = table_name
|
61
60
|
end
|
62
61
|
|
@@ -71,7 +70,7 @@ module Stagehand
|
|
71
70
|
|
72
71
|
# CLASSES
|
73
72
|
|
74
|
-
class Record <
|
73
|
+
class Record < Stagehand::Database::ProductionProbe
|
75
74
|
self.record_timestamps = false
|
76
75
|
end
|
77
76
|
end
|
@@ -5,9 +5,11 @@ module Stagehand
|
|
5
5
|
def create_table(table_name, options = {})
|
6
6
|
super
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
return if options.symbolize_keys[:stagehand] == false
|
9
|
+
return if UNTRACKED_TABLES.include?(table_name)
|
10
|
+
return if Database.connected_to_production?
|
11
|
+
|
12
|
+
Schema.add_stagehand! :only => table_name
|
11
13
|
end
|
12
14
|
end
|
13
15
|
end
|
data/lib/stagehand/schema.rb
CHANGED
@@ -2,9 +2,11 @@ require "stagehand/schema/statements"
|
|
2
2
|
|
3
3
|
module Stagehand
|
4
4
|
module Schema
|
5
|
+
extend self
|
6
|
+
|
5
7
|
UNTRACKED_TABLES = ['schema_migrations', Stagehand::Staging::CommitEntry.table_name]
|
6
8
|
|
7
|
-
def
|
9
|
+
def init_stagehand!(options = {})
|
8
10
|
ActiveRecord::Schema.define do
|
9
11
|
create_table :stagehand_commit_entries do |t|
|
10
12
|
t.integer :record_id
|
@@ -28,44 +30,49 @@ module Stagehand
|
|
28
30
|
add_stagehand!(options)
|
29
31
|
end
|
30
32
|
|
31
|
-
def
|
33
|
+
def add_stagehand!(options = {})
|
32
34
|
ActiveRecord::Schema.define do
|
33
|
-
|
34
35
|
table_names = ActiveRecord::Base.connection.tables
|
35
36
|
table_names -= UNTRACKED_TABLES
|
36
37
|
table_names -= Array(options[:except]).collect(&:to_s)
|
37
38
|
table_names &= Array(options[:only]).collect(&:to_s) if options[:only].present?
|
38
39
|
|
39
40
|
table_names.each do |table_name|
|
40
|
-
Stagehand::Schema.
|
41
|
-
Stagehand::Schema.
|
42
|
-
Stagehand::Schema.
|
43
|
-
|
44
|
-
Stagehand::Schema.create_trigger(table_name, 'insert', 'NEW')
|
45
|
-
Stagehand::Schema.create_trigger(table_name, 'update', 'NEW')
|
46
|
-
Stagehand::Schema.create_trigger(table_name, 'delete', 'OLD')
|
41
|
+
Stagehand::Schema.send :create_trigger, table_name, 'insert', 'NEW'
|
42
|
+
Stagehand::Schema.send :create_trigger, table_name, 'update', 'NEW'
|
43
|
+
Stagehand::Schema.send :create_trigger, table_name, 'delete', 'OLD'
|
47
44
|
end
|
48
45
|
end
|
49
46
|
end
|
50
47
|
|
51
|
-
def
|
48
|
+
def remove_stagehand!(options = {})
|
52
49
|
ActiveRecord::Schema.define do
|
53
50
|
table_names = ActiveRecord::Base.connection.tables
|
54
51
|
table_names &= Array(options[:only]).collect(&:to_s) if options[:only].present?
|
55
52
|
|
56
53
|
table_names.each do |table_name|
|
57
|
-
Stagehand::Schema.drop_trigger
|
58
|
-
Stagehand::Schema.drop_trigger
|
59
|
-
Stagehand::Schema.drop_trigger
|
54
|
+
Stagehand::Schema.send :drop_trigger, table_name, 'insert'
|
55
|
+
Stagehand::Schema.send :drop_trigger, table_name, 'update'
|
56
|
+
Stagehand::Schema.send :drop_trigger, table_name, 'delete'
|
60
57
|
end
|
61
58
|
|
62
59
|
drop_table :stagehand_commit_entries unless options[:only].present?
|
63
60
|
end
|
64
61
|
end
|
65
62
|
|
63
|
+
def has_stagehand?(table_name = nil)
|
64
|
+
if table_name
|
65
|
+
trigger_exists?(table_name, 'insert')
|
66
|
+
else
|
67
|
+
ActiveRecord::Base.Connection.table_exists?(Stagehand::Staging::CommitEntry.table_name)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
66
71
|
private
|
67
72
|
|
68
|
-
def
|
73
|
+
def create_trigger(table_name, trigger_action, record)
|
74
|
+
return if trigger_exists?(table_name, trigger_action)
|
75
|
+
|
69
76
|
ActiveRecord::Base.connection.execute("
|
70
77
|
CREATE TRIGGER #{trigger_name(table_name, trigger_action)} AFTER #{trigger_action.upcase} ON #{table_name}
|
71
78
|
FOR EACH ROW
|
@@ -76,12 +83,16 @@ module Stagehand
|
|
76
83
|
")
|
77
84
|
end
|
78
85
|
|
79
|
-
def
|
86
|
+
def drop_trigger(table_name, trigger_action)
|
80
87
|
ActiveRecord::Base.connection.execute("DROP TRIGGER IF EXISTS #{trigger_name(table_name, trigger_action)};")
|
81
88
|
end
|
82
89
|
|
83
|
-
def
|
84
|
-
"
|
90
|
+
def trigger_exists?(table_name, trigger_action)
|
91
|
+
ActiveRecord::Base.connection.select_one("SHOW TRIGGERS where `trigger` = '#{trigger_name(table_name, trigger_action)}'").present?
|
92
|
+
end
|
93
|
+
|
94
|
+
def trigger_name(table_name, trigger_action)
|
95
|
+
"stagehand_#{trigger_action}_trigger_#{table_name}".downcase
|
85
96
|
end
|
86
97
|
end
|
87
98
|
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Stagehand
|
2
|
+
module Staging
|
3
|
+
module Auditor
|
4
|
+
extend self
|
5
|
+
|
6
|
+
def incomplete_commits
|
7
|
+
incomplete = []
|
8
|
+
|
9
|
+
incomplete_start_operations.each do |start_operation|
|
10
|
+
entries = records_until_match(start_operation, :asc, :operation => CommitEntry::START_OPERATION).to_a
|
11
|
+
incomplete << [start_operation.id, entries]
|
12
|
+
end
|
13
|
+
|
14
|
+
incomplete_end_operations.each do |end_operation|
|
15
|
+
entries = records_through_match(end_operation, :desc, :operation => CommitEntry::START_OPERATION).to_a
|
16
|
+
incomplete << [entries.last.id, entries]
|
17
|
+
end
|
18
|
+
|
19
|
+
return incomplete.to_h
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
# Incomplete End Operation that are not the last entry in their session
|
25
|
+
def incomplete_end_operations
|
26
|
+
last_entry_per_session = CommitEntry.group(:session).select('MAX(id) AS id')
|
27
|
+
return CommitEntry.uncontained.end_operations.where.not(:id => last_entry_per_session)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Incomplete Start on the same session as a subsequent start operation
|
31
|
+
def incomplete_start_operations
|
32
|
+
last_start_entry_per_session = CommitEntry.start_operations.group(:session).select('MAX(id) AS id')
|
33
|
+
return CommitEntry.uncontained.start_operations.where.not(:id => last_start_entry_per_session)
|
34
|
+
end
|
35
|
+
|
36
|
+
def records_until_match(start_entry, direction, match_attributes)
|
37
|
+
records_through_match(start_entry, direction, match_attributes)[0..-2]
|
38
|
+
end
|
39
|
+
|
40
|
+
def records_through_match(start_entry, direction, match_attributes)
|
41
|
+
last_entry = next_match(start_entry, direction, match_attributes)
|
42
|
+
return records_from(start_entry, direction).where.not("id #{exclusive_comparator(direction)} ?", last_entry)
|
43
|
+
end
|
44
|
+
|
45
|
+
def next_match(start_entry, direction, match_attributes)
|
46
|
+
records_from(start_entry, direction).where.not(:id => start_entry.id).where(match_attributes).first
|
47
|
+
end
|
48
|
+
|
49
|
+
def records_from(start_entry, direction)
|
50
|
+
scope = CommitEntry.where(:session => start_entry.session).where("id #{comparator(direction)} ?", start_entry.id)
|
51
|
+
scope = scope.reverse_order if direction == :desc
|
52
|
+
return scope
|
53
|
+
end
|
54
|
+
|
55
|
+
def comparator(direction)
|
56
|
+
exclusive_comparator(direction) + '='
|
57
|
+
end
|
58
|
+
|
59
|
+
def exclusive_comparator(direction)
|
60
|
+
direction == :asc ? '>' : '<'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -1,6 +1,9 @@
|
|
1
1
|
module Stagehand
|
2
2
|
module Staging
|
3
3
|
class Checklist
|
4
|
+
extend Cache
|
5
|
+
include Cache
|
6
|
+
|
4
7
|
def self.related_commits(commit)
|
5
8
|
Commit.find(related_commit_ids(commit))
|
6
9
|
end
|
@@ -34,10 +37,67 @@ module Stagehand
|
|
34
37
|
return related_entries
|
35
38
|
end
|
36
39
|
|
40
|
+
def self.associated_records(entries)
|
41
|
+
records = preload_records(compact_entries(entries)).select(&:record).flat_map do |entry|
|
42
|
+
associated_associations(entry.record_class).flat_map do |association|
|
43
|
+
entry.record.send(association)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
records.uniq!
|
48
|
+
records.compact!
|
49
|
+
records.select! {|record| stagehand_class?(record.class) }
|
50
|
+
|
51
|
+
return records
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns a list of entries that only includes a single entry for each record.
|
55
|
+
# The type of entry chosen prioritizes creates over updates, and deletes over creates.
|
56
|
+
def self.compact_entries(entries)
|
57
|
+
compact_entries = group_entries(entries)
|
58
|
+
compact_entries = compact_entries[:delete] + compact_entries[:insert] + compact_entries[:update]
|
59
|
+
compact_entries.uniq!(&:key)
|
60
|
+
|
61
|
+
return compact_entries
|
62
|
+
end
|
63
|
+
|
64
|
+
# Groups entries by their operation
|
65
|
+
def self.group_entries(entries)
|
66
|
+
group_entries = Hash.new {|h,k| h[k] = [] }
|
67
|
+
group_entries.merge! entries.group_by(&:operation).symbolize_keys!
|
68
|
+
|
69
|
+
return group_entries
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.preload_records(entries)
|
73
|
+
entries.group_by(&:table_name).each do |table_name, group_entries|
|
74
|
+
klass = CommitEntry.infer_class(table_name)
|
75
|
+
records = klass.where(:id => group_entries.collect(&:record_id))
|
76
|
+
records = records.includes(associated_associations(klass))
|
77
|
+
records_by_id = records.collect {|r| [r.id, r] }.to_h
|
78
|
+
group_entries.each do |entry|
|
79
|
+
entry.record = records_by_id[entry.record_id]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
return entries
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def self.associated_associations(klass)
|
89
|
+
cache("#{klass.name}_associated_associations") { klass.reflect_on_all_associations(:belongs_to).collect(&:name) }
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.stagehand_class?(klass)
|
93
|
+
cache("#{klass.name}_stagehand_class?") { Schema.has_stagehand?(klass.table_name) }
|
94
|
+
end
|
95
|
+
|
96
|
+
public
|
97
|
+
|
37
98
|
def initialize(subject, &confirmation_filter)
|
38
99
|
@subject = subject
|
39
100
|
@confirmation_filter = confirmation_filter
|
40
|
-
@cache = {}
|
41
101
|
affected_entries # Init the affected_entries changes can be rolled back without affecting the checklist
|
42
102
|
end
|
43
103
|
|
@@ -64,7 +124,7 @@ module Stagehand
|
|
64
124
|
end
|
65
125
|
|
66
126
|
def syncing_entries
|
67
|
-
cache(:syncing_entries) { compact_entries(affected_entries) }
|
127
|
+
cache(:syncing_entries) { self.class.compact_entries(affected_entries) }
|
68
128
|
end
|
69
129
|
|
70
130
|
def affected_records
|
@@ -72,7 +132,13 @@ module Stagehand
|
|
72
132
|
end
|
73
133
|
|
74
134
|
def affected_entries
|
75
|
-
cache(:affected_entries)
|
135
|
+
cache(:affected_entries) do
|
136
|
+
related = self.class.related_entries(@subject)
|
137
|
+
associated = self.class.associated_records(related)
|
138
|
+
associated_related = self.class.related_entries(associated)
|
139
|
+
|
140
|
+
related + associated_related
|
141
|
+
end
|
76
142
|
end
|
77
143
|
|
78
144
|
private
|
@@ -89,59 +155,15 @@ module Stagehand
|
|
89
155
|
# Don't need to confirm entries that were not part of a commit
|
90
156
|
entries = entries.select(&:commit_id)
|
91
157
|
|
92
|
-
entries = compact_entries(entries)
|
93
|
-
entries = preload_records(entries)
|
158
|
+
entries = self.class.compact_entries(entries)
|
94
159
|
entries = filter_entries(entries)
|
95
|
-
entries = group_entries(entries)
|
160
|
+
entries = self.class.group_entries(entries)
|
96
161
|
end
|
97
162
|
end
|
98
163
|
|
99
164
|
def filter_entries(entries)
|
100
165
|
@confirmation_filter ? entries.select {|entry| @confirmation_filter.call(entry.record) } : entries
|
101
166
|
end
|
102
|
-
|
103
|
-
# Returns a list of entries that only includes a single entry for each record.
|
104
|
-
# The type of entry chosen prioritizes creates over updates, and deletes over creates.
|
105
|
-
def compact_entries(entries)
|
106
|
-
compact_entries = group_entries(entries)
|
107
|
-
compact_entries = compact_entries[:delete] + compact_entries[:insert] + compact_entries[:update]
|
108
|
-
compact_entries.uniq!(&:key)
|
109
|
-
|
110
|
-
return compact_entries
|
111
|
-
end
|
112
|
-
|
113
|
-
# Groups entries by their operation
|
114
|
-
def group_entries(entries)
|
115
|
-
group_entries = Hash.new {|h,k| h[k] = [] }
|
116
|
-
group_entries.merge! entries.group_by(&:operation).symbolize_keys!
|
117
|
-
|
118
|
-
return group_entries
|
119
|
-
end
|
120
|
-
|
121
|
-
def preload_records(entries)
|
122
|
-
entries.group_by(&:table_name).each do |table_name, group_entries|
|
123
|
-
klass = CommitEntry.infer_class(table_name)
|
124
|
-
records = klass.where(:id => group_entries.collect(&:record_id))
|
125
|
-
records_by_id = records.collect {|r| [r.id, r] }.to_h
|
126
|
-
group_entries.each do |entry|
|
127
|
-
entry.record = records_by_id[entry.record_id]
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
return entries
|
132
|
-
end
|
133
|
-
|
134
|
-
def cache(key, &block)
|
135
|
-
if @cache.key?(key)
|
136
|
-
@cache[key]
|
137
|
-
else
|
138
|
-
@cache[key] = block.call
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
def clear_cache
|
143
|
-
@cache.clear
|
144
|
-
end
|
145
167
|
end
|
146
168
|
end
|
147
169
|
end
|
@@ -40,6 +40,10 @@ module Stagehand
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def sync_entries(entries)
|
43
|
+
return 0 if Configuration.single_connection? # Avoid deadlocking if the databases are the same
|
44
|
+
|
45
|
+
raise SchemaMismatch unless schemas_match?
|
46
|
+
|
43
47
|
ActiveRecord::Base.transaction do
|
44
48
|
entries.each do |entry|
|
45
49
|
Rails.logger.info "Synchronizing #{entry.table_name} #{entry.record_id}"
|
@@ -62,10 +66,18 @@ module Stagehand
|
|
62
66
|
CommitEntry.select('MAX(id) AS id').content_operations.not_in_progress.group('record_id, table_name').having('count(commit_id) = 0'))
|
63
67
|
end
|
64
68
|
end
|
69
|
+
|
70
|
+
def schemas_match?
|
71
|
+
versions_scope = ActiveRecord::SchemaMigration.order(:version)
|
72
|
+
staging_versions = Stagehand::Database.staging_connection.select_values(versions_scope)
|
73
|
+
production_versions = Stagehand::Database.production_connection.select_values(versions_scope)
|
74
|
+
return staging_versions == production_versions
|
75
|
+
end
|
65
76
|
end
|
66
77
|
end
|
67
78
|
|
68
79
|
# EXCEPTIONS
|
69
80
|
|
70
81
|
class SyncBlockRequired < StandardError; end
|
82
|
+
class SchemaMismatch < StandardError; end
|
71
83
|
end
|
data/lib/stagehand/staging.rb
CHANGED
data/lib/stagehand/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: culturecode_stagehand
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nicholas Jakobsen
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-04-
|
12
|
+
date: 2016-04-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -67,15 +67,18 @@ files:
|
|
67
67
|
- Rakefile
|
68
68
|
- lib/culturecode_stagehand.rb
|
69
69
|
- lib/stagehand.rb
|
70
|
+
- lib/stagehand/cache.rb
|
70
71
|
- lib/stagehand/configuration.rb
|
71
72
|
- lib/stagehand/controller_extensions.rb
|
73
|
+
- lib/stagehand/database.rb
|
72
74
|
- lib/stagehand/engine.rb
|
73
|
-
- lib/stagehand/
|
75
|
+
- lib/stagehand/key.rb
|
74
76
|
- lib/stagehand/production.rb
|
75
77
|
- lib/stagehand/production/controller.rb
|
76
78
|
- lib/stagehand/schema.rb
|
77
79
|
- lib/stagehand/schema/statements.rb
|
78
80
|
- lib/stagehand/staging.rb
|
81
|
+
- lib/stagehand/staging/auditor.rb
|
79
82
|
- lib/stagehand/staging/checklist.rb
|
80
83
|
- lib/stagehand/staging/commit.rb
|
81
84
|
- lib/stagehand/staging/commit_entry.rb
|