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 +4 -4
- data/.gitlab-ci.yml +16 -1
- data/Gemfile.lock +9 -9
- data/lib/gitlab_reviewbot/gem_version.rb +1 -1
- data/lib/gitlab_reviewbot/gitlab.rb +54 -26
- data/lib/gitlab_reviewbot/strategies/least_busy.rb +2 -3
- data/lib/gitlab_reviewbot/strategies/strategy.rb +1 -1
- data/spec/gitlab_ext_spec.rb +51 -0
- data/spec/spec_helper.rb +2 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 67b82907ad367877d16780bff37695983a3235649eb5751564f80af6b3741eac
|
4
|
+
data.tar.gz: b35596f4f8d498cfdbb5dc873a99418782558ace2680980900735ede0f7f1825
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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 (
|
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 (
|
29
|
+
faraday (>= 0.9.0, < 2.0)
|
30
30
|
faraday-http-cache (~> 2.0)
|
31
|
-
git (~> 1.
|
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 (
|
38
|
-
danger
|
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.
|
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.
|
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.
|
68
|
+
httparty (0.18.1)
|
69
69
|
mime-types (~> 3.0)
|
70
70
|
multi_xml (>= 0.5.2)
|
71
71
|
kramdown (2.2.1)
|
@@ -19,12 +19,33 @@ module Gitlab
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
class
|
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 =
|
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
|
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
|
-
|
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
|
@@ -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" => "
|
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
|
+
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:
|
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
|