duple 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.
- data/.gitignore +19 -0
- data/.rspec +2 -0
- data/.simplecov +14 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +64 -0
- data/Rakefile +21 -0
- data/bin/duple +11 -0
- data/duple.gemspec +30 -0
- data/lib/duple.rb +3 -0
- data/lib/duple/cli/config.rb +63 -0
- data/lib/duple/cli/copy.rb +29 -0
- data/lib/duple/cli/helpers.rb +192 -0
- data/lib/duple/cli/init.rb +15 -0
- data/lib/duple/cli/refresh.rb +75 -0
- data/lib/duple/cli/root.rb +41 -0
- data/lib/duple/cli/structure.rb +23 -0
- data/lib/duple/configuration.rb +203 -0
- data/lib/duple/heroku_runner.rb +25 -0
- data/lib/duple/pg_runner.rb +27 -0
- data/lib/duple/runner.rb +63 -0
- data/lib/duple/version.rb +3 -0
- data/spec/duple/cli/config_spec.rb +16 -0
- data/spec/duple/cli/copy_spec.rb +112 -0
- data/spec/duple/cli/init_spec.rb +19 -0
- data/spec/duple/cli/refresh_spec.rb +413 -0
- data/spec/duple/cli/structure_spec.rb +133 -0
- data/spec/duple/configuration_spec.rb +166 -0
- data/spec/duple/runner_spec.rb +65 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/support/cli_spec_helpers.rb +85 -0
- data/spec/support/duple.rb +5 -0
- data/spec/support/io_spec_helpers.rb +33 -0
- data/spec/support/rspec_fire.rb +0 -0
- metadata +190 -0
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Duple::CLI::Config do
|
4
|
+
it 'prints the configuration' do
|
5
|
+
result = capture_stdout do
|
6
|
+
script = Duple::CLI::Config.new
|
7
|
+
script.invoke(:all, [], {})
|
8
|
+
end
|
9
|
+
|
10
|
+
result.should =~ /Environments/
|
11
|
+
result.should =~ /Groups/
|
12
|
+
result.should =~ /Pre-Refresh Tasks/
|
13
|
+
result.should =~ /Post-Refresh Tasks/
|
14
|
+
result.should =~ /Other Options/
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Duple::CLI::Copy do
|
4
|
+
include Duple::CLISpecHelpers
|
5
|
+
|
6
|
+
def invoke_copy(options = nil)
|
7
|
+
options ||= {}
|
8
|
+
options = { tables: ['categories'] }.merge(options)
|
9
|
+
invoke_cli(:copy, options)
|
10
|
+
end
|
11
|
+
|
12
|
+
before {
|
13
|
+
stub_fetch_config
|
14
|
+
stub_dump_data
|
15
|
+
stub_restore_data
|
16
|
+
}
|
17
|
+
|
18
|
+
context 'with neither tables nor group option' do
|
19
|
+
it 'fetches the source credentials' do
|
20
|
+
expect {
|
21
|
+
invoke_copy(tables: nil)
|
22
|
+
}.to raise_error(ArgumentError, 'One of --group or --tables options is required.')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'from heroku to local' do
|
27
|
+
let(:source) { 'stage' }
|
28
|
+
let(:target) { 'development' }
|
29
|
+
|
30
|
+
it 'fetches the source credentials' do
|
31
|
+
runner.should_receive(:capture).with("heroku config -a duple-stage")
|
32
|
+
.and_return(heroku_config_response)
|
33
|
+
|
34
|
+
invoke_copy
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'dowloads the data from the source' do
|
38
|
+
runner.should_receive(:run)
|
39
|
+
.with(%{PGPASSWORD="pg-pass" pg_dump -Fc -a -t categories -h pg-host -U pg-user -p 6022 pg-db > tmp/duple/stage-data.dump})
|
40
|
+
|
41
|
+
invoke_copy
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'uploads the data to the target' do
|
45
|
+
runner.should_receive(:run)
|
46
|
+
.with(%{PGPASSWORD="" pg_restore -e -v --no-acl -O -a -h localhost -U postgres -p 5432 -d duple_development < tmp/duple/stage-data.dump})
|
47
|
+
|
48
|
+
invoke_copy
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'from heroku to heroku' do
|
53
|
+
let(:source) { 'production' }
|
54
|
+
let(:target) { 'stage' }
|
55
|
+
|
56
|
+
it 'fetches the source credentials' do
|
57
|
+
runner.should_receive(:capture).with("heroku config -a duple-production")
|
58
|
+
.and_return(heroku_config_response)
|
59
|
+
|
60
|
+
invoke_copy
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'fetches the target credentials' do
|
64
|
+
runner.should_receive(:capture).with("heroku config -a duple-stage")
|
65
|
+
.and_return(heroku_config_response)
|
66
|
+
|
67
|
+
invoke_copy
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'dowloads the data from the source' do
|
71
|
+
runner.should_receive(:run)
|
72
|
+
.with(%{PGPASSWORD="pg-pass" pg_dump -Fc -a -t categories -h pg-host -U pg-user -p 6022 pg-db > tmp/duple/production-data.dump})
|
73
|
+
|
74
|
+
invoke_copy
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'uploads the data to the target' do
|
78
|
+
runner.should_receive(:run)
|
79
|
+
.with(%{PGPASSWORD="pg-pass" pg_restore -e -v --no-acl -O -a -h pg-host -U pg-user -p 6022 -d pg-db < tmp/duple/production-data.dump})
|
80
|
+
|
81
|
+
invoke_copy
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'from local to heroku' do
|
86
|
+
let(:source) { 'development' }
|
87
|
+
let(:target) { 'stage' }
|
88
|
+
|
89
|
+
it 'fetches the target credentials' do
|
90
|
+
runner.should_receive(:capture).with("heroku config -a duple-stage")
|
91
|
+
.and_return(heroku_config_response)
|
92
|
+
|
93
|
+
invoke_copy
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'dumps the data from the local db' do
|
97
|
+
stub_fetch_config
|
98
|
+
runner.should_receive(:run)
|
99
|
+
.with(%{PGPASSWORD="" pg_dump -Fc -a -t categories -h localhost -U postgres -p 5432 duple_development > tmp/duple/development-data.dump})
|
100
|
+
stub_restore_data
|
101
|
+
|
102
|
+
invoke_copy
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'uploads the data to the target' do
|
106
|
+
runner.should_receive(:run)
|
107
|
+
.with(%{PGPASSWORD="pg-pass" pg_restore -e -v --no-acl -O -a -h pg-host -U pg-user -p 6022 -d pg-db < tmp/duple/development-data.dump})
|
108
|
+
|
109
|
+
invoke_copy
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Duple::CLI::Init do
|
4
|
+
before { suppress_output }
|
5
|
+
after { reset_output }
|
6
|
+
|
7
|
+
before { FileUtils.mkdir_p('tmp/duple/init') }
|
8
|
+
after { FileUtils.rm_rf('tmp/duple') }
|
9
|
+
|
10
|
+
it 'creates a config file in the default location' do
|
11
|
+
FileUtils.chdir('tmp/duple/init') do
|
12
|
+
# capture_stdout do
|
13
|
+
script = Duple::CLI::Root.new
|
14
|
+
script.invoke(:init)
|
15
|
+
Pathname.new("config/duple.yml").should exist
|
16
|
+
# end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,413 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Duple::CLI::Refresh do
|
4
|
+
include Duple::CLISpecHelpers
|
5
|
+
|
6
|
+
def invoke_refresh(options = nil)
|
7
|
+
invoke_cli(:refresh, options)
|
8
|
+
end
|
9
|
+
|
10
|
+
before { FileUtils.mkdir_p('tmp/duple') }
|
11
|
+
after { FileUtils.rm_rf('tmp/duple') }
|
12
|
+
|
13
|
+
context 'from heroku to heroku' do
|
14
|
+
before {
|
15
|
+
stub_fetch_url
|
16
|
+
stub_reset_heroku
|
17
|
+
stub_restore_url
|
18
|
+
}
|
19
|
+
|
20
|
+
let(:source) { 'production' }
|
21
|
+
let(:target) { 'stage' }
|
22
|
+
|
23
|
+
it 'runs commands in the correct order' do
|
24
|
+
runner.should_receive(:run).once.ordered.with(/heroku pgbackups:capture/)
|
25
|
+
runner.should_receive(:capture).once.ordered.with(/heroku pgbackups:url/).and_return(heroku_pgbackups_url_response)
|
26
|
+
runner.should_receive(:run).once.ordered.with(/heroku pg:reset/)
|
27
|
+
runner.should_receive(:run).once.ordered.with(/heroku pgbackups:restore/)
|
28
|
+
|
29
|
+
invoke_refresh(capture: true)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'fetches the latest snapshot URL for the source' do
|
33
|
+
runner.should_receive(:capture).with('heroku pgbackups:url -a duple-production')
|
34
|
+
.and_return(heroku_pgbackups_url_response)
|
35
|
+
|
36
|
+
invoke_refresh
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'resets the target database' do
|
40
|
+
runner.should_receive(:run).with(%{heroku pg:reset -a duple-stage})
|
41
|
+
|
42
|
+
invoke_refresh
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'does not reset the source database' do
|
46
|
+
runner.should_not_receive(:run).with(/heroku pg:reset -a phsnap-production/)
|
47
|
+
|
48
|
+
invoke_refresh
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'restores the target from the snapshot URL' do
|
52
|
+
db_url = heroku_pgbackups_url_response.strip
|
53
|
+
runner.should_receive(:run).with(%{heroku pgbackups:restore DATABASE #{db_url} -a duple-stage})
|
54
|
+
|
55
|
+
invoke_refresh
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'does not capture a new snapshot by default' do
|
59
|
+
runner.should_not_receive(:run).with(/heroku pgbackups:capture/)
|
60
|
+
invoke_refresh
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'with the --capture flag' do
|
64
|
+
it 'captures a new snapshot before fetching the URL' do
|
65
|
+
runner.should_receive(:run).with('heroku pgbackups:capture -a duple-production')
|
66
|
+
invoke_refresh(capture: true)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'with a table list' do
|
71
|
+
before {
|
72
|
+
stub_fetch_config
|
73
|
+
stub_dump_data
|
74
|
+
stub_restore_data
|
75
|
+
}
|
76
|
+
|
77
|
+
it 'runs commands in the correct order' do
|
78
|
+
runner.should_not_receive(:capture).with(/heroku pgbackups:url/)
|
79
|
+
runner.should_not_receive(:run).with(/heroku pgbackups:restore/)
|
80
|
+
|
81
|
+
runner.should_receive(:run).once.ordered.with(/heroku pgbackups:capture/)
|
82
|
+
runner.should_receive(:capture).once.ordered.with(/heroku config -a duple-production/).and_return(heroku_config_response)
|
83
|
+
runner.should_receive(:run).once.ordered.with(/pg_dump/).and_return(heroku_config_response)
|
84
|
+
runner.should_receive(:run).once.ordered.with(/heroku pg:reset/)
|
85
|
+
runner.should_receive(:capture).once.ordered.with(/heroku config -a duple-stage/).and_return(heroku_config_response)
|
86
|
+
runner.should_receive(:run).once.ordered.with(/pg_restore/)
|
87
|
+
|
88
|
+
invoke_refresh(capture: true, tables: ['categories'])
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'does not download the snapshot' do
|
92
|
+
runner.should_not_receive(:capture).with(/pgbackups/)
|
93
|
+
runner.should_not_receive(:capture).with(/curl/)
|
94
|
+
|
95
|
+
invoke_refresh(tables: ['categories'])
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'dumps the tables in the list' do
|
99
|
+
runner.should_receive(:run)
|
100
|
+
.with(%{PGPASSWORD="pg-pass" pg_dump -Fc -a -t categories -h pg-host -U pg-user -p 6022 pg-db > tmp/duple/production-data.dump})
|
101
|
+
|
102
|
+
invoke_refresh(tables: ['categories'])
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'loads the dump file into the target database' do
|
106
|
+
runner.should_receive(:run)
|
107
|
+
.with(%{PGPASSWORD="pg-pass" pg_restore -e -v --no-acl -O -a -h pg-host -U pg-user -p 6022 -d pg-db < tmp/duple/production-data.dump})
|
108
|
+
|
109
|
+
invoke_refresh(tables: ['categories'])
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
context 'from heroku to local' do
|
115
|
+
before {
|
116
|
+
stub_fetch_url
|
117
|
+
stub_fetch_backups
|
118
|
+
stub_download_snapshot
|
119
|
+
stub_reset_local
|
120
|
+
stub_restore_data
|
121
|
+
}
|
122
|
+
|
123
|
+
let(:source) { 'stage' }
|
124
|
+
let(:target) { 'development' }
|
125
|
+
|
126
|
+
it 'runs commands in the correct order' do
|
127
|
+
runner.should_receive(:run).once.ordered.with(/heroku pgbackups:capture/)
|
128
|
+
runner.should_receive(:capture).once.ordered.with(/heroku pgbackups:url/).and_return(heroku_pgbackups_url_response)
|
129
|
+
runner.should_receive(:capture).once.ordered.with(/heroku pgbackups/).and_return(heroku_pgbackups_response)
|
130
|
+
runner.should_receive(:run).once.ordered.with(/curl/)
|
131
|
+
runner.should_receive(:run).once.ordered.with(/rake db:drop db:create/)
|
132
|
+
runner.should_receive(:run).once.ordered.with(/pg_restore/)
|
133
|
+
|
134
|
+
invoke_refresh(capture: true)
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'fetches the latest snapshot URL for the source' do
|
138
|
+
runner.should_receive(:capture).with('heroku pgbackups:url -a duple-stage')
|
139
|
+
.and_return(heroku_pgbackups_url_response)
|
140
|
+
|
141
|
+
invoke_refresh
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'resets the local database' do
|
145
|
+
runner.should_receive(:run).with(%{bundle exec rake db:drop db:create})
|
146
|
+
|
147
|
+
invoke_refresh
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'does not reset the source database' do
|
151
|
+
runner.should_not_receive(:run).with(/heroku pg:reset/)
|
152
|
+
|
153
|
+
invoke_refresh
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'downloads the snapshot from the snapshot URL' do
|
157
|
+
runner.should_receive(:run).with(%{curl -o #{snapshot_path} #{heroku_pgbackups_url_response.strip}})
|
158
|
+
|
159
|
+
invoke_refresh
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'does not re-download the snapshot if the timestamp has not changed' do
|
163
|
+
FileUtils.touch(snapshot_path)
|
164
|
+
|
165
|
+
runner.should_not_receive(:run).with(/curl/)
|
166
|
+
|
167
|
+
invoke_refresh
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'loads the snapshot file into the local database' do
|
171
|
+
runner.should_receive(:run)
|
172
|
+
.with(%{PGPASSWORD="" pg_restore -e -v --no-acl -O -a -h localhost -U postgres -p 5432 -d duple_development < #{snapshot_path}})
|
173
|
+
|
174
|
+
invoke_refresh
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'does not capture a new snapshot by default' do
|
178
|
+
runner.should_not_receive(:run).with(/heroku pgbackups:capture/)
|
179
|
+
invoke_refresh
|
180
|
+
end
|
181
|
+
|
182
|
+
context 'with the --capture flag' do
|
183
|
+
it 'captures a new snapshot before fetching the URL' do
|
184
|
+
runner.should_receive(:run).with('heroku pgbackups:capture -a duple-stage')
|
185
|
+
invoke_refresh(capture: true)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
context 'with a table list' do
|
190
|
+
let(:table_options) { {tables: ['categories']} }
|
191
|
+
|
192
|
+
before {
|
193
|
+
stub_fetch_config
|
194
|
+
stub_dump_data
|
195
|
+
stub_restore_data
|
196
|
+
}
|
197
|
+
|
198
|
+
it 'runs commands in the correct order' do
|
199
|
+
runner.should_receive(:run).once.ordered.with(/heroku pgbackups:capture/)
|
200
|
+
runner.should_receive(:capture).once.ordered.with(/heroku config -a duple-stage/).and_return(heroku_config_response)
|
201
|
+
runner.should_receive(:run).once.ordered.with(/pg_dump/)
|
202
|
+
runner.should_receive(:run).once.ordered.with(/rake db:drop db:create/)
|
203
|
+
runner.should_receive(:run).once.ordered.with(/pg_restore/)
|
204
|
+
|
205
|
+
invoke_refresh(table_options.merge(capture: true))
|
206
|
+
end
|
207
|
+
|
208
|
+
it 'does not download the snapshot' do
|
209
|
+
runner.should_not_receive(:capture).with(/pgbackups/)
|
210
|
+
runner.should_not_receive(:capture).with(/curl/)
|
211
|
+
|
212
|
+
invoke_refresh(table_options)
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'dumps the tables in the list' do
|
216
|
+
runner.should_receive(:run)
|
217
|
+
.with(%{PGPASSWORD="pg-pass" pg_dump -Fc -a -t categories -h pg-host -U pg-user -p 6022 pg-db > tmp/duple/stage-data.dump})
|
218
|
+
|
219
|
+
invoke_refresh(table_options)
|
220
|
+
end
|
221
|
+
|
222
|
+
it 'loads the dump file into the target database' do
|
223
|
+
runner.should_receive(:run)
|
224
|
+
.with(%{PGPASSWORD="" pg_restore -e -v --no-acl -O -a -h localhost -U postgres -p 5432 -d duple_development < tmp/duple/stage-data.dump})
|
225
|
+
|
226
|
+
invoke_refresh(table_options)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
context 'from local to heroku' do
|
232
|
+
before {
|
233
|
+
stub_dump_data
|
234
|
+
stub_reset_heroku
|
235
|
+
stub_fetch_config
|
236
|
+
stub_restore_data
|
237
|
+
}
|
238
|
+
|
239
|
+
let(:source) { 'development' }
|
240
|
+
let(:target) { 'stage' }
|
241
|
+
|
242
|
+
it 'runs commands in the correct order' do
|
243
|
+
runner.should_receive(:run).once.ordered.with(/pg_dump/)
|
244
|
+
runner.should_receive(:run).once.ordered.with(/heroku pg:reset/)
|
245
|
+
runner.should_receive(:capture).once.ordered.with(/heroku config -a duple-stage/).and_return(heroku_config_response)
|
246
|
+
runner.should_receive(:run).once.ordered.with(/pg_restore/)
|
247
|
+
|
248
|
+
invoke_refresh(capture: true)
|
249
|
+
end
|
250
|
+
|
251
|
+
it 'dumps the data from the local database' do
|
252
|
+
runner.should_receive(:run)
|
253
|
+
.with(%{PGPASSWORD="" pg_dump -Fc -a -h localhost -U postgres -p 5432 duple_development > tmp/duple/development-data.dump})
|
254
|
+
|
255
|
+
invoke_refresh
|
256
|
+
end
|
257
|
+
|
258
|
+
it 'resets the target database' do
|
259
|
+
runner.should_receive(:run).with(%{heroku pg:reset -a duple-stage})
|
260
|
+
|
261
|
+
invoke_refresh
|
262
|
+
end
|
263
|
+
|
264
|
+
it 'restores the target from the dump' do
|
265
|
+
runner.should_receive(:run)
|
266
|
+
.with(%{PGPASSWORD="pg-pass" pg_restore -e -v --no-acl -O -a -h pg-host -U pg-user -p 6022 -d pg-db < tmp/duple/development-data.dump})
|
267
|
+
|
268
|
+
invoke_refresh
|
269
|
+
end
|
270
|
+
|
271
|
+
it 'does not capture a new snapshot' do
|
272
|
+
runner.should_not_receive(:run).with(/heroku pgbackups:capture/)
|
273
|
+
|
274
|
+
invoke_refresh
|
275
|
+
end
|
276
|
+
|
277
|
+
context 'with the --capture flag' do
|
278
|
+
it 'does not capture a new snapshot' do
|
279
|
+
runner.should_not_receive(:run).with(/heroku pgbackups:capture/)
|
280
|
+
|
281
|
+
invoke_refresh(capture: true)
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
context 'with a table list' do
|
286
|
+
it 'downloads only the tables in the list' do
|
287
|
+
runner.should_receive(:run)
|
288
|
+
.with(%{PGPASSWORD="" pg_dump -Fc -a -t categories -h localhost -U postgres -p 5432 duple_development > tmp/duple/development-data.dump})
|
289
|
+
|
290
|
+
invoke_refresh(tables: ['categories'])
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
context 'with pre-refresh tasks' do
|
296
|
+
before { pending 'Implement pre-refresh tasks' }
|
297
|
+
|
298
|
+
before {
|
299
|
+
stub_fetch_url
|
300
|
+
stub_fetch_config
|
301
|
+
stub_fetch_backups
|
302
|
+
stub_dump_data
|
303
|
+
stub_download_snapshot
|
304
|
+
stub_reset_heroku
|
305
|
+
stub_reset_local
|
306
|
+
stub_restore_url
|
307
|
+
stub_restore_data
|
308
|
+
}
|
309
|
+
|
310
|
+
let(:source) { 'production' }
|
311
|
+
let(:target) { 'stage' }
|
312
|
+
let(:task_options) { { config: 'spec/config/tasks.yml' } }
|
313
|
+
|
314
|
+
it 'executes the tasks before refreshing' do
|
315
|
+
runner.should_receive(:run).once.ordered.with('heroku maintenance:on -a duple-stage')
|
316
|
+
runner.should_receive(:run).any_number_of_times.ordered.with(/heroku pgbackups/)
|
317
|
+
|
318
|
+
invoke_refresh(table_options.merge(capture: true))
|
319
|
+
end
|
320
|
+
|
321
|
+
it 'executes the tasks in order' do
|
322
|
+
runner.should_receive(:run).once.ordered.with('heroku run "rake refresh:prepare" -a duple-production')
|
323
|
+
runner.should_receive(:run).once.ordered.with('heroku maintenance:on -a duple-stage')
|
324
|
+
runner.should_receive(:run).once.ordered.with('heroku run "rake refresh:prepare" -a duple-stage')
|
325
|
+
|
326
|
+
invoke_refresh(task_options)
|
327
|
+
end
|
328
|
+
|
329
|
+
context 'with a local target' do
|
330
|
+
let(:target) { 'development' }
|
331
|
+
|
332
|
+
it 'executes the tasks in order' do
|
333
|
+
runner.should_receive(:run).once.ordered.with('heroku run "rake refresh:prepare" -a duple-production')
|
334
|
+
runner.should_not_receive(:run).with(/heroku maintenance:on/)
|
335
|
+
runner.should_receive(:run).once.ordered.with('rake refresh:prepare')
|
336
|
+
|
337
|
+
invoke_refresh(task_options)
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
context 'with a local source' do
|
342
|
+
let(:source) { 'development' }
|
343
|
+
|
344
|
+
it 'executes the tasks in order' do
|
345
|
+
runner.should_receive(:run).once.ordered.with('rake refresh:prepare')
|
346
|
+
runner.should_receive(:run).once.ordered.with('heroku maintenance:on -a duple-stage')
|
347
|
+
runner.should_receive(:run).once.ordered.with('heroku run "rake refresh:prepare" -a duple-stage')
|
348
|
+
|
349
|
+
invoke_refresh(task_options)
|
350
|
+
end
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
context 'with post-refresh tasks' do
|
355
|
+
before { pending 'Implement post-refresh tasks' }
|
356
|
+
before {
|
357
|
+
stub_fetch_url
|
358
|
+
stub_fetch_config
|
359
|
+
stub_fetch_backups
|
360
|
+
stub_dump_data
|
361
|
+
stub_download_snapshot
|
362
|
+
stub_reset_heroku
|
363
|
+
stub_reset_local
|
364
|
+
stub_restore_url
|
365
|
+
stub_restore_data
|
366
|
+
}
|
367
|
+
|
368
|
+
let(:source) { 'production' }
|
369
|
+
let(:target) { 'stage' }
|
370
|
+
let(:task_options) { { config: 'spec/config/tasks.yml' } }
|
371
|
+
|
372
|
+
it 'executes the tasks after refreshing' do
|
373
|
+
runner.should_receive(:run).any_number_of_times.ordered.with(/heroku pgbackups/)
|
374
|
+
runner.should_receive(:run).once.ordered.with('heroku maintenance:on -a duple-stage')
|
375
|
+
|
376
|
+
invoke_refresh(table_options.merge(capture: true))
|
377
|
+
end
|
378
|
+
|
379
|
+
it 'executes the tasks in order' do
|
380
|
+
runner.should_receive(:run).once.ordered.with('heroku run "rake refresh:finish" -a duple-production')
|
381
|
+
runner.should_receive(:run).once.ordered.with('heroku maintenance:off -a duple-stage')
|
382
|
+
runner.should_receive(:run).once.ordered.with('heroku run "rake refresh:finish" -a duple-stage')
|
383
|
+
|
384
|
+
invoke_refresh(task_options)
|
385
|
+
end
|
386
|
+
|
387
|
+
context 'with a local target' do
|
388
|
+
let(:target) { 'development' }
|
389
|
+
|
390
|
+
it 'executes the tasks in order' do
|
391
|
+
runner.should_receive(:run).once.ordered.with('heroku run "rake refresh:finish" -a duple-production')
|
392
|
+
runner.should_not_receive(:run).with(/heroku maintenance:off/)
|
393
|
+
runner.should_receive(:run).once.ordered.with('rake refresh:finish')
|
394
|
+
|
395
|
+
invoke_refresh(task_options)
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
context 'with a local source' do
|
400
|
+
let(:source) { 'development' }
|
401
|
+
|
402
|
+
it 'executes the tasks in order' do
|
403
|
+
runner.should_receive(:run).once.ordered.with('rake refresh:finish')
|
404
|
+
runner.should_receive(:run).once.ordered.with('heroku maintenance:on -a duple-stage')
|
405
|
+
runner.should_receive(:run).once.ordered.with('heroku run "rake refresh:finish" -a duple-stage')
|
406
|
+
|
407
|
+
invoke_refresh(task_options)
|
408
|
+
end
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
412
|
+
|
413
|
+
end
|