gitlab-dangerfiles 3.11.0 → 3.13.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2ee27fb91564bfb45f28aed3fca576c6731c91ae9f69719e2ebb0ce5807ff1ee
4
- data.tar.gz: 3bcd268c5fc1a91141a447ff6bb1b0c63841fe4dab2c65fffc61c7c488048275
3
+ metadata.gz: fae45cdf2a0c840f86b2d1864e521587210e4f365d2d03727be0d73866e4379c
4
+ data.tar.gz: a8380520fe8d4d12be578493244570265023db9f850ff374cd879591fb533b02
5
5
  SHA512:
6
- metadata.gz: d5cab2d3171779a9f28c00452e4e0435a6aa93852d80847b4da3b03f38fe294e7c855232b1402d6f3ac14f99b04518993b5fb6401da928ed9189f86a44948769
7
- data.tar.gz: dc580aa4781087b6598c8d4f2befb2fec6b9d87ae4ce964227b35a4fbc537c62f2bad0e4d947a65154753157a896cb890472be33d99f0e15463d63beed17b6ee
6
+ metadata.gz: 178104293164685aa9b265505785872372ad621b92b15fca37a590be070e7abbfd4090c339f3869c1c9e4da56281800b479c96c6992fb141e358320944e508ab
7
+ data.tar.gz: bb6f9c2b409a904517d7f8e91918ddc7df959de37b41a25cd898398749d227e5b40755669a406e3bd8063df255f8639d5fccdef37c2cd150cad31e6c3d036f11
data/.rubocop.yml CHANGED
@@ -20,7 +20,7 @@ Layout/LineLength:
20
20
  Enabled: false
21
21
 
22
22
  RSpec/MultipleMemoizedHelpers:
23
- Max: 30
23
+ Max: 35
24
24
 
25
25
  RSpec/FilePath:
26
26
  Enabled: false
@@ -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
- INCLUDE_TIMEZONE_FOR_CATEGORY = {
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], timezone_experiment: false)
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
- including_timezone = INCLUDE_TIMEZONE_FOR_CATEGORY.fetch(category, timezone_experiment)
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, timezone_experiment: including_timezone).reviewer
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, timezone_experiment: including_timezone).maintainer
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, timezone_experiment: including_timezone).maintainer
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, timezone_experiment: including_timezone).maintainer
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 required_approvals
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["approvals_required"] > 0 &&
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, timezone_experiment: false)
227
+ def spin_for_person(people)
231
228
  shuffled_people = people.shuffle(random: random)
232
229
 
233
- if timezone_experiment
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, timezone_experiment: false)
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, timezone_experiment: timezone_experiment)
288
- maintainer = spin_for_person(weighted_maintainers, timezone_experiment: timezone_experiment)
280
+ reviewer = spin_for_person(weighted_reviewers)
281
+ maintainer = spin_for_person(weighted_maintainers)
289
282
 
290
- Spin.new(category, reviewer, maintainer, false, timezone_experiment)
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
- ux_spin = spin(nil, [:ux]).first
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
- can_review_wider_community_contribution?(teammate)
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
- can_review_team_memeber_contribution?(teammate)
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
@@ -1,5 +1,5 @@
1
1
  module Gitlab
2
2
  module Dangerfiles
3
- VERSION = "3.11.0"
3
+ VERSION = "3.13.0"
4
4
  end
5
5
  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.11.0
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-06-22 00:00:00.000000000 Z
11
+ date: 2023-08-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake