paratrooper 2.4.1 → 3.0.0.beta1
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/.gitignore +5 -0
- data/CHANGELOG.md +9 -2
- data/README.md +3 -4
- data/lib/paratrooper.rb +3 -0
- data/lib/paratrooper/callbacks.rb +2 -2
- data/lib/paratrooper/configuration.rb +94 -0
- data/lib/paratrooper/deploy.rb +42 -105
- data/lib/paratrooper/error.rb +3 -0
- data/lib/paratrooper/heroku_wrapper.rb +16 -22
- data/lib/paratrooper/local_api_key_extractor.rb +2 -1
- data/lib/paratrooper/notifiers/screen_notifier.rb +6 -5
- data/lib/paratrooper/pending_migration_check.rb +7 -6
- data/lib/paratrooper/source_control.rb +49 -0
- data/lib/paratrooper/system_caller.rb +19 -6
- data/lib/paratrooper/version.rb +1 -1
- data/paratrooper.gemspec +2 -2
- data/spec/paratrooper/configuration_spec.rb +352 -0
- data/spec/paratrooper/deploy_spec.rb +77 -232
- data/spec/paratrooper/heroku_wrapper_spec.rb +8 -38
- data/spec/paratrooper/local_api_key_extractor_spec.rb +2 -3
- data/spec/paratrooper/notifier_spec.rb +1 -1
- data/spec/paratrooper/pending_migration_check_spec.rb +14 -7
- data/spec/paratrooper/source_control_spec.rb +233 -0
- metadata +32 -28
- data/.bundle/config +0 -2
- data/.rspec +0 -2
- data/.ruby-version +0 -1
@@ -19,7 +19,6 @@ describe Paratrooper::Deploy do
|
|
19
19
|
let(:options) { Hash.new }
|
20
20
|
let(:heroku) do
|
21
21
|
double(:heroku,
|
22
|
-
app_url: 'application_url',
|
23
22
|
app_restart: true,
|
24
23
|
app_maintenance_on: true,
|
25
24
|
app_maintenance_off: true,
|
@@ -36,93 +35,26 @@ describe Paratrooper::Deploy do
|
|
36
35
|
end
|
37
36
|
let(:http_client) { double(:http_client).as_null_object }
|
38
37
|
|
39
|
-
|
40
|
-
|
41
|
-
deployer.tag = "tag_name"
|
42
|
-
expect(deployer.tag_name).to eq("tag_name")
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
describe "match_tag_to=" do
|
47
|
-
specify "match_tag is set and @match_tag_name holds value" do
|
48
|
-
deployer.match_tag = "staging"
|
49
|
-
expect(deployer.match_tag_name).to eq("staging")
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
describe "branch=" do
|
54
|
-
specify "branch is set and @branch_name holds value" do
|
55
|
-
deployer.branch = "branch_name"
|
56
|
-
expect(deployer.branch_name).to eq("branch_name")
|
57
|
-
end
|
38
|
+
before do
|
39
|
+
allow(screen_notifier).to receive(:notify)
|
58
40
|
end
|
59
41
|
|
60
42
|
describe "passing a block to initialize" do
|
61
43
|
it "sets attributes on self" do
|
62
44
|
deployer = described_class.new(app_name, default_options) do |p|
|
63
|
-
p.match_tag = "staging"
|
64
|
-
p.tag = "production"
|
65
|
-
p.debug = true
|
66
45
|
p.deployment_host = "HOST"
|
67
|
-
p.protocol
|
68
|
-
end
|
69
|
-
expect(deployer.match_tag_name).to eq("staging")
|
70
|
-
expect(deployer.tag_name).to eq("production")
|
71
|
-
expect(deployer.debug).to be_true
|
72
|
-
expect(deployer.deployment_host).to eq("HOST")
|
73
|
-
expect(deployer.protocol).to eq("MOM")
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
describe "options" do
|
78
|
-
context "accepts :tag" do
|
79
|
-
let(:options) { { tag: 'tag_name' } }
|
80
|
-
|
81
|
-
it "and responds to #tag_name" do
|
82
|
-
expect(deployer.tag_name).to eq('tag_name')
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
context "accepts :heroku_auth" do
|
87
|
-
let(:options) { { heroku_auth: heroku } }
|
88
|
-
let(:heroku) { double(:heroku) }
|
89
|
-
|
90
|
-
it "and responds to #heroku" do
|
91
|
-
expect(deployer.heroku).to eq(heroku)
|
46
|
+
p.protocol = "MOM"
|
92
47
|
end
|
48
|
+
expect(deployer.config.deployment_host).to eq("HOST")
|
49
|
+
expect(deployer.config.protocol).to eq("MOM")
|
93
50
|
end
|
94
51
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
it "and responds to #notifiers" do
|
100
|
-
expect(deployer.notifiers).to eq([notifiers])
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
describe "protocol" do
|
105
|
-
context "accepts :protocol" do
|
106
|
-
let(:options) { { protocol: 'https' } }
|
107
|
-
|
108
|
-
it "and responds to #protocol" do
|
109
|
-
expect(deployer.protocol).to eq('https')
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
context "no value passed" do
|
114
|
-
it "and responds to #protocol with default value" do
|
115
|
-
expect(deployer.protocol).to eq('http')
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
context "accepts :deployment_host" do
|
121
|
-
let(:options) { { deployment_host: 'host_name' } }
|
122
|
-
|
123
|
-
it "and responds to #notifiers" do
|
124
|
-
expect(deployer.deployment_host).to eq('host_name')
|
52
|
+
it "lazy loads dependent options" do
|
53
|
+
deployer = described_class.new(app_name, api_key: 'API_KEY') do |p|
|
54
|
+
p.force_push = false
|
125
55
|
end
|
56
|
+
expect(deployer.config.api_key).to eq('API_KEY')
|
57
|
+
expect(deployer.config.force_push).to eq(false)
|
126
58
|
end
|
127
59
|
end
|
128
60
|
|
@@ -132,32 +64,32 @@ describe Paratrooper::Deploy do
|
|
132
64
|
|
133
65
|
context "with pending migrations" do
|
134
66
|
before do
|
135
|
-
migration_check.
|
67
|
+
allow(migration_check).to receive(:migrations_waiting?).and_return(true)
|
136
68
|
end
|
137
69
|
|
138
70
|
it 'sends notification' do
|
139
|
-
deployer.
|
71
|
+
expect(deployer).to receive(:notify).with(:activate_maintenance_mode).once
|
140
72
|
deployer.activate_maintenance_mode
|
141
73
|
end
|
142
74
|
|
143
75
|
it "makes call to heroku to turn on maintenance mode" do
|
144
|
-
heroku.
|
76
|
+
expect(heroku).to receive(:app_maintenance_on)
|
145
77
|
deployer.activate_maintenance_mode
|
146
78
|
end
|
147
79
|
end
|
148
80
|
|
149
81
|
context "without pending migrations" do
|
150
82
|
before do
|
151
|
-
migration_check.
|
83
|
+
allow(migration_check).to receive(:migrations_waiting?).and_return(false)
|
152
84
|
end
|
153
85
|
|
154
86
|
it 'does not send notification' do
|
155
|
-
deployer.
|
87
|
+
expect(deployer).to_not receive(:notify).with(:activate_maintenance_mode)
|
156
88
|
deployer.activate_maintenance_mode
|
157
89
|
end
|
158
90
|
|
159
91
|
it "does not make a call to heroku to turn on maintenance mode" do
|
160
|
-
heroku.
|
92
|
+
expect(heroku).to_not receive(:app_maintenance_on)
|
161
93
|
deployer.activate_maintenance_mode
|
162
94
|
end
|
163
95
|
end
|
@@ -167,16 +99,16 @@ describe Paratrooper::Deploy do
|
|
167
99
|
let(:options) { { maintenance: false } }
|
168
100
|
|
169
101
|
before do
|
170
|
-
migration_check.
|
102
|
+
allow(migration_check).to receive(:migrations_waiting?).and_return(true)
|
171
103
|
end
|
172
104
|
|
173
105
|
it 'does not send notification' do
|
174
|
-
deployer.
|
106
|
+
expect(deployer).to_not receive(:notify).with(:activate_maintenance_mode)
|
175
107
|
deployer.activate_maintenance_mode
|
176
108
|
end
|
177
109
|
|
178
110
|
it "does not make a call to heroku to turn on maintenance mode" do
|
179
|
-
heroku.
|
111
|
+
expect(heroku).to_not receive(:app_maintenance_on)
|
180
112
|
deployer.activate_maintenance_mode
|
181
113
|
end
|
182
114
|
end
|
@@ -185,16 +117,16 @@ describe Paratrooper::Deploy do
|
|
185
117
|
let(:options) { { } }
|
186
118
|
|
187
119
|
before do
|
188
|
-
migration_check.
|
120
|
+
allow(migration_check).to receive(:migrations_waiting?).and_return(true)
|
189
121
|
end
|
190
122
|
|
191
123
|
it 'does not send notification' do
|
192
|
-
deployer.
|
124
|
+
expect(deployer).to_not receive(:notify).with(:activate_maintenance_mode)
|
193
125
|
deployer.activate_maintenance_mode
|
194
126
|
end
|
195
127
|
|
196
128
|
it "does not make a call to heroku to turn on maintenance mode" do
|
197
|
-
heroku.
|
129
|
+
expect(heroku).to_not receive(:app_maintenance_on)
|
198
130
|
deployer.activate_maintenance_mode
|
199
131
|
end
|
200
132
|
end
|
@@ -202,163 +134,103 @@ describe Paratrooper::Deploy do
|
|
202
134
|
|
203
135
|
describe "#deactivate_maintenance_mode" do
|
204
136
|
context "when maintenance_mode option is 'true'" do
|
205
|
-
let(:options) { {
|
137
|
+
let(:options) { { maintenance: true } }
|
206
138
|
|
207
139
|
context "with pending migrations" do
|
208
140
|
before do
|
209
|
-
migration_check.
|
141
|
+
allow(migration_check).to receive(:migrations_waiting?).and_return(true)
|
210
142
|
end
|
211
143
|
|
212
144
|
it 'sends notification' do
|
213
|
-
deployer.
|
145
|
+
expect(deployer).to receive(:notify).with(:deactivate_maintenance_mode).once
|
214
146
|
deployer.deactivate_maintenance_mode
|
215
147
|
end
|
216
148
|
|
217
149
|
it "makes call to heroku to turn on maintenance mode" do
|
218
|
-
heroku.
|
150
|
+
expect(heroku).to receive(:app_maintenance_off)
|
219
151
|
deployer.deactivate_maintenance_mode
|
220
152
|
end
|
221
153
|
end
|
222
154
|
|
223
155
|
context "without pending migrations" do
|
224
156
|
before do
|
225
|
-
migration_check.
|
157
|
+
allow(migration_check).to receive(:migrations_waiting?).and_return(false)
|
226
158
|
end
|
227
159
|
|
228
160
|
it 'does not send notification' do
|
229
|
-
deployer.
|
161
|
+
expect(deployer).to_not receive(:notify).with(:deactivate_maintenance_mode)
|
230
162
|
deployer.deactivate_maintenance_mode
|
231
163
|
end
|
232
164
|
|
233
165
|
it "does not make a call to heroku to turn on maintenance mode" do
|
234
|
-
heroku.
|
166
|
+
expect(heroku).to_not receive(:app_maintenance_off)
|
235
167
|
deployer.deactivate_maintenance_mode
|
236
168
|
end
|
237
169
|
end
|
238
170
|
end
|
239
171
|
end
|
240
172
|
|
241
|
-
describe "#
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
it 'sends notification' do
|
250
|
-
deployer.should_receive(:notify).with(:update_repo_tag).once
|
251
|
-
deployer.update_repo_tag
|
252
|
-
end
|
253
|
-
|
254
|
-
context "when deploy_tag is available" do
|
255
|
-
before do
|
256
|
-
options.merge!(match_tag: 'deploy_this')
|
257
|
-
end
|
258
|
-
|
259
|
-
it 'creates a git tag at deploy_tag reference point' do
|
260
|
-
system_caller.should_receive(:execute).with('git tag awesome deploy_this -f')
|
261
|
-
deployer.update_repo_tag
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
265
|
-
context "when no deploy_tag is available" do
|
266
|
-
it 'creates a git tag at HEAD' do
|
267
|
-
system_caller.should_receive(:execute).with('git tag awesome master -f')
|
268
|
-
deployer.update_repo_tag
|
269
|
-
end
|
270
|
-
end
|
271
|
-
|
272
|
-
it 'pushes git tag' do
|
273
|
-
expected = 'git push -f origin awesome'
|
274
|
-
system_caller.should_receive(:execute).with(expected)
|
275
|
-
deployer.update_repo_tag
|
276
|
-
end
|
277
|
-
end
|
278
|
-
|
279
|
-
context "when a tag_name is unavailable" do
|
280
|
-
let(:options) { Hash.new }
|
281
|
-
|
282
|
-
it 'no repo tags are created' do
|
283
|
-
system_caller.should_not_receive(:execute)
|
284
|
-
deployer.update_repo_tag
|
173
|
+
describe "#push_repo" do
|
174
|
+
let(:notifier) { double(:notifier) }
|
175
|
+
let(:source_control) { double(:source_control) }
|
176
|
+
let(:deployer) do
|
177
|
+
described_class.new('APP') do |d|
|
178
|
+
d.notifiers = notifier
|
179
|
+
d.source_control = source_control
|
285
180
|
end
|
286
181
|
end
|
287
|
-
end
|
288
182
|
|
289
|
-
describe "#push_repo" do
|
290
183
|
before do
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
deployer.should_receive(:notify)
|
296
|
-
.with(:push_repo, reference_point: 'master').once
|
297
|
-
deployer.push_repo
|
184
|
+
allow(source_control).to receive(:reference_point)
|
185
|
+
allow(source_control).to receive(:remote)
|
186
|
+
allow(source_control).to receive(:push_to_deploy)
|
187
|
+
allow(notifier).to receive(:notify)
|
298
188
|
end
|
299
189
|
|
300
|
-
|
301
|
-
|
302
|
-
|
190
|
+
it "sends notification" do
|
191
|
+
allow(notifier).to receive(:notify) do |step, options|
|
192
|
+
expect(step).to eq(:push_repo)
|
303
193
|
end
|
194
|
+
deployer.push_repo
|
304
195
|
|
305
|
-
|
306
|
-
expected_call = 'git push -f git@heroku.com:app.git refs/heads/BRANCH_NAME:refs/heads/master'
|
307
|
-
system_caller.should_receive(:execute).with(expected_call)
|
308
|
-
deployer.push_repo
|
309
|
-
end
|
196
|
+
expect(notifier).to have_received(:notify).once
|
310
197
|
end
|
311
198
|
|
312
|
-
|
313
|
-
|
314
|
-
deployer.tag_name = "TAG_NAME"
|
315
|
-
end
|
199
|
+
it "pushes repo to remote" do
|
200
|
+
deployer.push_repo
|
316
201
|
|
317
|
-
|
318
|
-
expected_call = 'git push -f git@heroku.com:app.git refs/tags/TAG_NAME:refs/heads/master'
|
319
|
-
system_caller.should_receive(:execute).with(expected_call)
|
320
|
-
deployer.push_repo
|
321
|
-
end
|
202
|
+
expect(source_control).to have_received(:push_to_deploy)
|
322
203
|
end
|
323
|
-
|
324
|
-
context "when no branch_name or tag_name" do
|
325
|
-
it 'pushes master repo to heroku' do
|
326
|
-
expected_call = 'git push -f git@heroku.com:app.git master:refs/heads/master'
|
327
|
-
system_caller.should_receive(:execute).with(expected_call)
|
328
|
-
deployer.push_repo
|
329
|
-
end
|
330
|
-
end
|
331
|
-
|
332
204
|
end
|
333
205
|
|
334
206
|
describe "#run_migrations" do
|
335
207
|
before do
|
336
|
-
system_caller.
|
208
|
+
allow(system_caller).to receive(:execute)
|
337
209
|
end
|
338
210
|
|
339
211
|
context "when new migrations are waiting to be run" do
|
340
212
|
before do
|
341
|
-
migration_check.
|
213
|
+
allow(migration_check).to receive(:migrations_waiting?).and_return(true)
|
342
214
|
end
|
343
215
|
|
344
216
|
it 'sends notification' do
|
345
|
-
deployer.
|
217
|
+
expect(deployer).to receive(:notify).with(:run_migrations).once
|
346
218
|
deployer.run_migrations
|
347
219
|
end
|
348
220
|
|
349
221
|
it 'pushes repo to heroku' do
|
350
|
-
heroku.
|
222
|
+
expect(heroku).to receive(:run_migrations)
|
351
223
|
deployer.run_migrations
|
352
224
|
end
|
353
225
|
end
|
354
226
|
|
355
227
|
context "when no migrations are available to be run" do
|
356
228
|
before do
|
357
|
-
migration_check.
|
229
|
+
allow(migration_check).to receive(:migrations_waiting?).and_return(false)
|
358
230
|
end
|
359
231
|
|
360
232
|
specify "heroku is not notified to run migrations" do
|
361
|
-
heroku.
|
233
|
+
expect(heroku).to_not receive(:run_migrations)
|
362
234
|
deployer.run_migrations
|
363
235
|
end
|
364
236
|
end
|
@@ -367,7 +239,7 @@ describe Paratrooper::Deploy do
|
|
367
239
|
describe "#app_restart" do
|
368
240
|
context 'when a restart is required due to pending migrations' do
|
369
241
|
before do
|
370
|
-
migration_check.
|
242
|
+
allow(migration_check).to receive(:migrations_waiting?).and_return(true)
|
371
243
|
end
|
372
244
|
|
373
245
|
it 'sends notification' do
|
@@ -383,7 +255,7 @@ describe Paratrooper::Deploy do
|
|
383
255
|
|
384
256
|
context 'when a restart is not required' do
|
385
257
|
before do
|
386
|
-
migration_check.
|
258
|
+
allow(migration_check).to receive(:migrations_waiting?).and_return(false)
|
387
259
|
end
|
388
260
|
|
389
261
|
it 'does not send notification' do
|
@@ -398,68 +270,41 @@ describe Paratrooper::Deploy do
|
|
398
270
|
end
|
399
271
|
end
|
400
272
|
|
401
|
-
describe "#
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
it 'sends notification' do
|
407
|
-
deployer.should_receive(:notify).with(:warm_instance).once
|
408
|
-
deployer.warm_instance(0)
|
409
|
-
end
|
410
|
-
|
411
|
-
it 'pings application url' do
|
412
|
-
expected_url = 'http://application_url'
|
413
|
-
expect(http_client).to receive(:get).with(expected_url)
|
414
|
-
deployer.warm_instance(0)
|
415
|
-
end
|
416
|
-
|
417
|
-
context 'with optional protocol' do
|
418
|
-
let(:options) { { protocol: 'https' } }
|
273
|
+
describe "#add_callback" do
|
274
|
+
it "adds callback" do
|
275
|
+
callback = proc do |output|
|
276
|
+
system("touch spec/fixtures/test.txt")
|
277
|
+
end
|
419
278
|
|
420
|
-
|
421
|
-
|
422
|
-
expect(http_client).to receive(:get).with(expected_url)
|
423
|
-
deployer.warm_instance(0)
|
279
|
+
deployer = described_class.new(app_name, default_options) do |p|
|
280
|
+
p.add_callback(:before_setup, &callback)
|
424
281
|
end
|
282
|
+
|
283
|
+
expect(deployer.config.callbacks[:before_setup]).to eq([callback])
|
425
284
|
end
|
426
285
|
|
427
|
-
|
428
|
-
it "
|
286
|
+
context "when messaging is added to callback" do
|
287
|
+
it "is called" do
|
429
288
|
callback = proc do |output|
|
430
|
-
|
289
|
+
output.display("Whoo Hoo!")
|
431
290
|
end
|
432
291
|
|
292
|
+
allow(screen_notifier).to receive(:display).with("Whoo Hoo!")
|
293
|
+
|
433
294
|
deployer = described_class.new(app_name, default_options) do |p|
|
434
295
|
p.add_callback(:before_setup, &callback)
|
435
296
|
end
|
297
|
+
deployer.setup
|
436
298
|
|
437
|
-
expect(
|
438
|
-
end
|
439
|
-
|
440
|
-
context "when messaging is added to callback" do
|
441
|
-
it "is called" do
|
442
|
-
callback = proc do |output|
|
443
|
-
output.display("Whoo Hoo!")
|
444
|
-
end
|
445
|
-
|
446
|
-
screen_notifier.stub(:display).with("Whoo Hoo!")
|
447
|
-
|
448
|
-
deployer = described_class.new(app_name, default_options) do |p|
|
449
|
-
p.add_callback(:before_setup, &callback)
|
450
|
-
end
|
451
|
-
deployer.setup
|
452
|
-
|
453
|
-
expect(screen_notifier).to have_received(:display).with("Whoo Hoo!")
|
454
|
-
end
|
299
|
+
expect(screen_notifier).to have_received(:display).with("Whoo Hoo!")
|
455
300
|
end
|
456
301
|
end
|
302
|
+
end
|
457
303
|
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
end
|
304
|
+
describe "#add_remote_task" do
|
305
|
+
it "makes call to heroku to run task" do
|
306
|
+
expect(heroku).to receive(:run_task).with("rake some:task:to:run")
|
307
|
+
deployer.add_remote_task("rake some:task:to:run")
|
463
308
|
end
|
464
309
|
end
|
465
310
|
end
|