gitlab-dangerfiles 0.1.0 → 0.6.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/lib/danger/helper.rb +155 -113
- data/lib/danger/roulette.rb +68 -36
- data/lib/gitlab/dangerfiles.rb +0 -34
- data/lib/gitlab/dangerfiles/base_linter.rb +96 -0
- data/lib/gitlab/dangerfiles/commit_linter.rb +25 -103
- data/lib/gitlab/dangerfiles/merge_request_linter.rb +30 -0
- data/lib/gitlab/dangerfiles/teammate.rb +23 -9
- data/lib/gitlab/dangerfiles/title_linting.rb +38 -0
- data/lib/gitlab/dangerfiles/version.rb +1 -1
- data/lib/gitlab/dangerfiles/weightage.rb +10 -0
- data/lib/gitlab/dangerfiles/weightage/maintainers.rb +33 -0
- data/lib/gitlab/dangerfiles/weightage/reviewers.rb +65 -0
- metadata +9 -25
- data/lib/danger/changelog.rb +0 -39
- data/lib/danger/sidekiq_queues.rb +0 -37
- data/lib/gitlab/dangerfiles/bundle_size/Dangerfile +0 -38
- data/lib/gitlab/dangerfiles/ce_ee_vue_templates/Dangerfile +0 -56
- data/lib/gitlab/dangerfiles/changelog/Dangerfile +0 -90
- data/lib/gitlab/dangerfiles/changes_size/Dangerfile +0 -17
- data/lib/gitlab/dangerfiles/commit_messages/Dangerfile +0 -135
- data/lib/gitlab/dangerfiles/database/Dangerfile +0 -67
- data/lib/gitlab/dangerfiles/documentation/Dangerfile +0 -29
- data/lib/gitlab/dangerfiles/duplicate_yarn_dependencies/Dangerfile +0 -29
- data/lib/gitlab/dangerfiles/eslint/Dangerfile +0 -31
- data/lib/gitlab/dangerfiles/frozen_string/Dangerfile +0 -28
- data/lib/gitlab/dangerfiles/karma/Dangerfile +0 -51
- data/lib/gitlab/dangerfiles/metadata/Dangerfile +0 -50
- data/lib/gitlab/dangerfiles/popen.rb +0 -55
- data/lib/gitlab/dangerfiles/prettier/Dangerfile +0 -41
- data/lib/gitlab/dangerfiles/roulette/Dangerfile +0 -97
- data/lib/gitlab/dangerfiles/sidekiq_queues/Dangerfile +0 -27
- data/lib/gitlab/dangerfiles/specs/Dangerfile +0 -42
- data/lib/gitlab/dangerfiles/tasks.rb +0 -19
- data/lib/gitlab/dangerfiles/telemetry/Dangerfile +0 -32
- data/lib/gitlab/dangerfiles/utility_css/Dangerfile +0 -51
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a41237cf8c1b948162962ffd5712cac36034d6e3f6ddbd551f7b7f5c64315ac6
|
4
|
+
data.tar.gz: 9416beb3ed3688db58d83bfafb103a3f21b15c7a1e1dae83fe08dae33b13d329
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 294c63c0dad1685a71e4110ab5248d96e7efa97ef448dc861c6a443a8123fd490b1fbdf303b87bf7c18802074b24b3b371a433b3ef06c831cc368559c4c832a0
|
7
|
+
data.tar.gz: aa3bc70fe5068018df9dd1eee9010732b4df231033434ba02c3872b0902e3850adde1b97b6228dbda9f58e10c032b7d4b6467c96f18392d3e74dfab497638835
|
data/lib/danger/helper.rb
CHANGED
@@ -2,93 +2,72 @@
|
|
2
2
|
|
3
3
|
require "net/http"
|
4
4
|
require "json"
|
5
|
+
require "danger"
|
5
6
|
require_relative "../gitlab/dangerfiles/teammate"
|
7
|
+
require_relative "../gitlab/dangerfiles/title_linting"
|
6
8
|
|
7
9
|
module Danger
|
8
10
|
# Common helper functions for our danger scripts.
|
9
11
|
class Helper < Danger::Plugin
|
10
12
|
RELEASE_TOOLS_BOT = "gitlab-release-tools-bot"
|
13
|
+
DRAFT_REGEX = /\A*#{Regexp.union(/(?i)(\[WIP\]\s*|WIP:\s*|WIP$)/, /(?i)(\[draft\]|\(draft\)|draft:|draft\s\-\s|draft$)/)}+\s*/i.freeze
|
11
14
|
CATEGORY_LABELS = {
|
12
15
|
docs: "~documentation", # Docs are reviewed along DevOps stages, so don't need roulette for now.
|
13
16
|
none: "",
|
14
17
|
qa: "~QA",
|
15
18
|
test: "~test ~Quality for `spec/features/*`",
|
16
19
|
engineering_productivity: '~"Engineering Productivity" for CI, Danger',
|
17
|
-
|
18
|
-
# First-match win, so be sure to put more specific regex at the top...
|
19
|
-
CATEGORIES = {
|
20
|
-
%r{\Adoc/} => :docs,
|
21
|
-
%r{\A(CONTRIBUTING|LICENSE|MAINTENANCE|PHILOSOPHY|PROCESS|README)(\.md)?\z} => :docs,
|
22
|
-
|
23
|
-
%r{\A(ee/)?app/(assets|views)/} => :frontend,
|
24
|
-
%r{\A(ee/)?public/} => :frontend,
|
25
|
-
%r{\A(ee/)?spec/(javascripts|frontend)/} => :frontend,
|
26
|
-
%r{\A(ee/)?vendor/assets/} => :frontend,
|
27
|
-
%r{\A(ee/)?scripts/frontend/} => :frontend,
|
28
|
-
%r{(\A|/)(
|
29
|
-
\.babelrc |
|
30
|
-
\.eslintignore |
|
31
|
-
\.eslintrc(\.yml)? |
|
32
|
-
\.nvmrc |
|
33
|
-
\.prettierignore |
|
34
|
-
\.prettierrc |
|
35
|
-
\.scss-lint.yml |
|
36
|
-
\.stylelintrc |
|
37
|
-
\.haml-lint.yml |
|
38
|
-
\.haml-lint_todo.yml |
|
39
|
-
babel\.config\.js |
|
40
|
-
jest\.config\.js |
|
41
|
-
package\.json |
|
42
|
-
yarn\.lock |
|
43
|
-
config/.+\.js
|
44
|
-
)\z}x => :frontend,
|
45
|
-
|
46
|
-
%r{(\A|/)(
|
47
|
-
\.gitlab/ci/frontend\.gitlab-ci\.yml
|
48
|
-
)\z}x => %i[frontend engineering_productivity],
|
49
|
-
|
50
|
-
%r{\A(ee/)?db/(?!fixtures)[^/]+} => :database,
|
51
|
-
%r{\A(ee/)?lib/gitlab/(database|background_migration|sql|github_import)(/|\.rb)} => :database,
|
52
|
-
%r{\A(app/models/project_authorization|app/services/users/refresh_authorized_projects_service)(/|\.rb)} => :database,
|
53
|
-
%r{\A(ee/)?app/finders/} => :database,
|
54
|
-
%r{\Arubocop/cop/migration(/|\.rb)} => :database,
|
55
|
-
|
56
|
-
%r{\A(\.gitlab-ci\.yml\z|\.gitlab\/ci)} => :engineering_productivity,
|
57
|
-
%r{\A\.codeclimate\.yml\z} => :engineering_productivity,
|
58
|
-
%r{\A\.overcommit\.yml\.example\z} => :engineering_productivity,
|
59
|
-
%r{\A\.editorconfig\z} => :engineering_productivity,
|
60
|
-
%r{Dangerfile\z} => :engineering_productivity,
|
61
|
-
%r{\A(ee/)?(danger/|lib/gitlab/danger/)} => :engineering_productivity,
|
62
|
-
%r{\A(ee/)?scripts/} => :engineering_productivity,
|
63
|
-
%r{\Atooling/} => :engineering_productivity,
|
64
|
-
|
65
|
-
%r{\A(ee/)?app/(?!assets|views)[^/]+} => :backend,
|
66
|
-
%r{\A(ee/)?(bin|config|generator_templates|lib|rubocop)/} => :backend,
|
67
|
-
%r{\A(ee/)?spec/features/} => :test,
|
68
|
-
%r{\A(ee/)?spec/} => :backend,
|
69
|
-
%r{\A(ee/)?vendor/} => :backend,
|
70
|
-
%r{\A(Gemfile|Gemfile.lock|Rakefile)\z} => :backend,
|
71
|
-
%r{\A[A-Z_]+_VERSION\z} => :backend,
|
72
|
-
%r{\A\.rubocop(_todo)?\.yml\z} => :backend,
|
73
|
-
%r{\Afile_hooks/} => :backend,
|
74
|
-
|
75
|
-
%r{\A(ee/)?qa/} => :qa,
|
76
|
-
|
77
|
-
# Files that don't fit into any category are marked with :none
|
78
|
-
%r{\A(ee/)?changelogs/} => :none,
|
79
|
-
%r{\Alocale/gitlab\.pot\z} => :none,
|
80
|
-
|
81
|
-
# Fallbacks in case the above patterns miss anything
|
82
|
-
%r{\.rb\z} => :backend,
|
83
|
-
%r{(
|
84
|
-
\.(md|txt)\z |
|
85
|
-
\.markdownlint\.json
|
86
|
-
)}x => :none, # To reinstate roulette for documentation, set to `:docs`.
|
87
|
-
%r{\.js\z} => :frontend,
|
20
|
+
ci_template: '~"ci::templates"',
|
88
21
|
}.freeze
|
89
22
|
|
90
23
|
HTTPError = Class.new(StandardError)
|
91
24
|
|
25
|
+
Change = Struct.new(:file, :change_type, :category)
|
26
|
+
|
27
|
+
class Changes < ::SimpleDelegator
|
28
|
+
def added
|
29
|
+
select_by_change_type(:added)
|
30
|
+
end
|
31
|
+
|
32
|
+
def modified
|
33
|
+
select_by_change_type(:modified)
|
34
|
+
end
|
35
|
+
|
36
|
+
def deleted
|
37
|
+
select_by_change_type(:deleted)
|
38
|
+
end
|
39
|
+
|
40
|
+
def renamed_before
|
41
|
+
select_by_change_type(:renamed_before)
|
42
|
+
end
|
43
|
+
|
44
|
+
def renamed_after
|
45
|
+
select_by_change_type(:renamed_after)
|
46
|
+
end
|
47
|
+
|
48
|
+
def has_category?(category)
|
49
|
+
any? { |change| change.category == category }
|
50
|
+
end
|
51
|
+
|
52
|
+
def by_category(category)
|
53
|
+
Changes.new(select { |change| change.category == category })
|
54
|
+
end
|
55
|
+
|
56
|
+
def categories
|
57
|
+
map(&:category).uniq
|
58
|
+
end
|
59
|
+
|
60
|
+
def files
|
61
|
+
map(&:file)
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def select_by_change_type(change_type)
|
67
|
+
Changes.new(select { |change| change.change_type == change_type })
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
92
71
|
def gitlab_helper
|
93
72
|
# Unfortunately the following does not work:
|
94
73
|
# - respond_to?(:gitlab)
|
@@ -98,10 +77,6 @@ module Danger
|
|
98
77
|
nil
|
99
78
|
end
|
100
79
|
|
101
|
-
def rule_names
|
102
|
-
ci? ? Gitlab::Dangerfiles::LOCAL_RULES | Gitlab::Dangerfiles::CI_ONLY_RULES : Gitlab::Dangerfiles::LOCAL_RULES
|
103
|
-
end
|
104
|
-
|
105
80
|
def html_link(str)
|
106
81
|
ci? ? gitlab_helper.html_link(str) : str
|
107
82
|
end
|
@@ -148,23 +123,25 @@ module Danger
|
|
148
123
|
.sort
|
149
124
|
end
|
150
125
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
126
|
+
# Returns a string containing changed lines as git diff
|
127
|
+
#
|
128
|
+
# Considering changing a line in lib/gitlab/usage_data.rb it will return:
|
129
|
+
#
|
130
|
+
# [ "--- a/lib/gitlab/usage_data.rb",
|
131
|
+
# "+++ b/lib/gitlab/usage_data.rb",
|
132
|
+
# "+ # Test change",
|
133
|
+
# "- # Old change" ]
|
134
|
+
def changed_lines(changed_file)
|
135
|
+
diff = git.diff_for_file(changed_file)
|
136
|
+
return [] unless diff
|
137
|
+
|
138
|
+
diff.patch.split("\n").select { |line| %r{^[+-]}.match?(line) }
|
158
139
|
end
|
159
140
|
|
160
141
|
def release_automation?
|
161
142
|
gitlab_helper&.mr_author == RELEASE_TOOLS_BOT
|
162
143
|
end
|
163
144
|
|
164
|
-
def project_name
|
165
|
-
ee? ? "gitlab" : "gitlab-foss"
|
166
|
-
end
|
167
|
-
|
168
145
|
def markdown_list(items)
|
169
146
|
list = items.map { |item| "* `#{item}`" }.join("\n")
|
170
147
|
|
@@ -175,17 +152,51 @@ module Danger
|
|
175
152
|
end
|
176
153
|
end
|
177
154
|
|
178
|
-
# @return [Hash<
|
179
|
-
def changes_by_category
|
155
|
+
# @return [Hash<Symbol,Array<String>>]
|
156
|
+
def changes_by_category(categories)
|
180
157
|
all_changed_files.each_with_object(Hash.new { |h, k| h[k] = [] }) do |file, hash|
|
181
|
-
categories_for_file(file).each { |category| hash[category] << file }
|
158
|
+
categories_for_file(file, categories).each { |category| hash[category] << file }
|
182
159
|
end
|
183
160
|
end
|
184
161
|
|
185
|
-
#
|
162
|
+
# @return [Changes]
|
163
|
+
def changes(categories)
|
164
|
+
Changes.new([]).tap do |changes|
|
165
|
+
git.added_files.each do |file|
|
166
|
+
categories_for_file(file, categories).each { |category| changes << Change.new(file, :added, category) }
|
167
|
+
end
|
168
|
+
|
169
|
+
git.modified_files.each do |file|
|
170
|
+
categories_for_file(file, categories).each { |category| changes << Change.new(file, :modified, category) }
|
171
|
+
end
|
172
|
+
|
173
|
+
git.deleted_files.each do |file|
|
174
|
+
categories_for_file(file, categories).each { |category| changes << Change.new(file, :deleted, category) }
|
175
|
+
end
|
176
|
+
|
177
|
+
git.renamed_files.map { |x| x[:before] }.each do |file|
|
178
|
+
categories_for_file(file, categories).each { |category| changes << Change.new(file, :renamed_before, category) }
|
179
|
+
end
|
180
|
+
|
181
|
+
git.renamed_files.map { |x| x[:after] }.each do |file|
|
182
|
+
categories_for_file(file, categories).each { |category| changes << Change.new(file, :renamed_after, category) }
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
# Determines the categories a file is in, e.g., `[:frontend]`, `[:backend]`, or `%i[frontend engineering_productivity]`
|
188
|
+
# using filename regex and specific change regex if given.
|
189
|
+
#
|
186
190
|
# @return Array<Symbol>
|
187
|
-
def categories_for_file(file)
|
188
|
-
_, categories =
|
191
|
+
def categories_for_file(file, categories)
|
192
|
+
_, categories = categories.find do |key, _|
|
193
|
+
filename_regex, changes_regex = Array(key)
|
194
|
+
|
195
|
+
found = filename_regex.match?(file)
|
196
|
+
found &&= changed_lines(file).any? { |changed_line| changes_regex.match?(changed_line) } if changes_regex
|
197
|
+
|
198
|
+
found
|
199
|
+
end
|
189
200
|
|
190
201
|
Array(categories || :unknown)
|
191
202
|
end
|
@@ -202,43 +213,64 @@ module Danger
|
|
202
213
|
usernames.map { |u| Gitlab::Dangerfiles::Teammate.new("username" => u) }
|
203
214
|
end
|
204
215
|
|
205
|
-
def
|
206
|
-
|
207
|
-
["database"]
|
208
|
-
else
|
209
|
-
["database", "database::review pending"]
|
210
|
-
end
|
216
|
+
def mr_iid
|
217
|
+
return "" unless gitlab_helper
|
211
218
|
|
212
|
-
|
219
|
+
gitlab_helper.mr_json["iid"]
|
213
220
|
end
|
214
221
|
|
215
|
-
def
|
216
|
-
|
222
|
+
def mr_title
|
223
|
+
return "" unless gitlab_helper
|
224
|
+
|
225
|
+
gitlab_helper.mr_json["title"]
|
217
226
|
end
|
218
227
|
|
219
|
-
def
|
220
|
-
return
|
228
|
+
def mr_web_url
|
229
|
+
return "" unless gitlab_helper
|
230
|
+
|
231
|
+
gitlab_helper.mr_json["web_url"]
|
232
|
+
end
|
233
|
+
|
234
|
+
def mr_labels
|
235
|
+
return [] unless gitlab_helper
|
236
|
+
|
237
|
+
gitlab_helper.mr_labels
|
238
|
+
end
|
239
|
+
|
240
|
+
def mr_target_branch
|
241
|
+
return "" unless gitlab_helper
|
221
242
|
|
222
|
-
gitlab_helper.mr_json["
|
243
|
+
gitlab_helper.mr_json["target_branch"]
|
244
|
+
end
|
245
|
+
|
246
|
+
def draft_mr?
|
247
|
+
Gitlab::Dangerfiles::TitleLinting.has_draft_flag?(mr_title)
|
248
|
+
end
|
249
|
+
|
250
|
+
def security_mr?
|
251
|
+
mr_web_url.include?("/gitlab-org/security/")
|
223
252
|
end
|
224
253
|
|
225
254
|
def cherry_pick_mr?
|
226
|
-
|
255
|
+
Gitlab::Dangerfiles::TitleLinting.has_cherry_pick_flag?(mr_title)
|
256
|
+
end
|
227
257
|
|
228
|
-
|
258
|
+
def run_all_rspec_mr?
|
259
|
+
Gitlab::Dangerfiles::TitleLinting.has_run_all_rspec_flag?(mr_title)
|
229
260
|
end
|
230
261
|
|
231
|
-
def
|
232
|
-
|
262
|
+
def run_as_if_foss_mr?
|
263
|
+
Gitlab::Dangerfiles::TitleLinting.has_run_as_if_foss_flag?(mr_title)
|
264
|
+
end
|
233
265
|
|
234
|
-
|
266
|
+
def stable_branch?
|
267
|
+
/\A\d+-\d+-stable-ee/i.match?(mr_target_branch)
|
235
268
|
end
|
236
269
|
|
237
270
|
def mr_has_labels?(*labels)
|
238
|
-
return false unless gitlab_helper
|
239
|
-
|
240
271
|
labels = labels.flatten.uniq
|
241
|
-
|
272
|
+
|
273
|
+
(labels & mr_labels) == labels
|
242
274
|
end
|
243
275
|
|
244
276
|
def labels_list(labels, sep: ", ")
|
@@ -251,10 +283,20 @@ module Danger
|
|
251
283
|
"/label #{labels_list(labels, sep: " ")}"
|
252
284
|
end
|
253
285
|
|
254
|
-
|
286
|
+
def changed_files(regex)
|
287
|
+
all_changed_files.grep(regex)
|
288
|
+
end
|
255
289
|
|
256
290
|
def has_database_scoped_labels?(current_mr_labels)
|
257
291
|
current_mr_labels.any? { |label| label.start_with?("database::") }
|
258
292
|
end
|
293
|
+
|
294
|
+
def has_ci_changes?
|
295
|
+
changed_files(%r{\A(\.gitlab-ci\.yml|\.gitlab/ci/)}).any?
|
296
|
+
end
|
297
|
+
|
298
|
+
def group_label(labels)
|
299
|
+
labels.find { |label| label.start_with?("group::") }
|
300
|
+
end
|
259
301
|
end
|
260
302
|
end
|
data/lib/danger/roulette.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "../gitlab/dangerfiles/teammate"
|
4
|
+
require_relative "../gitlab/dangerfiles/weightage/maintainers"
|
5
|
+
require_relative "../gitlab/dangerfiles/weightage/reviewers"
|
4
6
|
|
5
7
|
module Danger
|
6
8
|
# Common helper functions for our danger scripts. See Danger::Helper
|
@@ -9,42 +11,58 @@ module Danger
|
|
9
11
|
ROULETTE_DATA_URL = "https://gitlab-org.gitlab.io/gitlab-roulette/roulette.json"
|
10
12
|
HOURS_WHEN_PERSON_CAN_BE_PICKED = (6..14).freeze
|
11
13
|
|
12
|
-
|
14
|
+
INCLUDE_TIMEZONE_FOR_CATEGORY = {
|
15
|
+
database: false,
|
16
|
+
}.freeze
|
17
|
+
|
18
|
+
Spin = Struct.new(:category, :reviewer, :maintainer, :optional_role, :timezone_experiment)
|
19
|
+
|
20
|
+
def team_mr_author
|
21
|
+
team.find { |person| person.username == mr_author_username }
|
22
|
+
end
|
13
23
|
|
14
24
|
# Assigns GitLab team members to be reviewer and maintainer
|
15
25
|
# for each change category that a Merge Request contains.
|
16
26
|
#
|
17
27
|
# @return [Array<Spin>]
|
18
|
-
def spin(project, categories,
|
19
|
-
|
20
|
-
|
21
|
-
rescue => err
|
22
|
-
warn("Reviewer roulette failed to load team data: #{err.message}")
|
23
|
-
[]
|
24
|
-
end
|
28
|
+
def spin(project, categories, timezone_experiment: false)
|
29
|
+
spins = categories.sort.map do |category|
|
30
|
+
including_timezone = INCLUDE_TIMEZONE_FOR_CATEGORY.fetch(category, timezone_experiment)
|
25
31
|
|
26
|
-
|
27
|
-
|
28
|
-
spin_per_category = categories.each_with_object({}) do |category, memo|
|
29
|
-
memo[category] = spin_for_category(team, project, category, canonical_branch_name, timezone_experiment: timezone_experiment)
|
32
|
+
spin_for_category(project, category, timezone_experiment: including_timezone)
|
30
33
|
end
|
31
34
|
|
32
|
-
|
33
|
-
|
35
|
+
backend_spin = spins.find { |spin| spin.category == :backend }
|
36
|
+
|
37
|
+
spins.each do |spin|
|
38
|
+
including_timezone = INCLUDE_TIMEZONE_FOR_CATEGORY.fetch(spin.category, timezone_experiment)
|
39
|
+
case spin.category
|
40
|
+
when :qa
|
41
|
+
# MR includes QA changes, but also other changes, and author isn't an SET
|
42
|
+
if categories.size > 1 && !team_mr_author&.any_capability?(project, spin.category)
|
43
|
+
spin.optional_role = :maintainer
|
44
|
+
end
|
34
45
|
when :test
|
46
|
+
spin.optional_role = :maintainer
|
47
|
+
|
35
48
|
if spin.reviewer.nil?
|
36
49
|
# Fetch an already picked backend reviewer, or pick one otherwise
|
37
|
-
spin.reviewer =
|
50
|
+
spin.reviewer = backend_spin&.reviewer || spin_for_category(project, :backend, timezone_experiment: including_timezone).reviewer
|
38
51
|
end
|
39
52
|
when :engineering_productivity
|
40
53
|
if spin.maintainer.nil?
|
41
54
|
# Fetch an already picked backend maintainer, or pick one otherwise
|
42
|
-
spin.maintainer =
|
55
|
+
spin.maintainer = backend_spin&.maintainer || spin_for_category(project, :backend, timezone_experiment: including_timezone).maintainer
|
56
|
+
end
|
57
|
+
when :ci_template
|
58
|
+
if spin.maintainer.nil?
|
59
|
+
# Fetch an already picked backend maintainer, or pick one otherwise
|
60
|
+
spin.maintainer = backend_spin&.maintainer || spin_for_category(project, :backend, timezone_experiment: including_timezone).maintainer
|
43
61
|
end
|
44
62
|
end
|
45
|
-
|
46
|
-
spin
|
47
63
|
end
|
64
|
+
|
65
|
+
spins
|
48
66
|
end
|
49
67
|
|
50
68
|
# Looks up the current list of GitLab team members and parses it into a
|
@@ -66,14 +84,9 @@ module Danger
|
|
66
84
|
# @return [Array<Teammate>]
|
67
85
|
def project_team(project_name)
|
68
86
|
team.select { |member| member.in_project?(project_name) }
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
branch_name.gsub(/^[ce]e-|-[ce]e$/, "")
|
73
|
-
end
|
74
|
-
|
75
|
-
def new_random(seed)
|
76
|
-
Random.new(Digest::MD5.hexdigest(seed).to_i(16))
|
87
|
+
rescue => err
|
88
|
+
warn("Reviewer roulette failed to load team data: #{err.message}")
|
89
|
+
[]
|
77
90
|
end
|
78
91
|
|
79
92
|
# Known issue: If someone is rejected due to OOO, and then becomes not OOO, the
|
@@ -106,30 +119,49 @@ module Danger
|
|
106
119
|
# @param [Teammate] person
|
107
120
|
# @return [Boolean]
|
108
121
|
def mr_author?(person)
|
109
|
-
person.username ==
|
122
|
+
person.username == mr_author_username
|
123
|
+
end
|
124
|
+
|
125
|
+
def mr_author_username
|
126
|
+
helper.gitlab_helper&.mr_author || `whoami`
|
127
|
+
end
|
128
|
+
|
129
|
+
def mr_source_branch
|
130
|
+
return `git rev-parse --abbrev-ref HEAD` unless helper.gitlab_helper&.mr_json
|
131
|
+
|
132
|
+
helper.gitlab_helper.mr_json["source_branch"]
|
133
|
+
end
|
134
|
+
|
135
|
+
def mr_labels
|
136
|
+
helper.gitlab_helper&.mr_labels || []
|
137
|
+
end
|
138
|
+
|
139
|
+
def new_random(seed)
|
140
|
+
Random.new(Digest::MD5.hexdigest(seed).to_i(16))
|
110
141
|
end
|
111
142
|
|
112
143
|
def spin_role_for_category(team, role, project, category)
|
113
144
|
team.select do |member|
|
114
|
-
member.public_send("#{role}?", project, category,
|
145
|
+
member.public_send("#{role}?", project, category, mr_labels) # rubocop:disable GitlabSecurity/PublicSend
|
115
146
|
end
|
116
147
|
end
|
117
148
|
|
118
|
-
def spin_for_category(
|
149
|
+
def spin_for_category(project, category, timezone_experiment: false)
|
150
|
+
team = project_team(project)
|
119
151
|
reviewers, traintainers, maintainers =
|
120
152
|
%i[reviewer traintainer maintainer].map do |role|
|
121
153
|
spin_role_for_category(team, role, project, category)
|
122
154
|
end
|
123
155
|
|
124
|
-
|
125
|
-
|
156
|
+
random = new_random(mr_source_branch)
|
157
|
+
|
158
|
+
weighted_reviewers = Gitlab::Dangerfiles::Weightage::Reviewers.new(reviewers, traintainers).execute
|
159
|
+
weighted_maintainers = Gitlab::Dangerfiles::Weightage::Maintainers.new(maintainers).execute
|
126
160
|
|
127
|
-
|
128
|
-
|
129
|
-
reviewer = spin_for_person(reviewers + traintainers + traintainers, random: random, timezone_experiment: timezone_experiment)
|
130
|
-
maintainer = spin_for_person(maintainers, random: random, timezone_experiment: timezone_experiment)
|
161
|
+
reviewer = spin_for_person(weighted_reviewers, random: random, timezone_experiment: timezone_experiment)
|
162
|
+
maintainer = spin_for_person(weighted_maintainers, random: random, timezone_experiment: timezone_experiment)
|
131
163
|
|
132
|
-
Spin.new(category, reviewer, maintainer)
|
164
|
+
Spin.new(category, reviewer, maintainer, false, timezone_experiment)
|
133
165
|
end
|
134
166
|
end
|
135
167
|
end
|