git_reflow 0.7.4 → 0.7.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c6773486dad59a6ec3d71cd0047234005b8d06f1
|
4
|
+
data.tar.gz: 07665f57499a6aab0bd31218a0bf8d5e147c8581
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 930b0d1bb58185c59c0d759ef2aad44a10d2b2481bd78843f842c4b703c4b4770a29574cb34be888d01035db40fd66f10df45e343427c2fafee37e06791a1602
|
7
|
+
data.tar.gz: 8aa0cbcf0db37dcbb527f2275cef16125d7f736a18787700e1fc16c2934b68ac75f0f0e2713d1790c5e90efca256926be9df200f3baa61ae8aae427411facd1c
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
git_reflow (0.7.
|
4
|
+
git_reflow (0.7.5)
|
5
5
|
colorize (>= 0.7.0)
|
6
6
|
github_api (= 0.12.4)
|
7
7
|
gli (= 2.13.2)
|
@@ -104,13 +104,13 @@ PLATFORMS
|
|
104
104
|
|
105
105
|
DEPENDENCIES
|
106
106
|
appraisal (= 1.0.3)
|
107
|
-
bundler
|
107
|
+
bundler (~> 1.11)
|
108
108
|
chronic
|
109
109
|
git_reflow!
|
110
110
|
pry-byebug
|
111
|
-
rake
|
111
|
+
rake (~> 10.0)
|
112
112
|
rdoc
|
113
|
-
rspec (~> 3.0
|
113
|
+
rspec (~> 3.0)
|
114
114
|
webmock
|
115
115
|
wwtd (= 0.7.0)
|
116
116
|
|
data/Rakefile
CHANGED
@@ -1,11 +1,8 @@
|
|
1
1
|
#!/usr/bin/env rake
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require 'bundler/setup'
|
5
|
-
require 'rspec/core/rake_task'
|
6
|
-
|
7
|
-
Dir[File.join(File.dirname(__FILE__),'lib/tasks/*.rake')].each { |f| load f }
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
require "rspec/core/rake_task"
|
8
4
|
|
9
5
|
RSpec::Core::RakeTask.new(:spec)
|
10
6
|
|
11
|
-
task :default =>
|
7
|
+
task :default => :spec
|
8
|
+
|
data/bin/console
ADDED
data/bin/setup
ADDED
data/{bin → exe}/git-reflow
RENAMED
File without changes
|
data/git_reflow.gemspec
CHANGED
@@ -10,22 +10,22 @@ spec = Gem::Specification.new do |s|
|
|
10
10
|
s.summary = "A better git process"
|
11
11
|
s.description = "Git Reflow manages your git workflow."
|
12
12
|
s.platform = Gem::Platform::RUBY
|
13
|
-
s.files = `git ls-files`.split("\
|
13
|
+
s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
14
14
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
15
|
-
s.executables =
|
15
|
+
s.executables = s.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
16
16
|
s.has_rdoc = true
|
17
17
|
s.extra_rdoc_files = ['README.rdoc']
|
18
|
-
s.bindir =
|
19
|
-
s.require_paths
|
18
|
+
s.bindir = "exe"
|
19
|
+
s.require_paths = ["lib"]
|
20
20
|
s.rdoc_options << '--title' << 'git_reflow' << '--main' << 'README.rdoc' << '-ri'
|
21
21
|
|
22
22
|
s.add_development_dependency('appraisal', '1.0.3')
|
23
|
-
s.add_development_dependency('bundler')
|
23
|
+
s.add_development_dependency('bundler', "~> 1.11")
|
24
24
|
s.add_development_dependency('chronic')
|
25
25
|
s.add_development_dependency('pry-byebug')
|
26
|
-
s.add_development_dependency('rake')
|
26
|
+
s.add_development_dependency('rake', "~> 10.0")
|
27
27
|
s.add_development_dependency('rdoc')
|
28
|
-
s.add_development_dependency('rspec',
|
28
|
+
s.add_development_dependency('rspec', "~> 3.0")
|
29
29
|
s.add_development_dependency('webmock')
|
30
30
|
s.add_development_dependency('wwtd', '0.7.0')
|
31
31
|
|
@@ -15,11 +15,15 @@ command :setup do |c|
|
|
15
15
|
end
|
16
16
|
|
17
17
|
choose do |menu|
|
18
|
-
menu.header = "Available remote Git Server services
|
18
|
+
menu.header = "Available remote Git Server services"
|
19
19
|
menu.prompt = "Which service would you like to use for this project? "
|
20
20
|
|
21
21
|
menu.choice('GitHub') { GitReflow::GitServer.connect reflow_options.merge({ provider: 'GitHub', silent: false }) }
|
22
22
|
menu.choice('BitBucket (team-owned repos only)') { GitReflow::GitServer.connect reflow_options.merge({ provider: 'BitBucket', silent: false }) }
|
23
23
|
end
|
24
|
+
|
25
|
+
GitReflow::Config.add "constants.minimumApprovals", ask("Set the minimum number of approvals (leaving blank will require approval from all commenters): "), local: reflow_options[:project_only]
|
26
|
+
GitReflow::Config.add "constants.approvalRegex", GitReflow::GitServer::PullRequest::DEFAULT_APPROVAL_REGEX, local: reflow_options[:project_only]
|
27
|
+
|
24
28
|
end
|
25
29
|
end
|
@@ -52,7 +52,7 @@ module GitReflow
|
|
52
52
|
|
53
53
|
def approvals
|
54
54
|
pull_last_committed_at = get_committed_time(self.head.sha)
|
55
|
-
comment_authors(with:
|
55
|
+
comment_authors(with: self.class.approval_regex, after: pull_last_committed_at)
|
56
56
|
end
|
57
57
|
|
58
58
|
def comments
|
@@ -63,7 +63,19 @@ module GitReflow
|
|
63
63
|
end
|
64
64
|
|
65
65
|
def last_comment
|
66
|
-
|
66
|
+
if comments.last.nil?
|
67
|
+
""
|
68
|
+
else
|
69
|
+
"#{comments.last.body.inspect}"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def approved?
|
74
|
+
if self.class.minimum_approvals.to_i == 0
|
75
|
+
super
|
76
|
+
else
|
77
|
+
approvals.size >= self.class.minimum_approvals.to_i and !last_comment.match(self.class.approval_regex).nil?
|
78
|
+
end
|
67
79
|
end
|
68
80
|
|
69
81
|
def build
|
@@ -3,6 +3,20 @@ module GitReflow
|
|
3
3
|
class PullRequest
|
4
4
|
attr_accessor :description, :html_url, :feature_branch_name, :base_branch_name, :build_status, :source_object, :number
|
5
5
|
|
6
|
+
DEFAULT_APPROVAL_REGEX = /(?i-mx:lgtm|looks good to me|:\+1:|:thumbsup:|:shipit:)/
|
7
|
+
|
8
|
+
def self.minimum_approvals
|
9
|
+
"#{GitReflow::Config.get('constants.minimumApprovals')}"
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.approval_regex
|
13
|
+
if "#{GitReflow::Config.get('constants.approvalRegex')}".length > 0
|
14
|
+
Regexp.new("#{GitReflow::Config.get('constants.approvalRegex')}")
|
15
|
+
else
|
16
|
+
DEFAULT_APPROVAL_REGEX
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
6
20
|
def initialize(attributes)
|
7
21
|
raise "PullRequest#initialize must be implemented"
|
8
22
|
end
|
@@ -35,13 +49,47 @@ module GitReflow
|
|
35
49
|
reviewers - approvals
|
36
50
|
end
|
37
51
|
|
52
|
+
def approved?
|
53
|
+
has_comments_or_approvals = (has_comments? or approvals.any?)
|
54
|
+
|
55
|
+
case self.class.minimum_approvals
|
56
|
+
when "0"
|
57
|
+
true
|
58
|
+
when "", nil
|
59
|
+
# Approvals from every commenter
|
60
|
+
has_comments_or_approvals && reviewers_pending_response.empty?
|
61
|
+
else
|
62
|
+
approvals.size >= self.class.minimum_approvals.to_i
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def rejection_message
|
67
|
+
if !build_status.nil? and build_status != "success"
|
68
|
+
"#{build.description}: #{build.url}"
|
69
|
+
elsif !approval_minimums_reached?
|
70
|
+
"You need approval from at least #{self.class.minimum_approvals} users!"
|
71
|
+
elsif !all_comments_addressed?
|
72
|
+
# Maybe add what the last comment is?
|
73
|
+
"The last comment is holding up approval:\n#{last_comment}"
|
74
|
+
elsif reviewers_pending_response.count > 0
|
75
|
+
"You still need a LGTM from: #{reviewers_pending_response.join(', ')}"
|
76
|
+
else
|
77
|
+
"Your code has not been reviewed yet."
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def approval_minimums_reached?
|
82
|
+
self.class.minimum_approvals.length <= 0 or approvals.size >= self.class.minimum_approvals.to_i
|
83
|
+
end
|
84
|
+
|
85
|
+
def all_comments_addressed?
|
86
|
+
self.class.minimum_approvals.length <= 0 or last_comment.match(self.class.approval_regex)
|
87
|
+
end
|
88
|
+
|
38
89
|
def good_to_merge?(force: false)
|
39
90
|
return true if force
|
40
|
-
has_comments_or_approvals = (has_comments? or approvals.any?)
|
41
91
|
|
42
|
-
|
43
|
-
(build_status.nil? or build_status == "success") and
|
44
|
-
(has_comments_or_approvals and reviewers_pending_response.empty?))
|
92
|
+
(build_status.nil? or build_status == "success") and approved?
|
45
93
|
end
|
46
94
|
|
47
95
|
def display_pull_request_summary
|
data/lib/git_reflow/version.rb
CHANGED
data/lib/git_reflow.rb
CHANGED
@@ -21,8 +21,6 @@ module GitReflow
|
|
21
21
|
|
22
22
|
extend self
|
23
23
|
|
24
|
-
LGTM = /lgtm|looks good to me|:\+1:|:thumbsup:|:shipit:/i
|
25
|
-
|
26
24
|
def status(destination_branch)
|
27
25
|
pull_request = git_server.find_open_pull_request( :from => current_branch, :to => destination_branch )
|
28
26
|
|
@@ -156,12 +154,8 @@ module GitReflow
|
|
156
154
|
else
|
157
155
|
say "There were problems commiting your feature... please check the errors above and try again.", :error
|
158
156
|
end
|
159
|
-
elsif !existing_pull_request.build_status.nil? and existing_pull_request.build_status != "success"
|
160
|
-
say "#{existing_pull_request.build.description}: #{existing_pull_request.build.url}", :deliver_halted
|
161
|
-
elsif existing_pull_request.reviewers_pending_response.count > 0
|
162
|
-
say "You still need a LGTM from: #{existing_pull_request.reviewers_pending_response.join(', ')}", :deliver_halted
|
163
157
|
else
|
164
|
-
say
|
158
|
+
say existing_pull_request.rejection_message, :deliver_halted
|
165
159
|
end
|
166
160
|
end
|
167
161
|
|
data/spec/git_reflow_spec.rb
CHANGED
@@ -18,6 +18,11 @@ describe GitReflow do
|
|
18
18
|
let(:existing_pull_request) { GitReflow::GitServer::GitHub::PullRequest.new existing_pull_requests.first }
|
19
19
|
|
20
20
|
before do
|
21
|
+
|
22
|
+
# Stubbing out numlgtm value to test all reviewers in gitconfig file
|
23
|
+
allow(GitReflow::Config).to receive(:get).with("constants.minimumApprovals").and_return('')
|
24
|
+
allow(GitReflow::Config).to receive(:get).and_call_original
|
25
|
+
|
21
26
|
HighLine.any_instance.stub(:ask) do |terminal, question|
|
22
27
|
values = {
|
23
28
|
"Please enter your GitHub username: " => user,
|
@@ -211,18 +216,18 @@ describe GitReflow do
|
|
211
216
|
|
212
217
|
context "and pull request exists for the feature branch to the destination branch" do
|
213
218
|
before do
|
214
|
-
github.
|
215
|
-
github.
|
216
|
-
existing_pull_request.
|
217
|
-
github.
|
219
|
+
allow(github).to receive(:build_status).and_return(build_status)
|
220
|
+
allow(github).to receive(:find_open_pull_request).and_return(existing_pull_request)
|
221
|
+
allow(existing_pull_request).to receive(:has_comments?).and_return(true)
|
222
|
+
allow(github).to receive(:reviewers).and_return(['codenamev'])
|
218
223
|
end
|
219
224
|
|
220
225
|
context 'and build status is not "success"' do
|
221
226
|
let(:build_status) { Hashie::Mash.new({ state: 'failure', description: 'Build resulted in failed test(s)' }) }
|
222
227
|
|
223
228
|
before do
|
224
|
-
existing_pull_request.
|
225
|
-
existing_pull_request.
|
229
|
+
allow(existing_pull_request).to receive(:build).and_return(build_status)
|
230
|
+
allow(existing_pull_request).to receive(:has_comments?).and_return(true)
|
226
231
|
end
|
227
232
|
|
228
233
|
it "halts delivery and notifies user of a failed build" do
|
@@ -236,8 +241,8 @@ describe GitReflow do
|
|
236
241
|
|
237
242
|
before do
|
238
243
|
# stubbing unrelated results so we can just test that it made it insdide the conditional block
|
239
|
-
existing_pull_request.
|
240
|
-
existing_pull_request.
|
244
|
+
allow(existing_pull_request).to receive(:has_comments?).and_return(true)
|
245
|
+
allow(existing_pull_request).to receive(:reviewers).and_return([])
|
241
246
|
GitReflow.stub(:update_destination).and_return(true)
|
242
247
|
GitReflow.stub(:merge_feature_branch).and_return(true)
|
243
248
|
GitReflow.stub(:append_to_squashed_commit_message).and_return(true)
|
@@ -269,6 +274,34 @@ describe GitReflow do
|
|
269
274
|
subject
|
270
275
|
end
|
271
276
|
|
277
|
+
context "build status failure, testing description and target_url" do
|
278
|
+
let(:build_status) { Hashie::Mash.new({ state: 'failure', description: 'Build resulted in failed test(s)', target_url: "www.error.com" }) }
|
279
|
+
|
280
|
+
before do
|
281
|
+
existing_pull_request.stub(:build).and_return(build_status)
|
282
|
+
existing_pull_request.stub(:reviewers).and_return(lgtm_comment_authors)
|
283
|
+
existing_pull_request.stub(:has_comments?).and_return(true)
|
284
|
+
end
|
285
|
+
|
286
|
+
it "halts delivery and notifies user of a failed build" do
|
287
|
+
expect { subject }.to have_said "#{build_status.description}: #{build_status.url}", :deliver_halted
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
context "build status nil" do
|
292
|
+
let(:build_status) { nil }
|
293
|
+
|
294
|
+
before do
|
295
|
+
github.stub(:build).and_return(build_status)
|
296
|
+
existing_pull_request.stub(:reviewers_pending_response).and_return([])
|
297
|
+
existing_pull_request.stub(:has_comments_or_approvals).and_return(true)
|
298
|
+
end
|
299
|
+
|
300
|
+
it "commits the changes if the build status is nil but has comments/approvals and no pending response" do
|
301
|
+
expect{ subject }.to have_said 'Merge complete!', :success
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
272
305
|
context "and the pull request has no body" do
|
273
306
|
let(:first_commit_message) { "We'll do it live." }
|
274
307
|
|
@@ -325,7 +358,8 @@ describe GitReflow do
|
|
325
358
|
|
326
359
|
context "not always" do
|
327
360
|
before do
|
328
|
-
GitReflow::Config.stub(:get)
|
361
|
+
GitReflow::Config.stub(:get).with("reflow.always-deploy-and-cleanup").and_return("false")
|
362
|
+
GitReflow::Config.stub(:get).and_call_original
|
329
363
|
end
|
330
364
|
|
331
365
|
it "pushes local squash merged base branch to remote repo" do
|
@@ -343,7 +377,8 @@ describe GitReflow do
|
|
343
377
|
|
344
378
|
context "always" do
|
345
379
|
before do
|
346
|
-
GitReflow::Config.stub(:get)
|
380
|
+
GitReflow::Config.stub(:get).with("reflow.always-deploy-and-cleanup").and_return("true")
|
381
|
+
GitReflow::Config.stub(:get).and_call_original
|
347
382
|
end
|
348
383
|
|
349
384
|
it "pushes local squash merged base branch to remote repo" do
|