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 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