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