git_reflow 0.8.3 → 0.8.4

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.
@@ -1,522 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe GitReflow do
4
- let(:git_server) { GitReflow::GitServer::GitHub.new {} }
5
- let(:github) { Github.new basic_auth: "#{user}:#{password}" }
6
- let(:user) { 'reenhanced' }
7
- let(:password) { 'shazam' }
8
- let(:oauth_token_hash) { Hashie::Mash.new({ token: 'a1b2c3d4e5f6g7h8i9j0', note: 'hostname.local git-reflow'}) }
9
- let(:repo) { 'repo' }
10
- let(:base_branch) { 'master' }
11
- let(:feature_branch) { 'new-feature' }
12
- let(:enterprise_site) { 'https://github.reenhanced.com' }
13
- let(:enterprise_api) { 'https://github.reenhanced.com' }
14
- let(:hostname) { 'hostname.local' }
15
-
16
- let(:github_authorizations) { Github::Client::Authorizations.new }
17
- let(:existing_pull_requests) { Fixture.new('pull_requests/pull_requests.json').to_json_hashie }
18
- let(:existing_pull_request) { GitReflow::GitServer::GitHub::PullRequest.new existing_pull_requests.first }
19
-
20
- before do
21
-
22
- # Stubbing out minimum_approvals value to test 2 LGTM reviewers in gitconfig file
23
- allow(GitReflow::Config).to receive(:get).with("constants.minimumApprovals").and_return("2")
24
- allow(GitReflow::Config).to receive(:get).and_call_original
25
-
26
- allow_any_instance_of(HighLine).to receive(:ask) do |terminal, question|
27
- values = {
28
- "Please enter your GitHub username: " => user,
29
- "Please enter your GitHub password (we do NOT store this): " => password,
30
- "Please enter your Enterprise site URL (e.g. https://github.company.com):" => enterprise_site,
31
- "Please enter your Enterprise API endpoint (e.g. https://github.company.com/api/v3):" => enterprise_api,
32
- "Would you like to push this branch to your remote repo and cleanup your feature branch? " => 'yes',
33
- "Would you like to open it in your browser?" => 'n',
34
- "This is the current status of your Pull Request. Are you sure you want to deliver? " => 'y',
35
- "Please enter your delivery commit title: (leaving blank will use default)" => 'title',
36
- "Please enter your delivery commit message: (leaving blank will use default)" => 'message'
37
- }
38
- return_value = values[question] || values[terminal]
39
- question = ""
40
- return_value
41
- end
42
- end
43
-
44
- context :deliver do
45
- let(:branch) { 'new-feature' }
46
- let(:inputs) {
47
- { :title => "new-feature",
48
- :message => "message",
49
- :head => "reenhanced:new-feature"
50
- }
51
- }
52
- let(:merge_response) { {} }
53
- let!(:github) do
54
- allow_any_instance_of(GitReflow::GitServer::GitHub::PullRequest).to receive(:build).and_return(Struct.new(:state, :description, :url).new)
55
- stub_github_with({
56
- :user => user,
57
- :password => password,
58
- :repo => repo,
59
- :branch => branch,
60
- :pull => existing_pull_request
61
- })
62
- end
63
-
64
-
65
- before do
66
- allow(GitReflow::GitServer::GitHub).to receive_message_chain(:connection, :pull_requests, :merge).and_return(merge_response)
67
- allow(merge_response).to receive(:success?).and_return(true)
68
-
69
- # Stubs out the http response to github api
70
- allow(GitReflow::GitServer::GitHub).to receive_message_chain(:connection, :pull_requests, :merge).and_return(merge_response)
71
- allow(merge_response).to receive(:success?).and_return(true);
72
-
73
- module Kernel
74
- def system(cmd)
75
- "call #{cmd}"
76
- end
77
- end
78
- end
79
-
80
- subject { GitReflow.deliver inputs }
81
-
82
- it "looks for a pull request matching the feature branch and destination branch" do
83
- expect(github).to receive(:find_open_pull_request).with(from: branch, to: 'master')
84
- subject
85
- end
86
-
87
- context "and pull request exists for the feature branch to the destination branch" do
88
- before do
89
- allow(github).to receive(:build_status).and_return(build_status)
90
- expect(github).to receive(:find_open_pull_request).and_return(existing_pull_request)
91
- allow(existing_pull_request).to receive(:has_comments?).and_return(true)
92
- allow(github).to receive(:reviewers).and_return(['codenamev'])
93
- allow(existing_pull_request).to receive(:approvals).and_return(["Simon", "John"])
94
- allow(existing_pull_request).to receive_message_chain(:last_comment, :match).and_return(true)
95
- allow(GitReflow::Config).to receive(:get).with("reflow.always-deliver").and_return("true")
96
- allow(GitReflow).to receive(:status)
97
- end
98
-
99
- context 'and build status is not "success"' do
100
- let(:build_status) { Hashie::Mash.new({ state: 'failure', description: 'Build resulted in failed test(s)' }) }
101
-
102
- before do
103
- allow(existing_pull_request).to receive(:build).and_return(build_status)
104
- allow(existing_pull_request).to receive(:has_comments?).and_return(true)
105
- end
106
-
107
- it "halts delivery and notifies user of a failed build" do
108
- expect { subject }.to have_said "#{build_status.description}: #{build_status.target_url}", :deliver_halted
109
- end
110
-
111
- context 'forces a merge' do
112
- before do
113
- inputs[:skip_lgtm] = true
114
- allow(existing_pull_request).to receive(:has_comments?).and_return(true)
115
- allow(existing_pull_request).to receive(:reviewers).and_return([])
116
- allow(existing_pull_request).to receive(:reviewers_pending_response).and_return([])
117
- allow(existing_pull_request).to receive(:approvals).and_return(['simonzhu24'])
118
- allow(GitReflow).to receive(:append_to_squashed_commit_message)
119
- allow(GitReflow::Config).to receive(:get).with("reflow.always-cleanup").and_return("true")
120
- end
121
-
122
- it "checks out the base branch" do
123
- expect { subject }.to have_run_command("git checkout master")
124
- end
125
-
126
- it "pulls changes from remote repo to local branch" do
127
- expect { subject }.to have_run_command("git pull origin master")
128
- end
129
-
130
- it "deletes the remote feature branch" do
131
- expect { subject }.to have_run_command("git push origin :new-feature")
132
- end
133
-
134
- it "deletes the local feature branch" do
135
- expect { subject }.to have_run_command("git branch -D new-feature")
136
- end
137
-
138
- it "forces a merge" do
139
- expect { subject }.to have_said "Merging pull request ##{existing_pull_request.number}: '#{existing_pull_request.title}', from '#{existing_pull_request.head.label}' into '#{existing_pull_request.base.label}'", :notice
140
- expect { subject }.to have_said "Pull request ##{existing_pull_request.number} successfully merged.", :success
141
- end
142
- end
143
- end
144
-
145
- context 'and build status is nil' do
146
- let(:build_status) { nil }
147
-
148
- before do
149
- # stubbing unrelated results so we can just test that it made it insdide the conditional block
150
- inputs[:skip_lgtm] = false
151
- allow(existing_pull_request).to receive(:has_comments?).and_return(true)
152
- allow(existing_pull_request).to receive(:reviewers).and_return([])
153
- allow(existing_pull_request).to receive(:reviewers_pending_response).and_return([])
154
- allow(existing_pull_request).to receive(:approvals).and_return(['simonzhu24'])
155
- end
156
-
157
- it "ignores build status when not setup" do
158
- expect { subject }.to have_said "Pull request ##{existing_pull_request.number} successfully merged.", :success
159
- end
160
- end
161
-
162
- context 'and build status is "success"' do
163
- let(:build_status) { Hashie::Mash.new({ state: 'success' }) }
164
-
165
- context 'and has comments' do
166
- before do
167
- inputs[:skip_lgtm] = false
168
- allow(existing_pull_request).to receive(:has_comments?).and_return(true)
169
- end
170
-
171
- context 'but there are 2 LGTMs and irrelevant last comment' do
172
- let(:lgtm_comment_authors) { ['nhance', 'Simon'] }
173
- before do
174
- allow(existing_pull_request).to receive(:build).and_return(build_status)
175
- allow(existing_pull_request).to receive(:approvals).and_return(lgtm_comment_authors)
176
- allow(GitReflow::GitServer::PullRequest).to receive(:minimum_approvals).and_return("2")
177
- allow(existing_pull_request).to receive(:reviewers_pending_response).and_return([])
178
- allow(existing_pull_request).to receive_message_chain(:last_comment, :match).and_return(nil)
179
- end
180
-
181
- context "and the pull request has no body" do
182
- let(:first_commit_message) { "We'll do it live." }
183
-
184
- before do
185
- existing_pull_request.description = ''
186
- allow(github).to receive(:find_open_pull_request).and_return(existing_pull_request)
187
- allow(GitReflow).to receive(:get_first_commit_message).and_return(first_commit_message)
188
- allow(existing_pull_request).to receive(:reviewers).and_return(lgtm_comment_authors)
189
- end
190
- end
191
-
192
- it "doesn't notify user of the merge and performs it" do
193
- expect { subject }.to_not have_said "Merging pull request ##{existing_pull_request.number}: '#{existing_pull_request.title}', from '#{existing_pull_request.head.label}' into '#{existing_pull_request.base.label}'"
194
- end
195
-
196
- it "doesn't update the destination branch" do
197
- expect(GitReflow).to receive(:update_destination).with('master').never
198
- subject
199
- end
200
-
201
- context "and doesn't clean up feature branch" do
202
- before do
203
- allow_any_instance_of(HighLine).to receive(:ask) do |terminal, question|
204
- values = {
205
- "Please enter your GitHub username: " => user,
206
- "Please enter your GitHub password (we do NOT store this): " => password,
207
- "Please enter your Enterprise site URL (e.g. https://github.company.com):" => enterprise_site,
208
- "Please enter your Enterprise API endpoint (e.g. https://github.company.com/api/v3):" => enterprise_api,
209
- "Would you like to push this branch to your remote repo and cleanup your feature branch?" => 'yes',
210
- "Would you like to open it in your browser?" => 'no',
211
- "This is the current status of your Pull Request. Are you sure you want to deliver? " => 'y',
212
- "Please enter your delivery commit title: (leaving blank will use default)" => 'title',
213
- "Please enter your delivery commit message: (leaving blank will use default)" => 'message'
214
- }
215
- return_value = values[question] || values[terminal]
216
- question = ""
217
- return_value
218
- end
219
- end
220
-
221
- context "not always" do
222
- before do
223
- allow(GitReflow::Config).to receive(:get) { "false" }
224
- end
225
-
226
- it "doesn't checkout the base branch" do
227
- expect { subject }.to_not have_run_command("git checkout master")
228
- end
229
-
230
- it "doesn't push local squash merged base branch to remote repo" do
231
- expect { subject }.to_not have_run_command("git pull origin master")
232
- end
233
-
234
- it "doesn't delete the remote feature branch" do
235
- expect { subject }.to_not have_run_command("git push origin :new-feature")
236
- end
237
-
238
- it "doesn't delete the local feature branch" do
239
- expect { subject }.to_not have_run_command("git branch -D new-feature")
240
- end
241
- end
242
-
243
- context "always" do
244
- before do
245
- allow(GitReflow::Config).to receive(:get) { "true" }
246
- end
247
-
248
- it "doesn't checkout the base branch" do
249
- expect { subject }.to_not have_run_command("git checkout master")
250
- end
251
-
252
- it "doesn't push local squash merged base branch to remote repo" do
253
- expect { subject }.to_not have_run_command("git pull origin master")
254
- end
255
-
256
- it "doesn't delete the remote feature branch" do
257
- expect { subject }.to_not have_run_command("git push origin :new-feature")
258
- end
259
-
260
- it "doesn't delete the local feature branch" do
261
- expect { subject }.to_not have_run_command("git branch -D new-feature")
262
- end
263
- end
264
-
265
- end
266
-
267
- context "and not cleaning up feature branch" do
268
- before do
269
- allow_any_instance_of(HighLine).to receive(:ask) do |terminal, question|
270
- values = {
271
- "Please enter your GitHub username: " => user,
272
- "Please enter your GitHub password (we do NOT store this): " => password,
273
- "Please enter your Enterprise site URL (e.g. https://github.company.com):" => enterprise_site,
274
- "Please enter your Enterprise API endpoint (e.g. https://github.company.com/api/v3):" => enterprise_api,
275
- "Would you like to push this branch to your remote repo and cleanup your feature branch? " => 'no',
276
- "Would you like to open it in your browser?" => 'no',
277
- "This is the current status of your Pull Request. Are you sure you want to deliver? " => 'y',
278
- "Please enter your delivery commit title: (leaving blank will use default)" => 'title',
279
- "Please enter your delivery commit message: (leaving blank will use default)" => 'message'
280
- }
281
- return_value = values[question] || values[terminal]
282
- question = ""
283
- return_value
284
- end
285
- end
286
-
287
- it "doesn't checkout the base branch" do
288
- expect { subject }.to_not have_run_command('git checkout master')
289
- end
290
-
291
- it "doesn't pull changes from remote repo to local branch" do
292
- expect { subject }.to_not have_run_command('git pull origin master')
293
- end
294
-
295
- it "doesn't delete the feature branch on the remote repo" do
296
- expect { subject }.to_not have_run_command('git push origin :new-feature')
297
- end
298
-
299
- it "doesn't delete the local feature branch" do
300
- expect { subject }.to_not have_run_command('git branch -D new-feature')
301
- end
302
-
303
- it "doesn't provide instructions to undo the steps taken" do
304
- expect { subject }.to_not have_output("To reset and go back to your branch run \`git reset --hard origin/master && git checkout new-feature\`")
305
- end
306
- end
307
-
308
- context "and there were issues commiting the squash merge to the base branch" do
309
- before { stub_with_fallback(GitReflow, :run_command_with_label).with('git commit', {with_system: true}).and_return false }
310
- it "doesn't notifies user of issues commiting the squash merge of the feature branch" do
311
- expect { subject }.to_not have_said("There were problems commiting your feature... please check the errors above and try again.", :error)
312
- end
313
- end
314
- end
315
-
316
- context 'but there are 2 LGTMs and LGTM last comment' do
317
- let(:lgtm_comment_authors) { ['nhance', 'Simon'] }
318
- before do
319
- allow(existing_pull_request).to receive(:approvals).and_return(lgtm_comment_authors)
320
- allow(existing_pull_request).to receive(:reviewers_pending_response).and_return([])
321
- allow(existing_pull_request).to receive_message_chain(:last_comment, :match).and_return(true)
322
- end
323
-
324
- context "build status failure, testing description and target_url" do
325
- let(:build_status) { Hashie::Mash.new({ state: 'failure', description: 'Build resulted in failed test(s)', target_url: "www.error.com" }) }
326
-
327
- before do
328
- allow(existing_pull_request).to receive(:build).and_return(build_status)
329
- allow(existing_pull_request).to receive(:reviewers).and_return(lgtm_comment_authors)
330
- allow(existing_pull_request).to receive(:has_comments?).and_return(true)
331
- end
332
-
333
- it "halts delivery and notifies user of a failed build" do
334
- expect { subject }.to have_said "#{build_status.description}: #{build_status.url}", :deliver_halted
335
- end
336
- end
337
-
338
- context "build status nil" do
339
- let(:build_status) { nil }
340
-
341
- before do
342
- allow(github).to receive(:build).and_return(build_status)
343
- allow(existing_pull_request).to receive(:reviewers_pending_response).and_return([])
344
- allow(existing_pull_request).to receive(:has_comments_or_approvals).and_return(true)
345
- end
346
-
347
- it "commits the changes if the build status is nil but has comments/approvals and no pending response" do
348
- expect{ subject }.to have_said "Pull request ##{existing_pull_request.number} successfully merged.", :success
349
- end
350
- end
351
-
352
- context "and the pull request has no body" do
353
- let(:first_commit_message) { "We'll do it live." }
354
-
355
- before do
356
- existing_pull_request.description = ''
357
- allow(github).to receive(:find_open_pull_request).and_return(existing_pull_request)
358
- allow(GitReflow).to receive(:get_first_commit_message).and_return(first_commit_message)
359
- allow(existing_pull_request).to receive(:reviewers).and_return(lgtm_comment_authors)
360
- end
361
- end
362
-
363
- it "doesn't always deliver" do
364
- expect(GitReflow::Config).to receive(:get).with("reflow.always-deliver").and_return("false")
365
- expect { subject }.to have_said "Merge aborted", :deliver_halted
366
- end
367
-
368
- it "notifies user of the merge and performs it" do
369
- expect { subject }.to have_said "Merging pull request ##{existing_pull_request.number}: '#{existing_pull_request.title}', from '#{existing_pull_request.head.label}' into '#{existing_pull_request.base.label}'", :notice
370
- end
371
-
372
- it "commits the changes for the squash merge" do
373
- expect{ subject }.to have_said "Pull request ##{existing_pull_request.number} successfully merged.", :success
374
- end
375
-
376
- context "and cleaning up feature branch" do
377
- before do
378
- allow_any_instance_of(HighLine).to receive(:ask) do |terminal, question|
379
- values = {
380
- "Please enter your GitHub username: " => user,
381
- "Please enter your GitHub password (we do NOT store this): " => password,
382
- "Please enter your Enterprise site URL (e.g. https://github.company.com):" => enterprise_site,
383
- "Please enter your Enterprise API endpoint (e.g. https://github.company.com/api/v3):" => enterprise_api,
384
- "Would you like to push this branch to your remote repo and cleanup your feature branch? " => 'yes',
385
- "Would you like to open it in your browser?" => 'no',
386
- "This is the current status of your Pull Request. Are you sure you want to deliver? " => 'y',
387
- "Please enter your delivery commit title: (leaving blank will use default)" => 'title',
388
- "Please enter your delivery commit message: (leaving blank will use default)" => 'message'
389
- }
390
- return_value = values[question] || values[terminal]
391
- question = ""
392
- return_value
393
- end
394
- end
395
-
396
- context "not always" do
397
- before do
398
- allow(GitReflow::Config).to receive(:get).with("reflow.always-cleanup").and_return("false")
399
- end
400
-
401
- it "pulls changes from remote repo to local branch" do
402
- expect { subject }.to have_run_command("git pull origin master")
403
- end
404
-
405
- it "deletes the remote feature branch" do
406
- expect { subject }.to have_run_command("git push origin :new-feature")
407
- end
408
-
409
- it "deletes the local feature branch" do
410
- expect { subject }.to have_run_command("git branch -D new-feature")
411
- end
412
- end
413
-
414
- context "always" do
415
- before do
416
- allow(GitReflow::Config).to receive(:get).with("reflow.always-cleanup").and_return("true")
417
- end
418
-
419
- it "checks out the base branch" do
420
- expect { subject }.to have_run_command("git checkout master")
421
- end
422
-
423
- it "pulls changes from remote repo to local branch" do
424
- expect { subject }.to have_run_command("git pull origin master")
425
- end
426
-
427
- it "deletes the remote feature branch" do
428
- expect { subject }.to have_run_command("git push origin :new-feature")
429
- end
430
-
431
- it "deletes the local feature branch" do
432
- expect { subject }.to have_run_command("git branch -D new-feature")
433
- end
434
- end
435
- end
436
-
437
- context "and not cleaning up feature branch" do
438
- before do
439
- allow_any_instance_of(HighLine).to receive(:ask) do |terminal, question|
440
- values = {
441
- "Please enter your GitHub username: " => user,
442
- "Please enter your GitHub password (we do NOT store this): " => password,
443
- "Please enter your Enterprise site URL (e.g. https://github.company.com):" => enterprise_site,
444
- "Please enter your Enterprise API endpoint (e.g. https://github.company.com/api/v3):" => enterprise_api,
445
- "Would you like to push this branch to your remote repo and cleanup your feature branch? " => 'no',
446
- "Would you like to open it in your browser?" => 'no',
447
- "This is the current status of your Pull Request. Are you sure you want to deliver? " => 'y',
448
- "Please enter your delivery commit title: (leaving blank will use default)" => 'title',
449
- "Please enter your delivery commit message: (leaving blank will use default)" => 'message'
450
- }
451
- return_value = values[question] || values[terminal]
452
- question = ""
453
- return_value
454
- end
455
- end
456
-
457
- it "does update the local repo with the new squash merge" do
458
- expect { subject }.to have_run_command('git pull origin master')
459
- end
460
-
461
- it "doesn't delete the feature branch on the remote repo" do
462
- expect { subject }.to_not have_run_command('git push origin :new-feature')
463
- end
464
-
465
- it "doesn't delete the local feature branch" do
466
- expect { subject }.to_not have_run_command('git branch -D new-feature')
467
- end
468
-
469
- it "provides instructions to undo the steps taken" do
470
- expect { subject }.to have_said("To reset and go back to your branch run \`git reset --hard origin/master && git checkout new-feature\`")
471
- end
472
- end
473
- end
474
-
475
- context 'but there are still unaddressed comments' do
476
- let(:open_comment_authors) { ['nhance', 'codenamev'] }
477
- before { allow(existing_pull_request).to receive(:reviewers_pending_response).and_return(open_comment_authors) }
478
- it "notifies the user to get their code reviewed" do
479
- expect { subject }.to have_said "You still need a LGTM from: #{open_comment_authors.join(', ')}", :deliver_halted
480
- end
481
- end
482
- end
483
-
484
- context 'but has no comments' do
485
- before do
486
- allow(existing_pull_request).to receive(:has_comments?).and_return(false)
487
- allow(existing_pull_request).to receive(:approvals).and_return(['John', 'Simon'])
488
- allow(existing_pull_request).to receive(:reviewers_pending_response).and_return([])
489
- allow(existing_pull_request).to receive(:build).and_return(build_status)
490
- end
491
-
492
- it "notifies the user to get their code reviewed" do
493
- expect { subject }.to have_said "Pull request ##{existing_pull_request.number} successfully merged.", :success
494
- end
495
- end
496
-
497
- it "successfully finds a pull request for the current feature branch" do
498
- allow(existing_pull_request).to receive(:good_to_merge?).and_return(true)
499
- allow(existing_pull_request).to receive(:approvals).and_return(["Simon"])
500
- allow(existing_pull_request).to receive(:title).and_return(inputs[:title])
501
- expect { subject }.to have_said "Merging pull request #1: 'new-feature', from 'new-feature' into 'master'", :notice
502
- end
503
-
504
- it "merges and squashes the feature branch into the master branch" do
505
- allow(existing_pull_request).to receive(:good_to_merge?).and_return(true)
506
- allow(existing_pull_request).to receive(:approvals).and_return(["Simon"])
507
- allow(existing_pull_request).to receive(:title).and_return(inputs[:title])
508
- expect(existing_pull_request).to receive(:merge!).and_return(true)
509
- subject
510
- end
511
- end
512
- end
513
-
514
- context "and no pull request exists for the feature branch to the destination branch" do
515
- before { allow(github).to receive(:find_open_pull_request).and_return(nil) }
516
-
517
- it "notifies the user of a missing pull request" do
518
- expect { subject }.to have_said "No pull request exists for #{user}:#{branch}\nPlease submit your branch for review first with \`git reflow review\`", :deliver_halted
519
- end
520
- end
521
- end
522
- end