git_reflow 0.8.6 → 0.8.7

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.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +348 -348
  4. data/Gemfile.lock +13 -15
  5. data/LICENSE +20 -20
  6. data/README.rdoc +461 -461
  7. data/Rakefile +8 -8
  8. data/bin/console +7 -7
  9. data/bin/setup +6 -6
  10. data/circle.yml +5 -5
  11. data/exe/git-reflow +36 -36
  12. data/git_reflow.gemspec +1 -1
  13. data/lib/git_reflow/commands/deliver.rb +10 -10
  14. data/lib/git_reflow/commands/refresh.rb +20 -20
  15. data/lib/git_reflow/commands/review.rb +13 -13
  16. data/lib/git_reflow/commands/setup.rb +11 -11
  17. data/lib/git_reflow/commands/stage.rb +9 -9
  18. data/lib/git_reflow/commands/start.rb +22 -22
  19. data/lib/git_reflow/commands/status.rb +7 -7
  20. data/lib/git_reflow/config.rb +9 -9
  21. data/lib/git_reflow/git_server/base.rb +68 -68
  22. data/lib/git_reflow/git_server/bit_bucket/pull_request.rb +84 -84
  23. data/lib/git_reflow/git_server/bit_bucket.rb +101 -101
  24. data/lib/git_reflow/git_server/git_hub/pull_request.rb +4 -1
  25. data/lib/git_reflow/git_server/pull_request.rb +11 -2
  26. data/lib/git_reflow/git_server.rb +63 -63
  27. data/lib/git_reflow/logger.rb +49 -0
  28. data/lib/git_reflow/merge_error.rb +9 -9
  29. data/lib/git_reflow/os_detector.rb +23 -23
  30. data/lib/git_reflow/rspec/command_line_helpers.rb +12 -8
  31. data/lib/git_reflow/rspec/stub_helpers.rb +13 -13
  32. data/lib/git_reflow/rspec.rb +2 -2
  33. data/lib/git_reflow/sandbox.rb +11 -6
  34. data/lib/git_reflow/version.rb +1 -1
  35. data/lib/git_reflow/workflow.rb +59 -59
  36. data/lib/git_reflow/workflows/core.rb +238 -238
  37. data/lib/git_reflow/workflows/flat_merge.rb +10 -10
  38. data/lib/git_reflow.rb +11 -0
  39. data/spec/fixtures/awesome_workflow.rb +7 -0
  40. data/spec/fixtures/git/git_config +7 -0
  41. data/spec/fixtures/issues/comment.json.erb +27 -0
  42. data/spec/fixtures/issues/comments.json +29 -0
  43. data/spec/fixtures/issues/comments.json.erb +15 -0
  44. data/spec/fixtures/pull_requests/comment.json.erb +45 -0
  45. data/spec/fixtures/pull_requests/comments.json +47 -0
  46. data/spec/fixtures/pull_requests/comments.json.erb +15 -0
  47. data/spec/fixtures/pull_requests/commits.json +29 -0
  48. data/spec/fixtures/pull_requests/external_pull_request.json +145 -0
  49. data/spec/fixtures/pull_requests/pull_request.json +142 -0
  50. data/spec/fixtures/pull_requests/pull_request.json.erb +142 -0
  51. data/spec/fixtures/pull_requests/pull_request_exists_error.json +32 -0
  52. data/spec/fixtures/pull_requests/pull_requests.json +136 -0
  53. data/spec/fixtures/repositories/commit.json +53 -0
  54. data/spec/fixtures/repositories/commit.json.erb +53 -0
  55. data/spec/fixtures/repositories/commits.json.erb +13 -0
  56. data/spec/fixtures/repositories/statuses.json +31 -0
  57. data/spec/fixtures/workflow_with_super.rb +8 -0
  58. data/spec/lib/git_reflow/config_spec.rb +74 -0
  59. data/spec/lib/git_reflow/git_helpers_spec.rb +182 -0
  60. data/spec/lib/git_reflow/git_server/bit_bucket_spec.rb +81 -0
  61. data/spec/lib/git_reflow/git_server/git_hub/pull_request_spec.rb +587 -0
  62. data/spec/lib/git_reflow/git_server/git_hub_spec.rb +221 -0
  63. data/spec/lib/git_reflow/git_server/pull_request_spec.rb +524 -0
  64. data/spec/lib/git_reflow/git_server_spec.rb +101 -0
  65. data/spec/lib/git_reflow/logger_spec.rb +18 -0
  66. data/spec/lib/git_reflow/sandbox_spec.rb +15 -0
  67. data/spec/lib/git_reflow/workflow_spec.rb +59 -0
  68. data/spec/lib/git_reflow/workflows/core_spec.rb +665 -0
  69. data/spec/lib/git_reflow/workflows/flat_merge_spec.rb +59 -0
  70. data/spec/lib/git_reflow_spec.rb +75 -0
  71. data/spec/spec_helper.rb +38 -0
  72. data/spec/support/fake_github.rb +128 -0
  73. data/spec/support/fixtures.rb +54 -0
  74. data/spec/support/github_helpers.rb +109 -0
  75. data/spec/support/mock_pull_request.rb +17 -0
  76. data/spec/support/web_mocks.rb +39 -0
  77. metadata +83 -6
@@ -0,0 +1,587 @@
1
+ require 'spec_helper'
2
+
3
+ describe GitReflow::GitServer::GitHub::PullRequest do
4
+ let(:user) { 'reenhanced' }
5
+ let(:password) { 'shazam' }
6
+ let(:repo) { 'repo' }
7
+ let(:oauth_token_hash) { Hashie::Mash.new({ token: 'a1b2c3d4e5f6g7h8i9j0'}) }
8
+ let(:hostname) { 'hostname.local' }
9
+ let(:github_site) { 'https://github.com' }
10
+ let(:github_api_endpoint) { 'https://api.github.com' }
11
+ let(:enterprise_site) { 'https://github.gittyup.com' }
12
+ let(:enterprise_api) { 'https://github.gittyup.com/api/v3' }
13
+ let(:github) { stub_github_with }
14
+ let!(:github_api) { github.connection }
15
+ let(:existing_pull_request) { Fixture.new('pull_requests/external_pull_request.json').to_json_hashie }
16
+ let(:existing_pull_requests) { Fixture.new('pull_requests/pull_requests.json').to_json_hashie }
17
+ let(:existing_pull_commits) { Fixture.new('pull_requests/commits.json').to_json_hashie }
18
+ let(:comment_author) { 'octocat' }
19
+ let(:feature_branch_name) { existing_pull_request.head.label[/[^:]+$/] }
20
+ let(:base_branch_name) { existing_pull_request.base.label[/[^:]+$/] }
21
+ let(:existing_pull_comments) {
22
+ Fixture.new('pull_requests/comments.json.erb',
23
+ repo_owner: user,
24
+ repo_name: repo,
25
+ comments: [{author: comment_author}],
26
+ pull_request_number: existing_pull_request.number).to_json_hashie }
27
+ let(:existing_issue_comments) {
28
+ Fixture.new('issues/comments.json.erb',
29
+ repo_owner: user,
30
+ repo_name: repo,
31
+ comments: [{author: comment_author}],
32
+ pull_request_number: existing_pull_request.number).to_json_hashie }
33
+
34
+ let(:pr) { GitReflow::GitServer::GitHub::PullRequest.new(existing_pull_request) }
35
+
36
+
37
+ before do
38
+ stub_command_line_inputs({
39
+ "Please enter your GitHub username: " => user,
40
+ "Please enter your GitHub password (we do NOT store this): " => password,
41
+ "Please enter your Enterprise site URL (e.g. https://github.company.com):" => enterprise_site,
42
+ "Please enter your Enterprise API endpoint (e.g. https://github.company.com/api/v3):" => enterprise_api
43
+ })
44
+
45
+ allow(github.class).to receive(:remote_user).and_return(user)
46
+ allow(github.class).to receive(:remote_repo_name).and_return(repo)
47
+ allow(GitReflow::GitServer::PullRequest).to receive(:approval_regex).and_return(/(?i-mx:lgtm|looks good to me|:\+1:|:thumbsup:|:shipit:)/)
48
+ end
49
+
50
+ describe '#initialize(options)' do
51
+ specify { expect(pr.number).to eql(existing_pull_request.number) }
52
+ specify { expect(pr.description).to eql(existing_pull_request.body) }
53
+ specify { expect(pr.html_url).to eql(existing_pull_request.html_url) }
54
+ specify { expect(pr.feature_branch_name).to eql(feature_branch_name) }
55
+ specify { expect(pr.base_branch_name).to eql(base_branch_name) }
56
+ specify { expect(pr.build_status).to eql('success') }
57
+ specify { expect(pr.source_object).to eql(existing_pull_request) }
58
+ end
59
+
60
+ describe '#commit_author' do
61
+ subject { pr.commit_author }
62
+
63
+ before do
64
+ stub_request(:get, %r{#{GitReflow.git_server.class.api_endpoint}/repos/#{user}/#{repo}/pulls/#{existing_pull_request.number}/commits}).
65
+ with(query: {"access_token" => "a1b2c3d4e5f6g7h8i9j0"}).
66
+ to_return(:body => Fixture.new("pull_requests/commits.json").to_s, status: 201, headers: {content_type: "application/json; charset=utf-8"})
67
+ end
68
+ specify { expect(subject).to eql("#{existing_pull_commits.first.commit.author.name} <#{existing_pull_commits.first.commit.author.email}>") }
69
+ end
70
+
71
+ describe '#comments' do
72
+ subject { pr.comments }
73
+
74
+ context "Testing Appending of Comments" do
75
+ before do
76
+ FakeGitHub.new(
77
+ repo_owner: user,
78
+ repo_name: repo,
79
+ pull_request: {
80
+ number: existing_pull_request.number,
81
+ comments: [{author: comment_author}]
82
+ },
83
+ issue: {
84
+ number: existing_pull_request.number,
85
+ comments: [{author: comment_author}]
86
+ })
87
+ end
88
+ specify { expect(subject).to eql(existing_pull_comments.to_a + existing_issue_comments.to_a) }
89
+ end
90
+
91
+ context "Testing Nil Comments" do
92
+ before do
93
+ stub_request(:get, "https://api.github.com/repos/reenhanced/repo/pulls/2/comments?access_token=a1b2c3d4e5f6g7h8i9j0").
94
+ with(:headers => {'Accept'=>'application/vnd.github.v3+json,application/vnd.github.beta+json;q=0.5,application/json;q=0.1', 'Accept-Charset'=>'utf-8', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'token a1b2c3d4e5f6g7h8i9j0', 'User-Agent'=>'Github API Ruby Gem 0.15.0'}).
95
+ to_return(:status => 200, :body => "", :headers => {})
96
+
97
+ FakeGitHub.new(
98
+ repo_owner: user,
99
+ repo_name: repo,
100
+ pull_request: {
101
+ number: existing_pull_request.number,
102
+ comments: nil
103
+ },
104
+ issue: {
105
+ number: existing_pull_request.number,
106
+ comments: nil
107
+ })
108
+ end
109
+ specify { expect(subject).to eql([]) }
110
+ end
111
+ end
112
+
113
+ describe '#reviewers' do
114
+ subject { pr.reviewers }
115
+
116
+ before do
117
+ allow(existing_pull_request.user).to receive(:login).and_return('ringo')
118
+
119
+ FakeGitHub.new(
120
+ repo_owner: user,
121
+ repo_name: repo,
122
+ pull_request: {
123
+ number: existing_pull_request.number,
124
+ owner: existing_pull_request.user.login,
125
+ comments: [{author: 'tito'}, {author: 'bobby'}, {author: 'ringo'}]
126
+ },
127
+ issue: {
128
+ number: existing_pull_request.number,
129
+ comments: [{author: 'ringo'}, {author: 'randy'}]
130
+ })
131
+ end
132
+
133
+ specify { expect(subject).to eq(['tito', 'bobby', 'randy']) }
134
+ end
135
+
136
+
137
+ describe "#approved?" do
138
+ subject { pr.approved? }
139
+
140
+ context "no approvals and build success" do
141
+ before do
142
+ FakeGitHub.new(
143
+ repo_owner: user,
144
+ repo_name: repo,
145
+ pull_request: {
146
+ number: existing_pull_request.number,
147
+ owner: existing_pull_request.head.user.login,
148
+ comments: []
149
+ })
150
+ allow(GitReflow::GitServer::GitHub::PullRequest).to receive(:minimum_approvals).and_return("0")
151
+ end
152
+ specify { expect(subject).to be_truthy }
153
+ end
154
+
155
+ context "all commenters must approve and minimum_approvals is nil" do
156
+ before do
157
+ FakeGitHub.new(
158
+ repo_owner: user,
159
+ repo_name: repo,
160
+ pull_request: {
161
+ number: existing_pull_request.number,
162
+ owner: existing_pull_request.head.user.login,
163
+ comments: []
164
+ })
165
+ allow(GitReflow::GitServer::GitHub::PullRequest).to receive(:minimum_approvals).and_return(nil)
166
+ allow(pr).to receive(:has_comments?).and_return(true)
167
+ allow(pr).to receive(:approvals).and_return(["Simon"])
168
+ allow(pr).to receive(:reviewers_pending_response).and_return([])
169
+ end
170
+ specify { expect(subject).to be_truthy }
171
+ end
172
+
173
+ context "all commenters must approve but we have no pending reviewers" do
174
+ before do
175
+ FakeGitHub.new(
176
+ repo_owner: user,
177
+ repo_name: repo,
178
+ pull_request: {
179
+ number: existing_pull_request.number,
180
+ owner: existing_pull_request.head.user.login,
181
+ comments: []
182
+ })
183
+ allow(GitReflow::GitServer::GitHub::PullRequest).to receive(:minimum_approvals).and_return("")
184
+ allow(pr).to receive(:has_comments?).and_return(true)
185
+ allow(pr).to receive(:approvals).and_return(["Simon"])
186
+ allow(pr).to receive(:reviewers_pending_response).and_return([])
187
+ end
188
+ specify { expect(subject).to be_truthy }
189
+ end
190
+
191
+ context "all commenters must approve but we have 1 pending reviewer" do
192
+ before do
193
+ FakeGitHub.new(
194
+ repo_owner: user,
195
+ repo_name: repo,
196
+ pull_request: {
197
+ number: existing_pull_request.number,
198
+ owner: existing_pull_request.head.user.login,
199
+ comments: []
200
+ })
201
+ allow(GitReflow::GitServer::GitHub::PullRequest).to receive(:minimum_approvals).and_return("")
202
+ allow(pr).to receive(:has_comments?).and_return(true)
203
+ allow(pr).to receive(:approvals).and_return(["Simon"])
204
+ allow(pr).to receive(:reviewers_pending_response).and_return(["Simon"])
205
+ end
206
+ specify { expect(subject).to be_falsy }
207
+ end
208
+
209
+ context "2 approvals required but we only have 1 approval" do
210
+ before do
211
+ FakeGitHub.new(
212
+ repo_owner: user,
213
+ repo_name: repo,
214
+ pull_request: {
215
+ number: existing_pull_request.number,
216
+ owner: existing_pull_request.head.user.login,
217
+ comments: []
218
+ })
219
+ allow(GitReflow::GitServer::GitHub::PullRequest).to receive(:minimum_approvals).and_return("2")
220
+ allow(pr).to receive(:approvals).and_return(["Simon"])
221
+ allow(pr).to receive(:last_comment).and_return("LGTM")
222
+ end
223
+ specify { expect(subject).to be_falsy }
224
+ end
225
+
226
+ context "2 approvals required and we have 2 approvals but last comment is not approval" do
227
+ before do
228
+ FakeGitHub.new(
229
+ repo_owner: user,
230
+ repo_name: repo,
231
+ pull_request: {
232
+ number: existing_pull_request.number,
233
+ owner: existing_pull_request.head.user.login,
234
+ comments: []
235
+ })
236
+ allow(GitReflow::GitServer::GitHub::PullRequest).to receive(:minimum_approvals).and_return("2")
237
+ allow(pr).to receive(:approvals).and_return(["Simon", "Peter"])
238
+ allow(pr).to receive(:last_comment).and_return("Boo")
239
+ end
240
+ specify { expect(subject).to be_falsy }
241
+ end
242
+
243
+ context "2 approvals required and we have 2 approvals and last comment is approval" do
244
+ before do
245
+ FakeGitHub.new(
246
+ repo_owner: user,
247
+ repo_name: repo,
248
+ pull_request: {
249
+ number: existing_pull_request.number,
250
+ owner: existing_pull_request.head.user.login,
251
+ comments: []
252
+ })
253
+ allow(GitReflow::GitServer::GitHub::PullRequest).to receive(:minimum_approvals).and_return("2")
254
+ allow(pr).to receive(:approvals).and_return(["Simon", "Peter"])
255
+ allow(pr).to receive(:last_comment).and_return("LGTM")
256
+ end
257
+ specify { expect(subject).to be_truthy }
258
+ end
259
+ end
260
+
261
+ describe '#approvals' do
262
+ subject { pr.approvals }
263
+
264
+ context "no comments" do
265
+ before do
266
+ FakeGitHub.new(
267
+ repo_owner: user,
268
+ repo_name: repo,
269
+ pull_request: {
270
+ number: existing_pull_request.number,
271
+ owner: existing_pull_request.head.user.login,
272
+ comments: []
273
+ })
274
+ end
275
+
276
+ specify { expect(subject).to eq([]) }
277
+ end
278
+
279
+ context "single reviewer without approval" do
280
+ before do
281
+ FakeGitHub.new(
282
+ repo_owner: user,
283
+ repo_name: repo,
284
+ pull_request: {
285
+ number: existing_pull_request.number,
286
+ owner: existing_pull_request.head.user.login,
287
+ comments: [{author: 'tito', body: 'This is some funky stuff'}]
288
+ })
289
+ end
290
+
291
+ specify { expect(subject).to eq([]) }
292
+ end
293
+
294
+ context "single reviewer with approval" do
295
+ before do
296
+ FakeGitHub.new(
297
+ repo_owner: user,
298
+ repo_name: repo,
299
+ pull_request: {
300
+ number: existing_pull_request.number,
301
+ owner: existing_pull_request.head.user.login,
302
+ comments: [{author: 'tito', body: 'LGTM'}]
303
+ })
304
+ end
305
+
306
+ specify { expect(subject).to eq(['tito']) }
307
+
308
+ context "but a new commit has been introduced" do
309
+ before do
310
+ FakeGitHub.new(
311
+ repo_owner: user,
312
+ repo_name: repo,
313
+ commits: [
314
+ {
315
+ author: user,
316
+ pull_request_number: existing_pull_request.number,
317
+ created_at: Chronic.parse("1 second ago")
318
+ }
319
+ ],
320
+ pull_request: {
321
+ number: existing_pull_request.number,
322
+ owner: existing_pull_request.head.user.login,
323
+ comments: [{author: 'tito', body: 'LGTM', created_at: Chronic.parse('1 minute ago')}]
324
+ })
325
+ end
326
+
327
+ specify { expect(subject).to eq([]) }
328
+ end
329
+ end
330
+
331
+ context "multiple reviewers with only one approval" do
332
+ before do
333
+ FakeGitHub.new(
334
+ repo_owner: user,
335
+ repo_name: repo,
336
+ pull_request: {
337
+ number: existing_pull_request.number,
338
+ owner: existing_pull_request.head.user.login,
339
+ comments: [{author: 'tito', body: 'LGTM'}, {author: 'ringo', body: 'Needs more cowbell.'}]
340
+ })
341
+ end
342
+
343
+ specify { expect(subject).to eq(['tito']) }
344
+ end
345
+
346
+ context "multiple reviewers with all approvals" do
347
+ before do
348
+ FakeGitHub.new(
349
+ repo_owner: user,
350
+ repo_name: repo,
351
+ pull_request: {
352
+ number: existing_pull_request.number,
353
+ owner: existing_pull_request.head.user.login,
354
+ comments: [{author: 'tito', body: 'lgtm'}, {author: 'ringo', body: ':+1:'}]
355
+ })
356
+
357
+ allow(GitReflow::GitServer::GitHub::PullRequest).to receive(:approval_regex).and_return(/(?i-mx:lgtm|looks good to me|:\+1:|:thumbsup:|:shipit:)/)
358
+ end
359
+
360
+ context "2 approvals" do
361
+ specify { expect(subject).to eq(['tito', 'ringo']) }
362
+ end
363
+
364
+ context "but a new commit has been introduced" do
365
+ before do
366
+ FakeGitHub.new(
367
+ repo_owner: user,
368
+ repo_name: repo,
369
+ commits: [
370
+ {
371
+ author: user,
372
+ pull_request_number: existing_pull_request.number,
373
+ created_at: Chronic.parse("1 second ago")
374
+ }
375
+ ],
376
+ pull_request: {
377
+ number: existing_pull_request.number,
378
+ owner: existing_pull_request.head.user.login,
379
+ comments: [{author: 'tito', body: 'lgtm', created_at: Chronic.parse('1 minute ago')}, {author: 'ringo', body: ':+1:', created_at: Chronic.parse('1 minute ago')}]
380
+ })
381
+ end
382
+
383
+ specify { expect(subject).to eq([]) }
384
+ end
385
+ end
386
+
387
+ end
388
+
389
+ describe '#last_comment' do
390
+ subject { pr.last_comment }
391
+
392
+ before do
393
+ FakeGitHub.new(
394
+ repo_owner: user,
395
+ repo_name: repo,
396
+ pull_request: {
397
+ number: existing_pull_request.number,
398
+ owner: existing_pull_request.head.user.login,
399
+ comments: [{author: 'tito', body: 'lgtm'}, {author: 'ringo', body: 'Cha cha cha'}]
400
+ })
401
+ end
402
+
403
+ specify { expect(subject).to eq('"Cha cha cha"') }
404
+ end
405
+
406
+ describe '#build' do
407
+ let(:build) { Fixture.new('repositories/statuses.json').to_json_hashie.first }
408
+
409
+ subject { pr.build }
410
+
411
+ context "with an existing build" do
412
+ specify { expect(subject.state).to eq(build.state) }
413
+ specify { expect(subject.description).to eq(build.description) }
414
+ specify { expect(subject.url).to eq(build.target_url) }
415
+ end
416
+
417
+ context "no build found" do
418
+ before { allow(GitReflow.git_server).to receive(:get_build_status).and_return(nil) }
419
+ specify { expect(subject.state).to eq(nil) }
420
+ specify { expect(subject.description).to eq(nil) }
421
+ specify { expect(subject.url).to eq(nil) }
422
+ end
423
+ end
424
+
425
+ describe '#merge!' do
426
+ let(:inputs) do
427
+ {
428
+ :base => "base_branch",
429
+ :title => "title",
430
+ :message => "message"
431
+ }
432
+ end
433
+
434
+ let(:lgtm_comment_authors) {
435
+ ["simonzhu24", "reenhanced"]
436
+ }
437
+
438
+ let(:merge_response) { { :message => "Failure_Message" } }
439
+
440
+ subject { pr.merge! inputs }
441
+
442
+ before do
443
+ allow(GitReflow).to receive(:git_server).and_return(github)
444
+ allow(GitReflow::Config).to receive(:get)
445
+ allow(GitReflow.git_server).to receive(:connection).and_return(github_api)
446
+ allow(GitReflow.git_server).to receive(:get_build_status).and_return(Struct.new(:state, :description, :target_url).new())
447
+ allow_any_instance_of(GitReflow::GitServer::PullRequest).to receive(:commit_message_for_merge).and_return('Bingo')
448
+ allow_any_instance_of(GitReflow).to receive(:append_to_squashed_commit_message).and_return(true)
449
+ end
450
+
451
+ context "and force-merging" do
452
+ let(:inputs) do
453
+ {
454
+ base: "base_branch",
455
+ title: "title",
456
+ message: "message",
457
+ skip_lgtm: true
458
+ }
459
+ end
460
+
461
+ before { allow_any_instance_of(GitReflow::GitServer::PullRequest).to receive(:deliver?).and_return(true) }
462
+
463
+ it "falls back on manual squash merge" do
464
+ expect { subject }.to have_run_command "git merge --squash #{feature_branch_name}"
465
+ end
466
+ end
467
+
468
+ context "and always deliver is set" do
469
+ before do
470
+ allow(GitReflow::Config).to receive(:get).with('reflow.always-deliver').and_return('true')
471
+ allow(github_api).to receive_message_chain(:pull_requests, :merge).and_return(double(success?: true))
472
+ end
473
+
474
+ it "doesn't ask to confirm deliver" do
475
+ expect(pr).to_not receive(:ask).with('This is the current status of your Pull Request. Are you sure you want to deliver? ')
476
+ subject
477
+ end
478
+ end
479
+
480
+ context "and not suqash merging" do
481
+ let(:inputs) do
482
+ {
483
+ base: "base_branch",
484
+ title: "title",
485
+ message: "message",
486
+ merge_method: "merge"
487
+ }
488
+ end
489
+
490
+ before do
491
+ allow_any_instance_of(GitReflow::GitServer::PullRequest).to receive(:deliver?).and_return(true)
492
+ allow(github_api).to receive_message_chain(:pull_requests, :merge).and_return(double(success?: true))
493
+ end
494
+
495
+ it "doesn't ask Github to squash merge" do
496
+ expect(github_api).to receive_message_chain(:pull_requests, :merge).with(
497
+ user,
498
+ repo,
499
+ pr.number.to_s,
500
+ {
501
+ "commit_title" => "#{inputs[:title]}",
502
+ "commit_message" => "#{inputs[:message]}\n",
503
+ "sha" => pr.head.sha,
504
+ "merge_method" => "merge"
505
+ }
506
+ )
507
+
508
+ subject
509
+ end
510
+ end
511
+
512
+ context "finds pull request but merge response fails" do
513
+ before do
514
+ allow(GitReflow::GitServer::GitHub).to receive_message_chain(:connection, :pull_requests, :merge).and_return(merge_response)
515
+ allow(merge_response).to receive(:success?).and_return(false)
516
+ allow_any_instance_of(GitReflow::GitServer::GitHub::PullRequest).to receive(:approvals).and_return(lgtm_comment_authors)
517
+ allow(pr).to receive(:deliver?).and_return(true)
518
+ allow(merge_response).to receive(:to_s).and_return("Merge failed")
519
+ end
520
+
521
+ it "throws an error" do
522
+ expect { subject }.to have_said "Merge failed", :deliver_halted
523
+ expect { subject }.to have_said "There were problems commiting your feature... please check the errors above and try again.", :error
524
+ end
525
+ end
526
+ end
527
+
528
+ describe '.create(options)' do
529
+ let(:title) { 'Bone Saw is ready!' }
530
+ let(:body) { 'Snap into a Slim Jim!' }
531
+ let(:base_branch_name) { 'base-branch' }
532
+ let(:pull_request_response) do
533
+ Fixture.new('pull_requests/pull_request.json.erb',
534
+ number: 2,
535
+ title: title,
536
+ body: body,
537
+ base_branch: base_branch_name,
538
+ repo_owner: user,
539
+ repo_name: repo)
540
+ end
541
+
542
+ subject { GitReflow::GitServer::GitHub::PullRequest.create(title: title, body: body, base: base_branch_name) }
543
+
544
+ before do
545
+ stub_request(:post, %r{/repos/#{user}/#{repo}/pulls}).
546
+ to_return(body: pull_request_response.to_s, status: 201, headers: {content_type: "application/json; charset=utf-8"})
547
+ end
548
+
549
+ specify { expect(subject.class.to_s).to eql('GitReflow::GitServer::GitHub::PullRequest') }
550
+ specify { expect(subject.title).to eql(title) }
551
+ specify { expect(subject.description).to eql(body) }
552
+ specify { expect(subject.base_branch_name).to eql(base_branch_name) }
553
+ end
554
+
555
+ describe '.find_open(options)' do
556
+ let(:feature_branch) { 'new-feature' }
557
+ let(:base_branch) { 'base-branch' }
558
+
559
+ subject { GitReflow::GitServer::GitHub::PullRequest.find_open(from: feature_branch, to: base_branch) }
560
+
561
+ before do
562
+ allow(GitReflow.git_server.class).to receive(:current_branch).and_return(feature_branch)
563
+ FakeGitHub.new(
564
+ repo_owner: user,
565
+ repo_name: repo,
566
+ pull_request: {
567
+ number: existing_pull_request.number,
568
+ owner: existing_pull_request.head.user.login,
569
+ base_branch: base_branch,
570
+ feature_branch: feature_branch
571
+ })
572
+ end
573
+
574
+ specify { expect(subject.class.to_s).to eql('GitReflow::GitServer::GitHub::PullRequest') }
575
+ specify { expect(subject.number).to eql(existing_pull_request.number) }
576
+
577
+ context "without any options" do
578
+ let(:base_branch) { 'master' }
579
+ subject { GitReflow::GitServer::GitHub::PullRequest.find_open() }
580
+ it "defaults to the current branch as the feature branch and 'master' as the base branch" do
581
+ expect(subject.class.to_s).to eql('GitReflow::GitServer::GitHub::PullRequest')
582
+ expect(subject.number).to eql(existing_pull_request.number)
583
+ end
584
+ end
585
+ end
586
+
587
+ end