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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 64b5781cd74b023d9f5a94c91949cac9528636f7
4
- data.tar.gz: f509d8459ca0b092d4bd710722987613bfb6cd5f
3
+ metadata.gz: c6773486dad59a6ec3d71cd0047234005b8d06f1
4
+ data.tar.gz: 07665f57499a6aab0bd31218a0bf8d5e147c8581
5
5
  SHA512:
6
- metadata.gz: 0ec9acd3327e943147292d1a6f794b23ae5cedbc80250e4c29c3884d26d7382f4b972ef0151ece4ea989e524721248a02ffc2df453c1c1bd094c7f1cd6de62bd
7
- data.tar.gz: 860b02e97c65b9121ec31428ee8218a463fe5ccfab846767ee7312891a2321853e053902448bd29111f65200153b0cca775b4432d674465b5d6422239c2c9b02
6
+ metadata.gz: 930b0d1bb58185c59c0d759ef2aad44a10d2b2481bd78843f842c4b703c4b4770a29574cb34be888d01035db40fd66f10df45e343427c2fafee37e06791a1602
7
+ data.tar.gz: 8aa0cbcf0db37dcbb527f2275cef16125d7f736a18787700e1fc16c2934b68ac75f0f0e2713d1790c5e90efca256926be9df200f3baa61ae8aae427411facd1c
data/.gitignore CHANGED
@@ -2,3 +2,4 @@ pkg/*
2
2
  **/.DS_Store
3
3
  .rspec
4
4
  gemfiles
5
+ *.gem
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- git_reflow (0.7.4)
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.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 'rake'
3
- require 'bundler/gem_tasks'
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 => [:spec]
7
+ task :default => :spec
8
+
data/bin/console ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "git_reflow"
5
+
6
+ require "irb"
7
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
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("\n")
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 = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
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 = 'bin'
19
- s.require_paths << 'lib'
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', '~> 3.0.0')
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: LGTM, after: pull_last_committed_at)
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
- "#{comments.last.body.inspect}"
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
- force == true or (
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
@@ -1,3 +1,3 @@
1
1
  module GitReflow
2
- VERSION = "0.7.4"
2
+ VERSION = "0.7.5"
3
3
  end
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 "Your code has not been reviewed yet.", :deliver_halted
158
+ say existing_pull_request.rejection_message, :deliver_halted
165
159
  end
166
160
  end
167
161
 
@@ -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.stub(:get_build_status).and_return(build_status)
215
- github.should_receive(:find_open_pull_request).and_return(existing_pull_request)
216
- existing_pull_request.stub(:has_comments?).and_return(true)
217
- github.stub(:reviewers).and_return(['codenamev'])
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.stub(:build).and_return(build_status)
225
- existing_pull_request.stub(:has_comments?).and_return(true)
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.stub(:has_comments?).and_return(true)
240
- existing_pull_request.stub(:reviewers).and_return([])
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) { "false" }
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) { "true" }
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