gitlab-dangerfiles 4.12.0 → 4.14.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/CONTRIBUTING.md +1 -1
- data/Gemfile.lock +1 -1
- data/README.md +47 -34
- data/lefthook.yml +1 -1
- data/lib/danger/plugins/changelog.rb +17 -11
- data/lib/danger/plugins/commit_messages.rb +5 -2
- data/lib/danger/plugins/roulette.rb +24 -2
- data/lib/gitlab/dangerfiles/base_linter.rb +11 -4
- 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/title_linting.rb +4 -1
- 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: e62a200646d128a780ee1e17bb644f5fe296fef2f530631ebdabe677a2eea93f
|
|
4
|
+
data.tar.gz: 73aec620889b66c1c7f61fe845ab2b43c528c21301ed7b1bb4a8b6ad6e93656b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cfaa1d404d59cb656354135dd146d6ea908046f51430fd5d4f7d9aa83f13446bed69f7dc21b018a8f9e6154b6a65b5abf0a3fc90c6863986702b2b64403ffa81
|
|
7
|
+
data.tar.gz: 6300e9593543c6f635ced6fb6b1c9d04773bf1baac66d0dbc7bb2957607196f094d2a429e2372c64dcdbc31b331047e40ac387e2b99bd7b2777d52956c3e6b25
|
data/.gitlab/CODEOWNERS
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
* @gl-dx
|
|
1
|
+
* @gl-dx
|
data/CONTRIBUTING.md
CHANGED
|
@@ -6,7 +6,7 @@ Except for the license granted herein to GitLab B.V. and recipients of software
|
|
|
6
6
|
distributed by GitLab B.V., you reserve all right, title, and interest in and to
|
|
7
7
|
your Contributions.
|
|
8
8
|
|
|
9
|
-
All contributions are subject to the Developer Certificate of Origin and license set out at [docs.gitlab.com/
|
|
9
|
+
All contributions are subject to the Developer Certificate of Origin and license set out at [docs.gitlab.com/legal/developer_certificate_of_origin](https://docs.gitlab.com/legal/developer_certificate_of_origin/).
|
|
10
10
|
|
|
11
11
|
_This notice should stay as the first item in the CONTRIBUTING.md file._
|
|
12
12
|
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -148,7 +148,7 @@ Danger rules are located under `lib/danger/rules`.
|
|
|
148
148
|
|
|
149
149
|
#### `changelog`
|
|
150
150
|
|
|
151
|
-
This rule ensures the merge request follows our [Changelog guidelines](https://docs.gitlab.com/
|
|
151
|
+
This rule ensures the merge request follows our [Changelog guidelines](https://docs.gitlab.com/development/changelog/).
|
|
152
152
|
|
|
153
153
|
#### `changes_size`
|
|
154
154
|
|
|
@@ -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,17 +273,15 @@ 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
|
-
3. Create a [Project or group access token](https://docs.gitlab.com/
|
|
284
|
+
3. Create a [Project or group access token](https://docs.gitlab.com/user/project/settings/project_access_tokens/)
|
|
267
285
|
with scope `api` and role `Developer`.
|
|
268
286
|
4. Add a [CI/CD variable](https://docs.gitlab.com/ee/ci/variables/#add-a-cicd-variable-to-a-project)
|
|
269
287
|
`DANGER_GITLAB_API_TOKEN` (`Masked` but not `Protected`) and use Project access token as value.
|
|
@@ -274,25 +292,20 @@ See a [real world example](https://gitlab.com/gitlab-org/ruby/gems/gitlab-styles
|
|
|
274
292
|
|
|
275
293
|
Danger is a Ruby project and uses [`bundler`](https://bundler.io/) to manage
|
|
276
294
|
its dependencies. This requires a project to have a `Gemfile` and
|
|
277
|
-
`Gemfile.lock`
|
|
295
|
+
`Gemfile.lock` committed. 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
|
|
@@ -330,7 +343,7 @@ The following lint violations generate warnings:
|
|
|
330
343
|
1. The commit changes too many lines across too many files without describing the changes in the commit body ([code](https://gitlab.com/gitlab-org/ruby/gems/gitlab-dangerfiles/blob/bccb167/lib/gitlab/dangerfiles/commit_linter.rb#L83-85)).
|
|
331
344
|
1. The commit body contains too many characters per line ([code](https://gitlab.com/gitlab-org/ruby/gems/gitlab-dangerfiles/blob/bccb167/lib/gitlab/dangerfiles/commit_linter.rb#L87-96)).
|
|
332
345
|
|
|
333
|
-
All other lint violations generate errors, except when the MR has [Squash commits when merge request is accepted](https://docs.gitlab.com/
|
|
346
|
+
All other lint violations generate errors, except when the MR has [Squash commits when merge request is accepted](https://docs.gitlab.com/user/project/merge_requests/squash_and_merge/#squash-commits-in-a-merge-request) enabled, which downgrades lint violations to warnings.
|
|
334
347
|
|
|
335
348
|
## Documentation
|
|
336
349
|
|
|
@@ -368,9 +381,9 @@ See an [example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92580) fo
|
|
|
368
381
|
|
|
369
382
|
## Contributing
|
|
370
383
|
|
|
371
|
-
Bug reports and merge requests are welcome at https://gitlab.com/gitlab-org/gitlab-dangerfiles. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://gitlab.com/gitlab-org/gitlab-dangerfiles/blob/master/CODE_OF_CONDUCT.md).
|
|
384
|
+
Bug reports and merge requests are welcome at https://gitlab.com/gitlab-org/ruby/gems/gitlab-dangerfiles. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://gitlab.com/gitlab-org/ruby/gems/gitlab-dangerfiles/blob/master/CODE_OF_CONDUCT.md).
|
|
372
385
|
|
|
373
|
-
Make sure to include a changelog entry in your commit message and read the [changelog entries section](https://docs.gitlab.com/
|
|
386
|
+
Make sure to include a changelog entry in your commit message and read the [changelog entries section](https://docs.gitlab.com/development/changelog/).
|
|
374
387
|
|
|
375
388
|
## Release
|
|
376
389
|
|
|
@@ -402,4 +415,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
|
402
415
|
|
|
403
416
|
## Code of Conduct
|
|
404
417
|
|
|
405
|
-
Everyone interacting in the Gitlab::Danger project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://gitlab.com/gitlab-org/gitlab-dangerfiles/blob/master/CODE_OF_CONDUCT.md).
|
|
418
|
+
Everyone interacting in the Gitlab::Danger project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://gitlab.com/gitlab-org/ruby/gems/gitlab-dangerfiles/blob/master/CODE_OF_CONDUCT.md).
|
data/lefthook.yml
CHANGED
|
@@ -13,34 +13,34 @@ module Danger
|
|
|
13
13
|
NO_CHANGELOG_CATEGORIES = %i[docs none].freeze
|
|
14
14
|
CHANGELOG_TRAILER_REGEX = /^(?<name>Changelog):\s*(?<category>.+)$/i.freeze
|
|
15
15
|
CHANGELOG_EE_TRAILER_REGEX = /^EE: true$/.freeze
|
|
16
|
-
CHANGELOG_MODIFIED_URL_TEXT = "**CHANGELOG.md was edited.** Please remove the additions and follow the [changelog guidelines](https://docs.gitlab.com/
|
|
17
|
-
CHANGELOG_MISSING_URL_TEXT = "**[CHANGELOG missing](https://docs.gitlab.com/
|
|
16
|
+
CHANGELOG_MODIFIED_URL_TEXT = "**CHANGELOG.md was edited.** Please remove the additions and follow the [changelog guidelines](https://docs.gitlab.com/development/changelog/).\n\n"
|
|
17
|
+
CHANGELOG_MISSING_URL_TEXT = "**[CHANGELOG missing](https://docs.gitlab.com/development/changelog/)**:\n\n"
|
|
18
18
|
IF_REVERT_MR_TEXT = <<~MARKDOWN
|
|
19
|
-
In a revert merge request? Use the revert merge request template to add labels [that skip changelog checks](https://docs.gitlab.com/
|
|
19
|
+
In a revert merge request? Use the revert merge request template to add labels [that skip changelog checks](https://docs.gitlab.com/development/pipelines/#revert-mrs).
|
|
20
20
|
|
|
21
21
|
Reverting something in the current milestone? A changelog isn't required. Skip changelog checks by adding `~"regression:*"` label, then re-run the danger job (there is a link at the bottom of this comment).
|
|
22
22
|
MARKDOWN
|
|
23
23
|
|
|
24
24
|
OPTIONAL_CHANGELOG_MESSAGE = {
|
|
25
|
-
local: "If this merge request [doesn't need a CHANGELOG entry](https://docs.gitlab.com/
|
|
25
|
+
local: "If this merge request [doesn't need a CHANGELOG entry](https://docs.gitlab.com/development/changelog/#what-warrants-a-changelog-entry), feel free to ignore this message.",
|
|
26
26
|
ci: <<~MSG
|
|
27
27
|
If this merge request needs a changelog entry, add the `Changelog` trailer to the commit message you want to add to the changelog.
|
|
28
28
|
|
|
29
|
-
If this merge request [doesn't need a CHANGELOG entry](https://docs.gitlab.com/
|
|
29
|
+
If this merge request [doesn't need a CHANGELOG entry](https://docs.gitlab.com/development/changelog/#what-warrants-a-changelog-entry), feel free to ignore this message.
|
|
30
30
|
MSG
|
|
31
31
|
}.freeze
|
|
32
|
-
SEE_DOC = "See the [changelog documentation](https://docs.gitlab.com/
|
|
32
|
+
SEE_DOC = "See the [changelog documentation](https://docs.gitlab.com/development/changelog/)."
|
|
33
33
|
|
|
34
34
|
REQUIRED_CHANGELOG_REASONS = {
|
|
35
35
|
db_changes: "introduces a database migration",
|
|
36
36
|
feature_flag_removed: "removes a feature flag"
|
|
37
37
|
}.freeze
|
|
38
38
|
REQUIRED_CHANGELOG_MESSAGE = {
|
|
39
|
-
local: "This merge request requires a changelog entry because it [%<reason>s](https://docs.gitlab.com/
|
|
39
|
+
local: "This merge request requires a changelog entry because it [%<reason>s](https://docs.gitlab.com/development/changelog/#what-warrants-a-changelog-entry).",
|
|
40
40
|
ci: <<~MSG
|
|
41
41
|
To create a changelog entry, add the `Changelog` trailer to one of your Git commit messages.
|
|
42
42
|
|
|
43
|
-
This merge request requires a changelog entry because it [%<reason>s](https://docs.gitlab.com/
|
|
43
|
+
This merge request requires a changelog entry because it [%<reason>s](https://docs.gitlab.com/development/changelog/#what-warrants-a-changelog-entry).
|
|
44
44
|
MSG
|
|
45
45
|
}.freeze
|
|
46
46
|
DEFAULT_CHANGELOG_CATEGORIES = %w[
|
|
@@ -191,15 +191,15 @@ module Danger
|
|
|
191
191
|
ee_changes = helper.changed_files(%r{\Aee/})
|
|
192
192
|
|
|
193
193
|
if ee_changes.any? && !ee_changelog? && !required?
|
|
194
|
-
check_result.warning("This MR changes code in `ee/`, but its Changelog commit is missing the [`EE: true` trailer](https://docs.gitlab.com/
|
|
194
|
+
check_result.warning("This MR changes code in `ee/`, but its Changelog commit is missing the [`EE: true` trailer](https://docs.gitlab.com/development/changelog/#gitlab-enterprise-changes). Consider adding it to your Changelog commits.")
|
|
195
195
|
end
|
|
196
196
|
|
|
197
197
|
if ee_changes.empty? && ee_changelog?
|
|
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)
|
|
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/
|
|
201
|
+
if ee_changes.any? && ee_changelog? && required_reasons.include?(:db_changes) && non_ee_database_migration_changes?
|
|
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/development/changelog/#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
|
|
|
205
205
|
check_result
|
|
@@ -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
|
|
@@ -7,7 +7,7 @@ module Danger
|
|
|
7
7
|
# Common helper functions for our danger scripts. See Danger::Helper
|
|
8
8
|
# for more details
|
|
9
9
|
class CommitMessages < Danger::Plugin
|
|
10
|
-
COMMIT_MSG_DOC = "https://docs.gitlab.com/
|
|
10
|
+
COMMIT_MSG_DOC = "https://docs.gitlab.com/development/contributing/merge_request_workflow/#commit-messages-guidelines"
|
|
11
11
|
MORE_INFO = "For more information, take a look at our [Commit message guidelines](#{COMMIT_MSG_DOC}).".freeze
|
|
12
12
|
THE_DANGER_JOB_TEXT = "the `%<job_name>s` job"
|
|
13
13
|
MAX_COMMITS_COUNT_EXCEEDED_MESSAGE = <<~MSG
|
|
@@ -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) &&
|
|
@@ -7,6 +7,7 @@ module Gitlab
|
|
|
7
7
|
class BaseLinter
|
|
8
8
|
MIN_SUBJECT_WORDS_COUNT = 3
|
|
9
9
|
MAX_LINE_LENGTH = 72
|
|
10
|
+
PREFIX_REGEX = /\A(\[[^\]]+\]|[^:\s]+:)\s/
|
|
10
11
|
|
|
11
12
|
attr_reader :commit, :problems
|
|
12
13
|
|
|
@@ -92,11 +93,17 @@ module Gitlab
|
|
|
92
93
|
return false if subject_starts_with_a_space?
|
|
93
94
|
return false if ("A".."Z").cover?(subject[0])
|
|
94
95
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
if PREFIX_REGEX.match?(subject)
|
|
97
|
+
first_char = subject.sub(PREFIX_REGEX, "")[0]
|
|
98
|
+
return true if first_char.nil?
|
|
98
99
|
|
|
99
|
-
|
|
100
|
+
first_char_downcased = first_char.downcase
|
|
101
|
+
return true unless ("a".."z").cover?(first_char_downcased)
|
|
102
|
+
|
|
103
|
+
false
|
|
104
|
+
else
|
|
105
|
+
true
|
|
106
|
+
end
|
|
100
107
|
end
|
|
101
108
|
|
|
102
109
|
def subject_ends_with_a_period?
|
|
@@ -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)
|
|
@@ -3,7 +3,10 @@
|
|
|
3
3
|
module Gitlab
|
|
4
4
|
module Dangerfiles
|
|
5
5
|
module TitleLinting
|
|
6
|
-
|
|
6
|
+
# Matches the markers a title starts with, one or several in a row, and
|
|
7
|
+
# a WIP or draft it ends with. The same markers anywhere else in a title
|
|
8
|
+
# are part of its text.
|
|
9
|
+
DRAFT_REGEX = /\A(?:(?:\[WIP\]|WIP:|\[draft\]|\(draft\)|draft:|draft\s-\s)\s*)+|(?:WIP|draft)\z/i.freeze
|
|
7
10
|
CHERRY_PICK_REGEX = /cherry[\s-]*pick/i.freeze
|
|
8
11
|
RUN_ALL_RSPEC_REGEX = /RUN ALL RSPEC/i.freeze
|
|
9
12
|
RUN_AS_IF_FOSS_REGEX = /RUN AS-IF-FOSS/i.freeze
|
|
@@ -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.14.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-27 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
|