danger-gitlab_reviewbot 1.1.4 → 1.1.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f2886d84d0e6fb6e296379feeb66e4e183d5aa8bd8598a3f4e2713aa5b4b5927
4
- data.tar.gz: 0b1aa53383e71c481256c8893064ca54cda389c8dad6f2dcad014d48117c8edb
3
+ metadata.gz: 67b82907ad367877d16780bff37695983a3235649eb5751564f80af6b3741eac
4
+ data.tar.gz: b35596f4f8d498cfdbb5dc873a99418782558ace2680980900735ede0f7f1825
5
5
  SHA512:
6
- metadata.gz: 5a4d8a9e9da4ce0883efae5cd949d18497b0e571b916443c4276a884b1fe6be2fe35a143c803665bb0d6f810a16b1687032fde49585a92066d381811ed52507a
7
- data.tar.gz: '03528aa2084af65294610316cdff1a584c6507ccd88ed407270d87ed27029d6734e73a0ef06f4c9af5b60ce2bd68292debc456187c48107b015760b5f8a1393f'
6
+ metadata.gz: 0c9ca5a7f734c3c0a86c08d80309a58049b538bf546aaa6d47f74ac18fe248593383e7977c70d8aa1cc7b4501b6610e129d7e8c7d941de03746ede64739699fc
7
+ data.tar.gz: 4e0234da0471bba9284fbc70d618fc96b0f931e7eba63d3f0e555e08918d6dd06ec23f09fa8cd0639fd75d664d6b691163dcb67810f414e4dd471720820cd9a2
data/.gitlab-ci.yml CHANGED
@@ -4,16 +4,31 @@ cache:
4
4
  paths:
5
5
  - vendor/bundle/
6
6
 
7
+ stages:
8
+ - test
9
+ - deploy
10
+
7
11
  test:
8
12
  stage: test
9
13
  script:
10
14
  - gem install bundler
11
15
  - bundle --path vendor/bundle
12
16
  - bundle exec rake spec
13
- - bundle exec rake build
14
17
  artifacts:
15
18
  paths:
16
19
  - rspec.xml
17
20
  reports:
18
21
  junit: rspec.xml
19
22
 
23
+ deploy:
24
+ stage: deploy
25
+ only:
26
+ - tags
27
+ before_script:
28
+ - 'mkdir ~/.gem && echo -e "---\r\n:rubygems_api_key: $RUBYGEMS_API_KEY" > ~/.gem/credentials && chmod 0600 ~/.gem/credentials'
29
+ script:
30
+ - gem install bundler
31
+ - bundle --path vendor/bundle
32
+ - bundle exec rake build
33
+ - gem push pkg/danger-gitlab_reviewbot-${CI_COMMIT_TAG}.gem
34
+
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- danger-gitlab_reviewbot (1.1.3)
4
+ danger-gitlab_reviewbot (1.1.7)
5
5
  danger-gitlab
6
6
  danger-plugin-api (~> 1.0)
7
7
 
@@ -21,26 +21,26 @@ GEM
21
21
  colored2 (3.1.2)
22
22
  cork (0.3.0)
23
23
  colored2 (~> 3.1)
24
- danger (6.3.2)
24
+ danger (8.0.1)
25
25
  claide (~> 1.0)
26
26
  claide-plugins (>= 0.9.2)
27
27
  colored2 (~> 3.1)
28
28
  cork (~> 0.1)
29
- faraday (~> 0.9)
29
+ faraday (>= 0.9.0, < 2.0)
30
30
  faraday-http-cache (~> 2.0)
31
- git (~> 1.6)
31
+ git (~> 1.7)
32
32
  kramdown (~> 2.0)
33
33
  kramdown-parser-gfm (~> 1.0)
34
34
  no_proxy_fix
35
35
  octokit (~> 4.7)
36
36
  terminal-table (~> 1)
37
- danger-gitlab (7.0.0)
38
- danger (~> 6.0)
37
+ danger-gitlab (8.0.0)
38
+ danger
39
39
  gitlab (~> 4.2, >= 4.2.0)
40
40
  danger-plugin-api (1.0.0)
41
41
  danger (> 2.0)
42
42
  diff-lcs (1.3)
43
- faraday (0.17.3)
43
+ faraday (1.0.1)
44
44
  multipart-post (>= 1.2, < 3)
45
45
  faraday-http-cache (2.2.0)
46
46
  faraday (>= 0.8)
@@ -48,7 +48,7 @@ GEM
48
48
  formatador (0.2.5)
49
49
  git (1.7.0)
50
50
  rchardet (~> 1.8)
51
- gitlab (4.14.1)
51
+ gitlab (4.15.0)
52
52
  httparty (~> 0.14, >= 0.14.0)
53
53
  terminal-table (~> 1.5, >= 1.5.1)
54
54
  guard (2.16.2)
@@ -65,7 +65,7 @@ GEM
65
65
  guard (~> 2.1)
66
66
  guard-compat (~> 1.1)
67
67
  rspec (>= 2.99.0, < 4.0)
68
- httparty (0.18.0)
68
+ httparty (0.18.1)
69
69
  mime-types (~> 3.0)
70
70
  multi_xml (>= 0.5.2)
71
71
  kramdown (2.2.1)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GitlabReviewbot
4
- VERSION = "1.1.4"
4
+ VERSION = "1.1.9"
5
5
  end
@@ -19,12 +19,33 @@ module Gitlab
19
19
  end
20
20
  end
21
21
 
22
- class Client < API
22
+ class ClientHelper
23
+ def initialize(client)
24
+ @client = client
25
+ end
26
+
27
+ def users_with_pending_mr_review(project_id)
28
+ outstanding_mrs = fetch_mrs_requiring_review(project_id)
29
+ all_assignees = outstanding_mrs.reduce([]) { |acc, mr| acc + mr.assignees - assignees_with_review(project_id, mr.id, mr.assignees)}
30
+ assignees_id_map = all_assignees.each_with_object({}) do |a, acc|
31
+ aid = a["id"]
32
+ ausername = a["username"]
33
+ assignee = acc[aid] || User.new(aid, ausername)
34
+ assignee.review_count += 1
35
+ acc[aid] = assignee
36
+ end
37
+ assignees_id_map.values
38
+ end
39
+
40
+ def fetch_mrs_requiring_review(project_id)
41
+ @client.merge_requests(project_id, state: "opened", per_page: "100")
42
+ end
43
+
23
44
  def fetch_users_for_group(group_name)
24
- group_id = search_group(group_name)
45
+ group_id = search_group_with_path(group_name)
25
46
  return nil if group_id.nil?
26
47
 
27
- res = group_members(group_id)
48
+ res = @client.group_members(group_id, :per_page => 100)
28
49
 
29
50
  developer_access_level = 30
30
51
  res.select { |u| u.state == "active" && u.access_level >= developer_access_level }.map { |u| User.new(u.id, u.username) }
@@ -32,44 +53,28 @@ module Gitlab
32
53
 
33
54
  def assign_mr_to_users(project_id, mr_iid, users)
34
55
  user_ids = users.map(&:id)
35
- update_merge_request(project_id, mr_iid, "assignee_ids" => user_ids)
56
+ @client.update_merge_request(project_id, mr_iid, "assignee_ids" => user_ids)
57
+
36
58
  end
37
59
 
38
60
  def fetch_author_for_mr(project_id, mr_iid)
39
- res = merge_request(project_id, mr_iid)
61
+ res = @client.merge_request(project_id, mr_iid)
40
62
  User.new(res.author.id, res.author.name)
41
63
  end
42
64
 
43
- def fetch_mrs_requiring_review(project_id)
44
- merge_requests(project_id, state: "opened", per_page: "100").reject { |mr| mr.merge_status == "can_be_merged" }
45
- end
46
-
47
65
  def find_user_with_username(username)
48
- users({ username: username }).map { |u| User.new(u.id, u.username) }
49
- end
50
-
51
- def users_with_pending_mr_review(project_id)
52
- outstanding_mrs = fetch_mrs_requiring_review(project_id)
53
- all_assignees = outstanding_mrs.reduce([]) { |acc, mr| acc + mr.assignees }
54
- assignees_id_map = all_assignees.each_with_object({}) do |a, acc|
55
- aid = a["id"]
56
- ausername = a["username"]
57
- assignee = acc[aid] || User.new(aid, ausername)
58
- assignee.review_count += 1
59
- acc[aid] = assignee
60
- end
61
- assignees_id_map.values
66
+ @client.users({ username: username }).map { |u| User.new(u.id, u.username) }
62
67
  end
63
68
 
64
69
  def fetch_mr_reviewers(project_id, mr_iid)
65
- merge_request(project_id, mr_iid).assignees.map { |u| User.new(u["id"], u["username"]) }
70
+ @client.merge_request(project_id, mr_iid).assignees.map { |u| User.new(u["id"], u["username"]) }
66
71
  end
67
72
 
68
73
  private
69
74
 
70
- def search_group(group_name)
75
+ def search_group_with_path(group_name)
71
76
  short_name = group_name.split("/").last
72
- res = group_search(short_name)
77
+ res = @client.group_search(short_name)
73
78
  res = res.find { |i| i.full_path == group_name }
74
79
 
75
80
  if res.nil?
@@ -78,5 +83,28 @@ module Gitlab
78
83
  res.id
79
84
  end
80
85
  end
86
+
87
+ def assignees_with_review(project_id, mr_iid, gusers)
88
+ approvals = @client.merge_request_approval_state(project_id, mr_iid)
89
+ approved_by = approvals.rules.reduce([]) { |acc, r| acc + r['approved_by'] }
90
+ gusers.filter { |u| approved_by.index { |au| au['id'] == u['id'] } != nil }
91
+ end
92
+
93
+ end
94
+
95
+ class Client < API
96
+
97
+ def client_helper
98
+ @client_helper ||= ClientHelper.new(self)
99
+ end
100
+
101
+ def method_missing(method, *args)
102
+ if client_helper.respond_to?(method)
103
+ client_helper.send(method, *args)
104
+ else
105
+ super
106
+ end
107
+ end
108
+
81
109
  end
82
110
  end
@@ -13,9 +13,8 @@ module Danger
13
13
  group_users_with_reviews_pending = client.users_with_pending_mr_review(project_id).filter { |u| users_in_group.include? u }
14
14
  group_users_without_reviews_pending = users_in_group.filter { |u| !group_users_with_reviews_pending.include? u }
15
15
 
16
- (group_users_with_reviews_pending + group_users_without_reviews_pending).filter { |u| !invalid_assignees.include? u }
17
- .sort_by(&:review_count)
18
- .first(amount)
16
+ candidates = (group_users_with_reviews_pending + group_users_without_reviews_pending).filter { |u| !invalid_assignees.include? u }
17
+ candidates.shuffle.sort_by(&:review_count).first(amount)
19
18
  end
20
19
  end
21
20
  end
@@ -27,7 +27,7 @@ module Danger
27
27
  all_assignees.map(&:username)
28
28
  end
29
29
 
30
- def assignees(_amount)
30
+ def assignees(amount)
31
31
  raise "To be implemented in the subclasses"
32
32
  end
33
33
 
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path("spec_helper", __dir__)
4
+
5
+
6
+ module Danger
7
+ describe Gitlab::Client do
8
+ before do
9
+ #
10
+ # @sam = Gitlab::User.new(1, "Sam")
11
+ # @tom = Gitlab::User.new(2, "Tom")
12
+ # @nic = Gitlab::User.new(3, "Nic")
13
+ # @luke = Gitlab::User.new(4, "Luke")
14
+ @mock_client = double(Gitlab::Client)
15
+ @client_helper = Gitlab::ClientHelper.new(@mock_client)
16
+ @sam = Gitlab::User.new(1, "Sam")
17
+ @tom = Gitlab::User.new(2, "Tom")
18
+ @nic = Gitlab::User.new(3, "Nic")
19
+ @assignees = [{'id' => 1, 'username' => "Sam"},
20
+ {'id' => 2, 'username' => "Tom"},
21
+ {'id' => 3, 'username' => "Nic"}]
22
+ end
23
+
24
+ it "Correctly calculates users with pending reviews" do
25
+ already_reviewed = [@assignees[0]]
26
+
27
+ allow(@mock_client).to receive(:merge_requests).with(10, {:per_page=>"100", :state=>"opened"}).and_return([Gitlab::ObjectifiedHash.new({'id' => 110, 'assignees' => @assignees})])
28
+ allow(@mock_client).to receive(:merge_request_approval_state).with(10, 110).and_return(Gitlab::ObjectifiedHash.new({'rules' => [{'approved_by' => already_reviewed}]}))
29
+
30
+ expect(@client_helper.users_with_pending_mr_review(10)).to be == [@tom, @nic]
31
+ end
32
+
33
+ it "Correctly calculates users with pending reviews (multi rule)" do
34
+ allow(@mock_client).to receive(:merge_requests).with(10, {:per_page=>"100", :state=>"opened"}).and_return([Gitlab::ObjectifiedHash.new({'id' => 110, 'assignees' => @assignees})])
35
+ allow(@mock_client).to receive(:merge_request_approval_state).with(10, 110).and_return(Gitlab::ObjectifiedHash.new({'rules' => [{'approved_by' => [{'id' => 1, 'username' => "Sam"}]}, {'approved_by' => [{'id' => 2, 'username' => "Tom"}]}]}))
36
+
37
+ expect(@client_helper.users_with_pending_mr_review(10)).to be == [@nic]
38
+ end
39
+
40
+ it "Fetches only active developer users for group" do
41
+ active_users = [Gitlab::ObjectifiedHash.new({'id' => 1, 'username' => 'Sam', 'state' => 'active', 'access_level' => 30}),
42
+ Gitlab::ObjectifiedHash.new({'id' => 2, 'username' => 'Tom', 'state' => 'active', 'access_level' => 50})]
43
+ inactive_users = [Gitlab::ObjectifiedHash.new({'id' => 3, 'username' => 'OldSam', 'state' => 'inactive', 'access_level' => 30})]
44
+ non_developer_users = [Gitlab::ObjectifiedHash.new({'id' => 4, 'username' => 'Reporter', 'state' => 'active', 'access_level' => 20})]
45
+ allow(@mock_client).to receive(:group_search).with("mygroup").and_return([Gitlab::ObjectifiedHash.new({'id' => 10, 'full_path' => "mygroup"})])
46
+ allow(@mock_client).to receive(:group_members).with(10).and_return(active_users + inactive_users + non_developer_users)
47
+ expect(@client_helper.fetch_users_for_group("mygroup")).to be == [@sam, @tom]
48
+ end
49
+ end
50
+ end
51
+
data/spec/spec_helper.rb CHANGED
@@ -10,6 +10,7 @@ require "pry"
10
10
 
11
11
  require "rspec"
12
12
  require "danger"
13
+ require File.expand_path("../lib/gitlab_reviewbot/gitlab", __dir__)
13
14
 
14
15
  if `git remote -v` == ""
15
16
  puts "You cannot run tests without setting a local git remote on this repo"
@@ -59,7 +60,7 @@ def testing_env
59
60
  "CI_API_V4_URL" => "https://git.curve.tools/api/v4",
60
61
  "CI_PROJECT_ID" => "346",
61
62
  "GITLAB_CI" => true,
62
- "DANGER_GITLAB_API_TOKEN" => "jgUhHSk2vGNYYFr3QsPq"
63
+ "DANGER_GITLAB_API_TOKEN" => "token-token-token"
63
64
  }
64
65
  end
65
66
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: danger-gitlab_reviewbot
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.4
4
+ version: 1.1.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fabio Gallonetto
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-15 00:00:00.000000000 Z
11
+ date: 2021-08-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: danger-plugin-api
@@ -218,6 +218,7 @@ files:
218
218
  - lib/gitlab_reviewbot/strategies/least_busy.rb
219
219
  - lib/gitlab_reviewbot/strategies/random.rb
220
220
  - lib/gitlab_reviewbot/strategies/strategy.rb
221
+ - spec/gitlab_ext_spec.rb
221
222
  - spec/gitlab_reviewbot_spec.rb
222
223
  - spec/least_busy_strategy_spec.rb
223
224
  - spec/random_strategy_spec.rb
@@ -246,6 +247,7 @@ signing_key:
246
247
  specification_version: 4
247
248
  summary: A review raffle bot for Gitlab.
248
249
  test_files:
250
+ - spec/gitlab_ext_spec.rb
249
251
  - spec/gitlab_reviewbot_spec.rb
250
252
  - spec/least_busy_strategy_spec.rb
251
253
  - spec/random_strategy_spec.rb