gitlab-dangerfiles 4.11.1 → 4.13.0
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/CODEOWNERS +1 -1
- data/Gemfile.lock +1 -1
- data/README.md +40 -27
- data/lib/danger/plugins/changelog.rb +7 -1
- data/lib/danger/plugins/commit_messages.rb +4 -1
- data/lib/danger/plugins/roulette.rb +24 -2
- data/lib/gitlab/dangerfiles/approval.rb +2 -2
- data/lib/gitlab/dangerfiles/capability.rb +0 -11
- data/lib/gitlab/dangerfiles/commit_linter.rb +1 -1
- data/lib/gitlab/dangerfiles/config.rb +12 -6
- data/lib/gitlab/dangerfiles/spec_helper.rb +0 -12
- data/lib/gitlab/dangerfiles/spinner.rb +25 -18
- data/lib/gitlab/dangerfiles/version.rb +1 -1
- data/lib/gitlab/dangerfiles/weightage/maintainers.rb +9 -2
- data/lib/gitlab/dangerfiles/weightage/reviewers.rb +14 -5
- metadata +2 -4
- data/lib/danger/plugins/duo_code.rb +0 -12
- data/lib/danger/rules/duo_code_review/Dangerfile +0 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 90d11c90b2540e75f8664f62f9e8dca94f3a1ad9da4454af946d578ba5d06bd4
|
|
4
|
+
data.tar.gz: c3319c3df8c5bdc2fd9a9f1a409da791615b516272872eaf06f4fc1b1f0a6f73
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 943f6712c05394b8476f22eb937ebc5267c570e64e4ef2eb9414404353d92ff69dae10dfece405e6d2cbb7b4f117c873ec3b57998d5cf3db620ad8de239dc931
|
|
7
|
+
data.tar.gz: fd05d33d287a9d6661bd8cadc59613e9ad717427c22dfd97ed14be94cfa90c71b8f0d46b43a4135a07348acf3d173f4fe38183e5164e5afb4cca192630c8eb87
|
data/.gitlab/CODEOWNERS
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
* @gl-dx
|
|
1
|
+
* @gl-dx
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -169,16 +169,10 @@ This rule ensures the merge request isn't too big to be reviewed, otherwise it s
|
|
|
169
169
|
|
|
170
170
|
#### `commits_counter`
|
|
171
171
|
|
|
172
|
-
This rule posts a
|
|
172
|
+
This rule posts a warning if the merge request has more than 20 commits.
|
|
173
173
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
This rule posts a warning/failure when `@GitLabDuo` isn't assigned as a reviewer.
|
|
177
|
-
|
|
178
|
-
##### Available configurations
|
|
179
|
-
|
|
180
|
-
- `duo_code_review`: Whether a review from GitLab Duo Code is `:mandatory` or `:optional`.
|
|
181
|
-
Default to `:optional`.
|
|
174
|
+
For merge requests in [`gitlab-org/gitlab`](https://gitlab.com/gitlab-org/gitlab), it posts a failure
|
|
175
|
+
instead, unless the merge request is set to squash commits.
|
|
182
176
|
|
|
183
177
|
#### `metadata`
|
|
184
178
|
|
|
@@ -225,6 +219,32 @@ helper.config.auto_assign_for_roulette_roles = [:reviewer]
|
|
|
225
219
|
helper.config.auto_assign_for_roulette_labels = ["maintenance::dependency"]
|
|
226
220
|
```
|
|
227
221
|
|
|
222
|
+
##### CODEOWNERS boost
|
|
223
|
+
|
|
224
|
+
By default, the roulette selects reviewers and maintainers purely based on category membership and
|
|
225
|
+
capacity weights. You can optionally give CODEOWNERS-eligible approvers additional weight in the
|
|
226
|
+
selection pool, making them more likely to be picked without hard-gating on them.
|
|
227
|
+
|
|
228
|
+
Configure `codeowners_reviewer_boost_for_roulette` and/or `codeowners_maintainer_boost_for_roulette`
|
|
229
|
+
with a positive integer to add that many extra entries in the weighted pool for matching reviewers
|
|
230
|
+
or maintainers. The boost stacks on top of existing capacity, hungry, and traintainer weights.
|
|
231
|
+
|
|
232
|
+
```ruby
|
|
233
|
+
# Prefer code owners for review, but not for maintainer approval
|
|
234
|
+
helper.config.codeowners_reviewer_boost_for_roulette = 3
|
|
235
|
+
|
|
236
|
+
# Prefer code owners for both review and maintainer approval
|
|
237
|
+
helper.config.codeowners_reviewer_boost_for_roulette = 3
|
|
238
|
+
helper.config.codeowners_maintainer_boost_for_roulette = 2
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
| Value | Behavior |
|
|
242
|
+
|-------|----------|
|
|
243
|
+
| `0` (default) | No change — existing behavior preserved |
|
|
244
|
+
| `1-2` | Mild preference for code owners |
|
|
245
|
+
| `3` | Recommended — meaningful preference without starving non-owners |
|
|
246
|
+
| `4+` | Strong preference — use with caution on small teams |
|
|
247
|
+
|
|
228
248
|
##### Available configurations
|
|
229
249
|
|
|
230
250
|
Note: These options aren't actually used in the `simple_roulette` rule, but can be used in your own
|
|
@@ -253,14 +273,12 @@ In order to run `danger` on GitLab CI, perform the following steps:
|
|
|
253
273
|
|
|
254
274
|
1. If not yet done, create a `Dangerfile` at the top-level of your project. Refer to [Usage](#usage) to
|
|
255
275
|
see how to set it up.
|
|
256
|
-
2. In `.gitlab-ci.yml`, include [CI
|
|
257
|
-
which defines `danger-review` [CI job](https://docs.gitlab.com/ee/ci/jobs/):
|
|
276
|
+
2. In `.gitlab-ci.yml`, include the [`danger-review` CI/CD component](https://gitlab.com/gitlab-org/components/danger-review)
|
|
277
|
+
which defines the `danger-review` [CI job](https://docs.gitlab.com/ee/ci/jobs/):
|
|
258
278
|
|
|
259
279
|
```yaml
|
|
260
280
|
include:
|
|
261
|
-
-
|
|
262
|
-
file:
|
|
263
|
-
- '/ci/danger-review.yml'
|
|
281
|
+
- component: gitlab.com/gitlab-org/components/danger-review/danger-review@~latest
|
|
264
282
|
```
|
|
265
283
|
|
|
266
284
|
3. Create a [Project or group access token](https://docs.gitlab.com/ee/user/project/settings/project_access_tokens.html)
|
|
@@ -277,22 +295,17 @@ its dependencies. This requires a project to have a `Gemfile` and
|
|
|
277
295
|
`Gemfile.lock` commited. This is helpful especially if Danger is also used
|
|
278
296
|
locally - with `lefthook`, for example.
|
|
279
297
|
|
|
280
|
-
|
|
281
|
-
|
|
298
|
+
You don't need a `Gemfile` to use the `danger-review` component. If your project
|
|
299
|
+
has no `Gemfile`, the component creates one and adds the latest `gitlab-dangerfiles`
|
|
300
|
+
to it before it runs Danger.
|
|
301
|
+
|
|
302
|
+
To pin the `gitlab-dangerfiles` version instead, set the `gitlab_dangerfiles_version` input:
|
|
282
303
|
|
|
283
304
|
```yaml
|
|
284
305
|
include:
|
|
285
|
-
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
danger-review:
|
|
289
|
-
before_script:
|
|
290
|
-
- bundle init
|
|
291
|
-
# For latest version
|
|
292
|
-
- bundle add gitlab-dangerfiles
|
|
293
|
-
# OR
|
|
294
|
-
# For a pinned version
|
|
295
|
-
- bundle add gitlab-dangerfiles --version 3.1.0
|
|
306
|
+
- component: gitlab.com/gitlab-org/components/danger-review/danger-review@~latest
|
|
307
|
+
inputs:
|
|
308
|
+
gitlab_dangerfiles_version: "4.12.0"
|
|
296
309
|
```
|
|
297
310
|
|
|
298
311
|
## Local Danger Rake task
|
|
@@ -198,7 +198,7 @@ module Danger
|
|
|
198
198
|
check_result.warning("This MR has a Changelog commit for EE, but no code changes in `ee/`. Consider removing the `EE: true` trailer from your commits.")
|
|
199
199
|
end
|
|
200
200
|
|
|
201
|
-
if ee_changes.any? && ee_changelog? && required_reasons.include?(:db_changes)
|
|
201
|
+
if ee_changes.any? && ee_changelog? && required_reasons.include?(:db_changes) && non_ee_database_migration_changes?
|
|
202
202
|
check_result.warning("This MR has a Changelog commit with the `EE: true` trailer, but there are database changes which [requires](https://docs.gitlab.com/ee/development/changelog.html#what-warrants-a-changelog-entry) the Changelog commit to not have the `EE: true` trailer. Consider removing the `EE: true` trailer from your commits.")
|
|
203
203
|
end
|
|
204
204
|
|
|
@@ -216,6 +216,12 @@ module Danger
|
|
|
216
216
|
required_reasons.any?
|
|
217
217
|
end
|
|
218
218
|
|
|
219
|
+
def non_ee_database_migration_changes?
|
|
220
|
+
helper.changes.added.by_category(:migration).any? do |change|
|
|
221
|
+
!change.file.start_with?("ee/db/")
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
|
|
219
225
|
def optional?
|
|
220
226
|
categories_need_changelog? && mr_without_no_changelog_label?
|
|
221
227
|
end
|
|
@@ -102,7 +102,10 @@ module Danger
|
|
|
102
102
|
commit_linters = commits.map { |commit| lint_commit(commit) }
|
|
103
103
|
|
|
104
104
|
if helper.squash_mr?
|
|
105
|
-
|
|
105
|
+
# `commits` (and therefore `commit_linters`) is ordered newest-to-oldest, matching `git log`.
|
|
106
|
+
# We want the oldest multi-line, non-merge commit, since that's the commit whose message is
|
|
107
|
+
# expected to survive the squash, so we search in reverse order.
|
|
108
|
+
multi_line_commit_linter = commit_linters.reverse.detect do |commit_linter|
|
|
106
109
|
!commit_linter.merge? && commit_linter.multi_line?
|
|
107
110
|
end
|
|
108
111
|
|
|
@@ -53,12 +53,19 @@ module Danger
|
|
|
53
53
|
project = (project || config_project_name).downcase
|
|
54
54
|
categories = categories.map { |category| category&.downcase || :none }
|
|
55
55
|
|
|
56
|
+
reviewer_boost = helper.config.codeowners_reviewer_boost_for_roulette
|
|
57
|
+
maintainer_boost = helper.config.codeowners_maintainer_boost_for_roulette
|
|
58
|
+
co_usernames = reviewer_boost > 0 || maintainer_boost > 0 ? codeowners_eligible_usernames : Set.new
|
|
59
|
+
|
|
56
60
|
Gitlab::Dangerfiles::Spinner.new(
|
|
57
61
|
project: project,
|
|
58
62
|
author: helper.mr_author, team_author: team_mr_author,
|
|
59
63
|
labels: labels, categories: categories, random: random,
|
|
60
64
|
ux_fallback_wider_community_reviewer:
|
|
61
|
-
ux_fallback_wider_community_reviewer
|
|
65
|
+
ux_fallback_wider_community_reviewer,
|
|
66
|
+
codeowners_usernames: co_usernames,
|
|
67
|
+
codeowners_reviewer_boost: reviewer_boost,
|
|
68
|
+
codeowners_maintainer_boost: maintainer_boost)
|
|
62
69
|
.spin
|
|
63
70
|
end
|
|
64
71
|
|
|
@@ -120,10 +127,25 @@ module Danger
|
|
|
120
127
|
private
|
|
121
128
|
|
|
122
129
|
def ux_fallback_reviewer
|
|
123
|
-
teammates = %w[pedroms
|
|
130
|
+
teammates = %w[pedroms seggenberger clavimoniere]
|
|
124
131
|
Gitlab::Dangerfiles::Teammate.find_member(teammates.sample)
|
|
125
132
|
end
|
|
126
133
|
|
|
134
|
+
# Collect all CODEOWNERS-eligible approver usernames across qualifying approval rules.
|
|
135
|
+
#
|
|
136
|
+
# @return [Set<String>]
|
|
137
|
+
def codeowners_eligible_usernames
|
|
138
|
+
approval_rules = helper.mr_approval_state["rules"]
|
|
139
|
+
|
|
140
|
+
return Set.new unless approval_rules
|
|
141
|
+
|
|
142
|
+
unique_approval_rules(approval_rules).each_with_object(Set.new) do |rule, usernames|
|
|
143
|
+
next unless spin_for_approval_rule?(rule)
|
|
144
|
+
|
|
145
|
+
rule["eligible_approvers"].each { |approver| usernames << approver["username"] }
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
127
149
|
def spin_for_approval_rule?(rule)
|
|
128
150
|
rule["rule_type"] == "code_owner" &&
|
|
129
151
|
should_include_codeowners_rule?(rule) &&
|
|
@@ -4,7 +4,7 @@ require_relative "spin"
|
|
|
4
4
|
|
|
5
5
|
module Gitlab
|
|
6
6
|
module Dangerfiles
|
|
7
|
-
Approval = Struct.new(:category, :spin) do
|
|
7
|
+
Approval = Struct.new(:category, :spin, :name) do
|
|
8
8
|
def self.from_approval_rule(rule, maintainer)
|
|
9
9
|
category =
|
|
10
10
|
if rule["section"] == "codeowners"
|
|
@@ -15,7 +15,7 @@ module Gitlab
|
|
|
15
15
|
|
|
16
16
|
spin = Spin.new(category, nil, maintainer, :reviewer)
|
|
17
17
|
|
|
18
|
-
new(category, spin)
|
|
18
|
+
new(category, spin, rule["name"])
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
21
|
end
|
|
@@ -13,7 +13,6 @@ module Gitlab
|
|
|
13
13
|
def self.category_to_class
|
|
14
14
|
@category_to_class ||= {
|
|
15
15
|
none: None,
|
|
16
|
-
test: Test,
|
|
17
16
|
tooling: Tooling,
|
|
18
17
|
ux: UX
|
|
19
18
|
}.freeze
|
|
@@ -36,16 +35,6 @@ module Gitlab
|
|
|
36
35
|
end
|
|
37
36
|
end
|
|
38
37
|
|
|
39
|
-
class Test < Capability
|
|
40
|
-
def has_capability?(teammate)
|
|
41
|
-
return false if kind != :reviewer
|
|
42
|
-
|
|
43
|
-
area = teammate.role[/Software Engineer in Test(?:.*?, (\w+))/, 1]
|
|
44
|
-
|
|
45
|
-
!!area && labels.any?("devops::#{area.downcase}")
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
38
|
class Tooling < Capability
|
|
50
39
|
def has_capability?(teammate)
|
|
51
40
|
if super
|
|
@@ -40,11 +40,6 @@ module Gitlab
|
|
|
40
40
|
# @return [Integer] the maximum number of allowed non-squashed/non-fixup commits for a given MR. A warning is triggered if the MR has more commits.
|
|
41
41
|
attr_accessor :max_commits_count
|
|
42
42
|
|
|
43
|
-
# Rule: duo_code_review
|
|
44
|
-
# @!attribute duo_code_review
|
|
45
|
-
# @return [Symbol] whether a review from GitLab Duo Code is `:mandatory` or `:optional`. Default to `:optional`.
|
|
46
|
-
attr_accessor :duo_code_review
|
|
47
|
-
|
|
48
43
|
# Rule: simple_roulette
|
|
49
44
|
# @!attribute included_optional_codeowners_sections_for_roulette
|
|
50
45
|
# @return [Array] indicating which optional codeowners sections should be included in roulette. Default to `[]`.
|
|
@@ -55,6 +50,16 @@ module Gitlab
|
|
|
55
50
|
# @return [Array] indicating which required codeowners sections should be excluded from roulette. Default to `[]`.
|
|
56
51
|
attr_accessor :excluded_required_codeowners_sections_for_roulette
|
|
57
52
|
|
|
53
|
+
# Rule: simple_roulette
|
|
54
|
+
# @!attribute codeowners_reviewer_boost_for_roulette
|
|
55
|
+
# @return [Integer] extra weight given to reviewers who are CODEOWNERS-eligible approvers for the current merge request. Set to 0 to disable. Default to `0`.
|
|
56
|
+
attr_accessor :codeowners_reviewer_boost_for_roulette
|
|
57
|
+
|
|
58
|
+
# Rule: simple_roulette
|
|
59
|
+
# @!attribute codeowners_maintainer_boost_for_roulette
|
|
60
|
+
# @return [Integer] extra weight given to maintainers who are CODEOWNERS-eligible approvers for the current merge request. Set to 0 to disable. Default to `0`.
|
|
61
|
+
attr_accessor :codeowners_maintainer_boost_for_roulette
|
|
62
|
+
|
|
58
63
|
# @!attribute auto_assign_for_roulette_roles
|
|
59
64
|
# @return [Array<Symbol>] which roles to auto assign as reviewers, given roulette recommendations (:reviewer, :maintainer, or both). If empty, auto-assignment is disabled. Default to `[]`.
|
|
60
65
|
attr_accessor :auto_assign_for_roulette_roles
|
|
@@ -77,9 +82,10 @@ module Gitlab
|
|
|
77
82
|
@disabled_roulette_categories = []
|
|
78
83
|
@included_optional_codeowners_sections_for_roulette = []
|
|
79
84
|
@excluded_required_codeowners_sections_for_roulette = []
|
|
85
|
+
@codeowners_reviewer_boost_for_roulette = 0
|
|
86
|
+
@codeowners_maintainer_boost_for_roulette = 0
|
|
80
87
|
@auto_assign_for_roulette_roles = []
|
|
81
88
|
@auto_assign_for_roulette_labels = []
|
|
82
|
-
@duo_code_review = :optional
|
|
83
89
|
end
|
|
84
90
|
end
|
|
85
91
|
end
|
|
@@ -154,17 +154,6 @@ RSpec.shared_context "with teammates" do
|
|
|
154
154
|
)
|
|
155
155
|
end
|
|
156
156
|
|
|
157
|
-
let(:software_engineer_in_test) do
|
|
158
|
-
Gitlab::Dangerfiles::Teammate.new(
|
|
159
|
-
"username" => "software-engineer-in-test",
|
|
160
|
-
"name" => "Software Engineer in Test",
|
|
161
|
-
"role" => "Software Engineer in Test, Create:Source Code",
|
|
162
|
-
"projects" => { "gitlab" => "maintainer qa", "gitlab-qa" => "maintainer" },
|
|
163
|
-
"available" => true,
|
|
164
|
-
"tz_offset_hours" => 2.0
|
|
165
|
-
)
|
|
166
|
-
end
|
|
167
|
-
|
|
168
157
|
let(:tooling_reviewer) do
|
|
169
158
|
Gitlab::Dangerfiles::Teammate.new(
|
|
170
159
|
"username" => "eng-prod-reviewer",
|
|
@@ -227,7 +216,6 @@ RSpec.shared_context "with teammates" do
|
|
|
227
216
|
frontend_maintainer.to_h,
|
|
228
217
|
frontend_reviewer.to_h,
|
|
229
218
|
ux_reviewer.to_h,
|
|
230
|
-
software_engineer_in_test.to_h,
|
|
231
219
|
tooling_reviewer.to_h,
|
|
232
220
|
ci_template_reviewer.to_h,
|
|
233
221
|
workhorse_reviewer.to_h,
|
|
@@ -10,9 +10,14 @@ module Gitlab
|
|
|
10
10
|
class Spinner
|
|
11
11
|
attr_reader :project, :author, :team_author, :labels, :categories
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
# @param codeowners_usernames [Set<String>] usernames of CODEOWNERS-eligible approvers for the MR
|
|
14
|
+
# @param codeowners_reviewer_boost [Integer] extra weight entries for CODEOWNERS-eligible reviewers
|
|
15
|
+
# @param codeowners_maintainer_boost [Integer] extra weight entries for CODEOWNERS-eligible maintainers
|
|
16
|
+
def initialize( # rubocop:disable Metrics/ParameterLists -- CODEOWNERS boost params extend the existing signature
|
|
14
17
|
project:, author:, team_author: nil, labels: [], categories: [],
|
|
15
|
-
random: Random.new, ux_fallback_wider_community_reviewer: nil
|
|
18
|
+
random: Random.new, ux_fallback_wider_community_reviewer: nil,
|
|
19
|
+
codeowners_usernames: Set.new, codeowners_reviewer_boost: 0,
|
|
20
|
+
codeowners_maintainer_boost: 0)
|
|
16
21
|
@project = project
|
|
17
22
|
@author = author
|
|
18
23
|
@team_author = team_author
|
|
@@ -20,9 +25,12 @@ module Gitlab
|
|
|
20
25
|
@categories = categories
|
|
21
26
|
@random = random
|
|
22
27
|
@ux_fallback_wider_community_reviewer = ux_fallback_wider_community_reviewer
|
|
28
|
+
@codeowners_usernames = codeowners_usernames
|
|
29
|
+
@codeowners_reviewer_boost = codeowners_reviewer_boost
|
|
30
|
+
@codeowners_maintainer_boost = codeowners_maintainer_boost
|
|
23
31
|
end
|
|
24
32
|
|
|
25
|
-
# rubocop:disable Metrics/
|
|
33
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
26
34
|
def spin
|
|
27
35
|
spins = categories.sort_by(&:to_s).map do |category|
|
|
28
36
|
spin_for_category(category)
|
|
@@ -33,10 +41,7 @@ module Gitlab
|
|
|
33
41
|
|
|
34
42
|
spins.each do |spin|
|
|
35
43
|
case spin.category
|
|
36
|
-
when :qa
|
|
37
|
-
spin.optional_role = :maintainer if
|
|
38
|
-
categories.size > 1 && author_no_qa_capability?
|
|
39
|
-
when :test
|
|
44
|
+
when :qa, :test
|
|
40
45
|
spin.optional_role = :maintainer
|
|
41
46
|
|
|
42
47
|
if spin.no_reviewer?
|
|
@@ -61,8 +66,6 @@ module Gitlab
|
|
|
61
66
|
spin.maintainer = backend_spin&.maintainer || frontend_spin&.maintainer || spin_for_category(:backend).maintainer
|
|
62
67
|
end
|
|
63
68
|
when :ux
|
|
64
|
-
spin.optional_role = :maintainer
|
|
65
|
-
|
|
66
69
|
# We want at least a UX reviewer who can review any wider community
|
|
67
70
|
# contribution even without a team designer. We assign this to Pedro.
|
|
68
71
|
spin.reviewer = ux_fallback_wider_community_reviewer if
|
|
@@ -74,7 +77,7 @@ module Gitlab
|
|
|
74
77
|
|
|
75
78
|
spins
|
|
76
79
|
end
|
|
77
|
-
# rubocop:enable Metrics/
|
|
80
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
78
81
|
|
|
79
82
|
# Spin a reviewer for a particular approval rule
|
|
80
83
|
#
|
|
@@ -92,12 +95,8 @@ module Gitlab
|
|
|
92
95
|
|
|
93
96
|
private
|
|
94
97
|
|
|
95
|
-
attr_reader :random, :ux_fallback_wider_community_reviewer
|
|
96
|
-
|
|
97
|
-
# MR includes QA changes, but also other changes, and author isn't an SET
|
|
98
|
-
def author_no_qa_capability?
|
|
99
|
-
!(team_author && team_author.capabilities(project).any? { |capability| capability.end_with?("qa") })
|
|
100
|
-
end
|
|
98
|
+
attr_reader :random, :ux_fallback_wider_community_reviewer,
|
|
99
|
+
:codeowners_usernames, :codeowners_reviewer_boost, :codeowners_maintainer_boost
|
|
101
100
|
|
|
102
101
|
def spin_for_category(category)
|
|
103
102
|
reviewers, traintainers, maintainers =
|
|
@@ -105,8 +104,16 @@ module Gitlab
|
|
|
105
104
|
spin_role_for_category(role, category)
|
|
106
105
|
end
|
|
107
106
|
|
|
108
|
-
weighted_reviewers = Weightage::Reviewers.new(
|
|
109
|
-
|
|
107
|
+
weighted_reviewers = Weightage::Reviewers.new(
|
|
108
|
+
reviewers, traintainers,
|
|
109
|
+
codeowners_usernames: codeowners_usernames,
|
|
110
|
+
codeowners_boost: codeowners_reviewer_boost
|
|
111
|
+
).execute
|
|
112
|
+
weighted_maintainers = Weightage::Maintainers.new(
|
|
113
|
+
maintainers,
|
|
114
|
+
codeowners_usernames: codeowners_usernames,
|
|
115
|
+
codeowners_boost: codeowners_maintainer_boost
|
|
116
|
+
).execute
|
|
110
117
|
|
|
111
118
|
reviewer = spin_for_person(weighted_reviewers)
|
|
112
119
|
maintainer = spin_for_person(weighted_maintainers)
|
|
@@ -7,8 +7,13 @@ module Gitlab
|
|
|
7
7
|
module Weightage
|
|
8
8
|
# @api private
|
|
9
9
|
class Maintainers
|
|
10
|
-
|
|
10
|
+
# @param maintainers [Array<Gitlab::Dangerfiles::Teammate>]
|
|
11
|
+
# @param codeowners_usernames [Set<String>] usernames of CODEOWNERS-eligible approvers for the MR
|
|
12
|
+
# @param codeowners_boost [Integer] extra weight entries for CODEOWNERS-eligible maintainers
|
|
13
|
+
def initialize(maintainers, codeowners_usernames: Set.new, codeowners_boost: 0)
|
|
11
14
|
@maintainers = maintainers
|
|
15
|
+
@codeowners_usernames = codeowners_usernames
|
|
16
|
+
@codeowners_boost = codeowners_boost
|
|
12
17
|
end
|
|
13
18
|
|
|
14
19
|
def execute
|
|
@@ -19,7 +24,7 @@ module Gitlab
|
|
|
19
24
|
|
|
20
25
|
private
|
|
21
26
|
|
|
22
|
-
attr_reader :maintainers
|
|
27
|
+
attr_reader :maintainers, :codeowners_usernames, :codeowners_boost
|
|
23
28
|
|
|
24
29
|
def add_weighted_reviewer(reviewers, reviewer, weight)
|
|
25
30
|
if reviewer.reduced_capacity
|
|
@@ -27,6 +32,8 @@ module Gitlab
|
|
|
27
32
|
else
|
|
28
33
|
reviewers.fill(reviewer, reviewers.size, weight * Gitlab::Dangerfiles::Weightage::CAPACITY_MULTIPLIER)
|
|
29
34
|
end
|
|
35
|
+
|
|
36
|
+
reviewers.fill(reviewer, reviewers.size, codeowners_boost) if codeowners_boost.positive? && codeowners_usernames.include?(reviewer.username)
|
|
30
37
|
end
|
|
31
38
|
end
|
|
32
39
|
end
|
|
@@ -18,20 +18,27 @@ module Gitlab
|
|
|
18
18
|
# | hungry traintainer | 6 |
|
|
19
19
|
# +------------------------------+--------------------------------+
|
|
20
20
|
#
|
|
21
|
+
# When +codeowners_boost+ is configured (> 0), reviewers whose
|
|
22
|
+
# username appears in +codeowners_usernames+ receive that many
|
|
23
|
+
# additional entries in the pool on top of their base weight.
|
|
24
|
+
#
|
|
21
25
|
# @api private
|
|
22
26
|
class Reviewers
|
|
23
27
|
DEFAULT_REVIEWER_WEIGHT = Gitlab::Dangerfiles::Weightage::CAPACITY_MULTIPLIER * Gitlab::Dangerfiles::Weightage::BASE_REVIEWER_WEIGHT
|
|
24
28
|
TRAINTAINER_WEIGHT = 2
|
|
25
29
|
|
|
26
|
-
|
|
30
|
+
# @param reviewers [Array<Gitlab::Dangerfiles::Teammate>]
|
|
31
|
+
# @param traintainers [Array<Gitlab::Dangerfiles::Teammate>]
|
|
32
|
+
# @param codeowners_usernames [Set<String>] usernames of CODEOWNERS-eligible approvers for the MR
|
|
33
|
+
# @param codeowners_boost [Integer] extra weight entries for CODEOWNERS-eligible reviewers
|
|
34
|
+
def initialize(reviewers, traintainers, codeowners_usernames: Set.new, codeowners_boost: 0)
|
|
27
35
|
@reviewers = reviewers
|
|
28
36
|
@traintainers = traintainers
|
|
37
|
+
@codeowners_usernames = codeowners_usernames
|
|
38
|
+
@codeowners_boost = codeowners_boost
|
|
29
39
|
end
|
|
30
40
|
|
|
31
41
|
def execute
|
|
32
|
-
# TODO: take CODEOWNERS into account?
|
|
33
|
-
# https://gitlab.com/gitlab-org/gitlab/issues/26723
|
|
34
|
-
|
|
35
42
|
remove_traintainers_from_reviewers!
|
|
36
43
|
remove_maintainer_only_from_reviewers!
|
|
37
44
|
|
|
@@ -40,7 +47,7 @@ module Gitlab
|
|
|
40
47
|
|
|
41
48
|
private
|
|
42
49
|
|
|
43
|
-
attr_reader :reviewers, :traintainers
|
|
50
|
+
attr_reader :reviewers, :traintainers, :codeowners_usernames, :codeowners_boost
|
|
44
51
|
|
|
45
52
|
def remove_traintainers_from_reviewers!
|
|
46
53
|
# Sometimes folks will add themselves as traintainers and not remove themselves as reviewers.
|
|
@@ -75,6 +82,8 @@ module Gitlab
|
|
|
75
82
|
else
|
|
76
83
|
reviewers.fill(reviewer, reviewers.size, DEFAULT_REVIEWER_WEIGHT)
|
|
77
84
|
end
|
|
85
|
+
|
|
86
|
+
reviewers.fill(reviewer, reviewers.size, codeowners_boost) if codeowners_boost.positive? && codeowners_usernames.include?(reviewer.username)
|
|
78
87
|
end
|
|
79
88
|
end
|
|
80
89
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: gitlab-dangerfiles
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.
|
|
4
|
+
version: 4.13.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- GitLab
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-10-09 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rake
|
|
@@ -241,14 +241,12 @@ files:
|
|
|
241
241
|
- lefthook.yml
|
|
242
242
|
- lib/danger/plugins/changelog.rb
|
|
243
243
|
- lib/danger/plugins/commit_messages.rb
|
|
244
|
-
- lib/danger/plugins/duo_code.rb
|
|
245
244
|
- lib/danger/plugins/internal/helper.rb
|
|
246
245
|
- lib/danger/plugins/roulette.rb
|
|
247
246
|
- lib/danger/rules/changelog/Dangerfile
|
|
248
247
|
- lib/danger/rules/changes_size/Dangerfile
|
|
249
248
|
- lib/danger/rules/commit_messages/Dangerfile
|
|
250
249
|
- lib/danger/rules/commits_counter/Dangerfile
|
|
251
|
-
- lib/danger/rules/duo_code_review/Dangerfile
|
|
252
250
|
- lib/danger/rules/metadata/Dangerfile
|
|
253
251
|
- lib/danger/rules/simple_roulette/Dangerfile
|
|
254
252
|
- lib/danger/rules/type_label/Dangerfile
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Danger
|
|
4
|
-
# Contains method to check if Duo code suggestion added to MR as a reviewer.
|
|
5
|
-
class DuoCode < Danger::Plugin
|
|
6
|
-
def suggestion_added?
|
|
7
|
-
return false unless helper.ci?
|
|
8
|
-
|
|
9
|
-
helper.mr_reviewers.include?("GitLabDuo")
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
end
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
return if duo_code.suggestion_added?
|
|
4
|
-
|
|
5
|
-
case helper.config.duo_code_review
|
|
6
|
-
when :optional
|
|
7
|
-
markdown("We advise getting a review from GitLab Duo Code. You can assign `@GitLabDuo` as a reviewer to this merge request.")
|
|
8
|
-
when :mandatory
|
|
9
|
-
failure("A review from GitLab Duo Code is mandatory. Please assign `@GitLabDuo` as a reviewer to this merge request.")
|
|
10
|
-
end
|