gitlab-dangerfiles 3.11.0 → 3.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/.rubocop.yml +1 -1
- data/lib/danger/plugins/internal/helper.rb +1 -0
- data/lib/danger/plugins/roulette.rb +38 -53
- data/lib/danger/rules/simple_roulette/Dangerfile +0 -4
- data/lib/gitlab/dangerfiles/category.rb +7 -15
- data/lib/gitlab/dangerfiles/config.rb +10 -0
- data/lib/gitlab/dangerfiles/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fae45cdf2a0c840f86b2d1864e521587210e4f365d2d03727be0d73866e4379c
|
4
|
+
data.tar.gz: a8380520fe8d4d12be578493244570265023db9f850ff374cd879591fb533b02
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 178104293164685aa9b265505785872372ad621b92b15fca37a590be070e7abbfd4090c339f3869c1c9e4da56281800b479c96c6992fb141e358320944e508ab
|
7
|
+
data.tar.gz: bb6f9c2b409a904517d7f8e91918ddc7df959de37b41a25cd898398749d227e5b40755669a406e3bd8063df255f8639d5fccdef37c2cd150cad31e6c3d036f11
|
data/.rubocop.yml
CHANGED
@@ -478,6 +478,7 @@ module Danger
|
|
478
478
|
|
479
479
|
def current_milestone
|
480
480
|
@current_milestone ||= gitlab_helper.api.group_milestones(GITLAB_ORG_GROUP_ID, state: "active")
|
481
|
+
.auto_paginate
|
481
482
|
.select { |m| m.title.match?(/\A\d+\.\d+\z/) && !m.expired && m.start_date && m.due_date }
|
482
483
|
.min_by(&:start_date)
|
483
484
|
end
|
@@ -11,11 +11,7 @@ module Danger
|
|
11
11
|
ROULETTE_DATA_URL = "https://gitlab-org.gitlab.io/gitlab-roulette/roulette.json"
|
12
12
|
HOURS_WHEN_PERSON_CAN_BE_PICKED = (6..14).freeze
|
13
13
|
|
14
|
-
|
15
|
-
database: false,
|
16
|
-
}.freeze
|
17
|
-
|
18
|
-
Spin = Struct.new(:category, :reviewer, :maintainer, :optional_role, :timezone_experiment)
|
14
|
+
Spin = Struct.new(:category, :reviewer, :maintainer, :optional_role)
|
19
15
|
HTTPError = Class.new(StandardError)
|
20
16
|
|
21
17
|
Approval = Struct.new(:category, :spin) do
|
@@ -53,14 +49,6 @@ module Danger
|
|
53
49
|
categories
|
54
50
|
end
|
55
51
|
|
56
|
-
def assign_pedroms_for_ux_wider_community_contribution(spins)
|
57
|
-
# We want at least a UX reviewer who can review any wider community
|
58
|
-
# contribution even without a team designer. We assign this to Pedro.
|
59
|
-
ux_spin = look_for_fallback_designer_for_ux_wider_community_contribution?(spins)
|
60
|
-
|
61
|
-
ux_spin && ux_spin.reviewer = teammate_pedroms
|
62
|
-
end
|
63
|
-
|
64
52
|
# Finds the +Gitlab::Dangerfiles::Teammate+ object whose username matches the MR author username.
|
65
53
|
#
|
66
54
|
# @return [Gitlab::Dangerfiles::Teammate]
|
@@ -73,26 +61,22 @@ module Danger
|
|
73
61
|
#
|
74
62
|
# @param project [String] A project path.
|
75
63
|
# @param categories [Array<Symbol>] An array of categories symbols.
|
76
|
-
# @param timezone_experiment [Boolean] Whether to select reviewers based in timezone or not.
|
77
64
|
#
|
78
65
|
# @return [Array<Spin>]
|
79
66
|
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
80
|
-
def spin(project = nil, categories = [:none],
|
67
|
+
def spin(project = nil, categories = [:none], ux_fallback_wider_community_reviewer: teammate_pedroms)
|
81
68
|
project = (project || config_project_name).downcase
|
82
69
|
categories = categories.map { |category| category&.downcase || :none }
|
83
70
|
categories.reject! { |category| import_and_integrate_reject_category?(category, project) }
|
84
71
|
|
85
72
|
spins = categories.sort_by(&:to_s).map do |category|
|
86
|
-
|
87
|
-
|
88
|
-
spin_for_category(project, category, timezone_experiment: including_timezone)
|
73
|
+
spin_for_category(project, category)
|
89
74
|
end
|
90
75
|
|
91
76
|
backend_spin = spins.find { |spin| spin.category == :backend }
|
92
77
|
frontend_spin = spins.find { |spin| spin.category == :frontend }
|
93
78
|
|
94
79
|
spins.each do |spin|
|
95
|
-
including_timezone = INCLUDE_TIMEZONE_FOR_CATEGORY.fetch(spin.category, timezone_experiment)
|
96
80
|
case spin.category
|
97
81
|
when :qa
|
98
82
|
# MR includes QA changes, but also other changes, and author isn't an SET
|
@@ -105,29 +89,36 @@ module Danger
|
|
105
89
|
|
106
90
|
if spin.reviewer.nil?
|
107
91
|
# Fetch an already picked backend reviewer, or pick one otherwise
|
108
|
-
spin.reviewer = backend_spin&.reviewer || spin_for_category(project, :backend
|
92
|
+
spin.reviewer = backend_spin&.reviewer || spin_for_category(project, :backend).reviewer
|
109
93
|
end
|
110
94
|
when :tooling, :engineering_productivity # Deprecated as of 2.3.0 in favor of tooling
|
111
95
|
if spin.maintainer.nil?
|
112
96
|
# Fetch an already picked backend maintainer, or pick one otherwise
|
113
|
-
spin.maintainer = backend_spin&.maintainer || spin_for_category(project, :backend
|
97
|
+
spin.maintainer = backend_spin&.maintainer || spin_for_category(project, :backend).maintainer
|
114
98
|
end
|
115
99
|
when :ci_template
|
116
100
|
if spin.maintainer.nil?
|
117
101
|
# Fetch an already picked backend maintainer, or pick one otherwise
|
118
|
-
spin.maintainer = backend_spin&.maintainer || spin_for_category(project, :backend
|
102
|
+
spin.maintainer = backend_spin&.maintainer || spin_for_category(project, :backend).maintainer
|
119
103
|
end
|
120
104
|
when :analytics_instrumentation
|
121
105
|
spin.optional_role = :maintainer
|
122
106
|
|
123
107
|
if spin.maintainer.nil?
|
124
108
|
# Fetch an already picked maintainer, or pick one otherwise
|
125
|
-
spin.maintainer = backend_spin&.maintainer || frontend_spin&.maintainer || spin_for_category(project, :backend
|
109
|
+
spin.maintainer = backend_spin&.maintainer || frontend_spin&.maintainer || spin_for_category(project, :backend).maintainer
|
126
110
|
end
|
127
111
|
when :import_integrate_be, :import_integrate_fe
|
128
112
|
spin.optional_role = :maintainer
|
129
113
|
when :ux
|
130
114
|
spin.optional_role = :maintainer
|
115
|
+
|
116
|
+
# We want at least a UX reviewer who can review any wider community
|
117
|
+
# contribution even without a team designer. We assign this to Pedro.
|
118
|
+
spin.reviewer = ux_fallback_wider_community_reviewer if
|
119
|
+
labels.include?("Community contribution") &&
|
120
|
+
spin.reviewer.nil? &&
|
121
|
+
spin.maintainer.nil?
|
131
122
|
end
|
132
123
|
end
|
133
124
|
|
@@ -136,7 +127,7 @@ module Danger
|
|
136
127
|
|
137
128
|
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
138
129
|
|
139
|
-
def
|
130
|
+
def codeowners_approvals
|
140
131
|
approval_rules = helper.mr_approval_state["rules"]
|
141
132
|
|
142
133
|
return [] unless approval_rules
|
@@ -156,13 +147,25 @@ module Danger
|
|
156
147
|
@teammate_pedroms ||= find_member("pedroms")
|
157
148
|
end
|
158
149
|
|
150
|
+
alias_method :required_approvals, :codeowners_approvals
|
151
|
+
|
159
152
|
private
|
160
153
|
|
161
154
|
def spin_for_approval_rule?(rule)
|
162
155
|
rule["rule_type"] == "code_owner" &&
|
163
|
-
rule
|
156
|
+
should_include_codeowners_rule?(rule) &&
|
164
157
|
# Exclude generic codeowners rule, which should be covered by others already
|
165
|
-
!generic_codeowners_rule?(rule)
|
158
|
+
!generic_codeowners_rule?(rule) &&
|
159
|
+
!excluded_required_codeowners_rule?(rule)
|
160
|
+
end
|
161
|
+
|
162
|
+
def should_include_codeowners_rule?(rule)
|
163
|
+
rule["approvals_required"] > 0 ||
|
164
|
+
helper.config.included_optional_codeowners_sections_for_roulette.include?(rule["section"])
|
165
|
+
end
|
166
|
+
|
167
|
+
def excluded_required_codeowners_rule?(rule)
|
168
|
+
helper.config.excluded_required_codeowners_sections_for_roulette.include?(rule["section"])
|
166
169
|
end
|
167
170
|
|
168
171
|
def generic_codeowners_rule?(rule)
|
@@ -191,12 +194,6 @@ module Danger
|
|
191
194
|
!mr_author?(person) && person.available
|
192
195
|
end
|
193
196
|
|
194
|
-
# @param [Gitlab::Dangerfiles::Teammate] person
|
195
|
-
# @return [Boolean]
|
196
|
-
def valid_person_with_timezone?(person)
|
197
|
-
valid_person?(person) && HOURS_WHEN_PERSON_CAN_BE_PICKED.cover?(person.local_hour)
|
198
|
-
end
|
199
|
-
|
200
197
|
# @param [Gitlab::Dangerfiles::Teammate] person
|
201
198
|
# @return [Boolean]
|
202
199
|
def mr_author?(person)
|
@@ -227,14 +224,10 @@ module Danger
|
|
227
224
|
# @param [Array<Gitlab::Dangerfiles::Teammate>] people
|
228
225
|
#
|
229
226
|
# @return [Gitlab::Dangerfiles::Teammate]
|
230
|
-
def spin_for_person(people
|
227
|
+
def spin_for_person(people)
|
231
228
|
shuffled_people = people.shuffle(random: random)
|
232
229
|
|
233
|
-
|
234
|
-
shuffled_people.find(&method(:valid_person_with_timezone?))
|
235
|
-
else
|
236
|
-
shuffled_people.find(&method(:valid_person?))
|
237
|
-
end
|
230
|
+
shuffled_people.find(&method(:valid_person?))
|
238
231
|
end
|
239
232
|
|
240
233
|
# Spin a reviewer for a particular approval rule
|
@@ -274,7 +267,7 @@ module Danger
|
|
274
267
|
fallback_approvers.sample(random: random)
|
275
268
|
end
|
276
269
|
|
277
|
-
def spin_for_category(project, category
|
270
|
+
def spin_for_category(project, category)
|
278
271
|
team = project_team(project)
|
279
272
|
reviewers, traintainers, maintainers =
|
280
273
|
%i[reviewer traintainer maintainer].map do |role|
|
@@ -284,14 +277,13 @@ module Danger
|
|
284
277
|
weighted_reviewers = Gitlab::Dangerfiles::Weightage::Reviewers.new(reviewers, traintainers).execute
|
285
278
|
weighted_maintainers = Gitlab::Dangerfiles::Weightage::Maintainers.new(maintainers).execute
|
286
279
|
|
287
|
-
reviewer = spin_for_person(weighted_reviewers
|
288
|
-
maintainer = spin_for_person(weighted_maintainers
|
280
|
+
reviewer = spin_for_person(weighted_reviewers)
|
281
|
+
maintainer = spin_for_person(weighted_maintainers)
|
289
282
|
|
290
|
-
Spin.new(category, reviewer, maintainer, false
|
283
|
+
Spin.new(category, reviewer, maintainer, false)
|
291
284
|
end
|
292
285
|
|
293
286
|
def prepare_ux_category!(categories)
|
294
|
-
# Ensure to spin for UX reviewer when ~UX is applied (e.g. to review changes to the UI)
|
295
287
|
if labels.include?("Community contribution")
|
296
288
|
categories << :ux
|
297
289
|
else
|
@@ -303,7 +295,9 @@ module Danger
|
|
303
295
|
# there's no designer for this team.
|
304
296
|
labels << "Community contribution"
|
305
297
|
|
306
|
-
|
298
|
+
# Don't use a fallback reviewer so when a group doesn't have
|
299
|
+
# available reviewers, it'll not give us any reviewers.
|
300
|
+
ux_spin = spin(nil, [:ux], ux_fallback_wider_community_reviewer: nil).first
|
307
301
|
|
308
302
|
categories << :ux if ux_spin.reviewer || ux_spin.maintainer
|
309
303
|
ensure
|
@@ -313,15 +307,6 @@ module Danger
|
|
313
307
|
end
|
314
308
|
end
|
315
309
|
|
316
|
-
def look_for_fallback_designer_for_ux_wider_community_contribution?(spins)
|
317
|
-
labels.include?("Community contribution") &&
|
318
|
-
spins.find do |spin|
|
319
|
-
spin.category == :ux &&
|
320
|
-
spin.reviewer.nil? &&
|
321
|
-
spin.maintainer.nil?
|
322
|
-
end
|
323
|
-
end
|
324
|
-
|
325
310
|
# Fetches the given +url+ and parse its response as JSON.
|
326
311
|
#
|
327
312
|
# @param [String] url
|
@@ -87,10 +87,6 @@ if changes.any?
|
|
87
87
|
show_category_column = categories.size > 1 || categories.first != :none
|
88
88
|
random_roulette_spins = roulette.spin(nil, categories)
|
89
89
|
|
90
|
-
if categories.include?(:ux)
|
91
|
-
roulette.assign_pedroms_for_ux_wider_community_contribution(random_roulette_spins)
|
92
|
-
end
|
93
|
-
|
94
90
|
rows = random_roulette_spins.map do |spin|
|
95
91
|
markdown_row_for_spins(spin.category, [spin], show_category_column: show_category_column)
|
96
92
|
end
|
@@ -78,27 +78,19 @@ module Gitlab
|
|
78
78
|
super &&
|
79
79
|
|
80
80
|
if labels.any?("Community contribution")
|
81
|
-
|
81
|
+
# We want the designer for the team to review the wider community
|
82
|
+
# contribution because they're more familiar with that area.
|
83
|
+
the_designer_for_the_team?(teammate)
|
82
84
|
else
|
83
|
-
|
85
|
+
# We don't want the designer for the team to review merge
|
86
|
+
# requests for the same team which is designed by themselves.
|
87
|
+
# So they can only review if they're not the designer for the team.
|
88
|
+
!the_designer_for_the_team?(teammate)
|
84
89
|
end
|
85
90
|
end
|
86
91
|
|
87
92
|
private
|
88
93
|
|
89
|
-
def can_review_wider_community_contribution?(teammate)
|
90
|
-
# We want the designer for the team to review the wider community
|
91
|
-
# contribution because they're more familiar with that area.
|
92
|
-
the_designer_for_the_team?(teammate)
|
93
|
-
end
|
94
|
-
|
95
|
-
def can_review_team_memeber_contribution?(teammate)
|
96
|
-
# We don't want the designer for the team to review merge
|
97
|
-
# requests for the same team which is designed by themselves.
|
98
|
-
# So they can only review if they're not the designer for the team.
|
99
|
-
!the_designer_for_the_team?(teammate)
|
100
|
-
end
|
101
|
-
|
102
94
|
def the_designer_for_the_team?(teammate)
|
103
95
|
# Pick corresponding group for community contribution
|
104
96
|
# Specialty can be:
|
@@ -33,6 +33,14 @@ module Gitlab
|
|
33
33
|
# @return [Array] indicating which categories would be disabled for the simple roulette. Default to `[]` (all categories are enabled)
|
34
34
|
attr_accessor :disabled_roulette_categories
|
35
35
|
|
36
|
+
# @!attribute included_optional_codeowners_sections_for_roulette
|
37
|
+
# @return [Array] indicating which optional codeowners sections should be included in roulette. Default to `[]`.
|
38
|
+
attr_accessor :included_optional_codeowners_sections_for_roulette
|
39
|
+
|
40
|
+
# @!attribute excluded_required_codeowners_sections_for_roulette
|
41
|
+
# @return [Array] indicating which required codeowners sections should be excluded from roulette. Default to `[]`.
|
42
|
+
attr_accessor :excluded_required_codeowners_sections_for_roulette
|
43
|
+
|
36
44
|
DEFAULT_CHANGES_SIZE_THRESHOLDS = { high: 2_000, medium: 500 }.freeze
|
37
45
|
DEFAULT_COMMIT_MESSAGES_MAX_COMMITS_COUNT = 10
|
38
46
|
|
@@ -44,6 +52,8 @@ module Gitlab
|
|
44
52
|
@code_size_thresholds = DEFAULT_CHANGES_SIZE_THRESHOLDS
|
45
53
|
@max_commits_count = DEFAULT_COMMIT_MESSAGES_MAX_COMMITS_COUNT
|
46
54
|
@disabled_roulette_categories = []
|
55
|
+
@included_optional_codeowners_sections_for_roulette = []
|
56
|
+
@excluded_required_codeowners_sections_for_roulette = []
|
47
57
|
end
|
48
58
|
end
|
49
59
|
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: 3.
|
4
|
+
version: 3.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: 2023-
|
11
|
+
date: 2023-08-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|