gitlab-dangerfiles 3.13.0 → 4.10.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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -1
  3. data/.gitlab/CODEOWNERS +1 -1
  4. data/.gitlab/merge_request_templates/Release.md +1 -1
  5. data/.gitlab-ci.yml +21 -42
  6. data/.rubocop.yml +6 -16
  7. data/.rubocop_todo.yml +5 -8
  8. data/Gemfile +0 -16
  9. data/Gemfile.lock +234 -0
  10. data/README.md +96 -9
  11. data/gitlab-dangerfiles.gemspec +13 -5
  12. data/lefthook.yml +0 -5
  13. data/lib/danger/plugins/changelog.rb +9 -7
  14. data/lib/danger/plugins/duo_code.rb +12 -0
  15. data/lib/danger/plugins/internal/helper.rb +34 -10
  16. data/lib/danger/plugins/roulette.rb +95 -256
  17. data/lib/danger/rules/commit_messages/Dangerfile +2 -7
  18. data/lib/danger/rules/duo_code_review/Dangerfile +10 -0
  19. data/lib/danger/rules/simple_roulette/Dangerfile +17 -10
  20. data/lib/danger/rules/type_label/Dangerfile +0 -8
  21. data/lib/danger/rules/z_add_labels/Dangerfile +3 -3
  22. data/lib/gitlab/dangerfiles/approval.rb +22 -0
  23. data/lib/gitlab/dangerfiles/base_linter.rb +1 -1
  24. data/lib/gitlab/dangerfiles/capability.rb +82 -0
  25. data/lib/gitlab/dangerfiles/commit_linter.rb +2 -2
  26. data/lib/gitlab/dangerfiles/config.rb +29 -3
  27. data/lib/gitlab/dangerfiles/emoji_checker.rb +1 -1
  28. data/lib/gitlab/dangerfiles/spec_helper.rb +231 -1
  29. data/lib/gitlab/dangerfiles/spin.rb +15 -0
  30. data/lib/gitlab/dangerfiles/spinner.rb +191 -0
  31. data/lib/gitlab/dangerfiles/teammate.rb +94 -20
  32. data/lib/gitlab/dangerfiles/type_label_guesser.rb +2 -2
  33. data/lib/gitlab/dangerfiles/version.rb +1 -1
  34. data/lib/gitlab/dangerfiles.rb +0 -1
  35. metadata +100 -25
  36. data/lib/danger/rules/subtype_label/Dangerfile +0 -14
  37. data/lib/gitlab/dangerfiles/category.rb +0 -111
@@ -0,0 +1,191 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "spin"
4
+ require_relative "teammate"
5
+ require_relative "weightage/maintainers"
6
+ require_relative "weightage/reviewers"
7
+
8
+ module Gitlab
9
+ module Dangerfiles
10
+ class Spinner
11
+ attr_reader :project, :author, :team_author, :labels, :categories
12
+
13
+ def initialize(
14
+ project:, author:, team_author: nil, labels: [], categories: [],
15
+ random: Random.new, ux_fallback_wider_community_reviewer: nil)
16
+ @project = project
17
+ @author = author
18
+ @team_author = team_author
19
+ @labels = labels
20
+ @categories = categories.reject do |category|
21
+ import_and_integrate_reject_category?(project, category, labels)
22
+ end
23
+ @random = random
24
+ @ux_fallback_wider_community_reviewer = ux_fallback_wider_community_reviewer
25
+ end
26
+
27
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
28
+ def spin
29
+ spins = categories.sort_by(&:to_s).map do |category|
30
+ spin_for_category(category)
31
+ end
32
+
33
+ backend_spin = spins.find { |spin| spin.category == :backend }
34
+ frontend_spin = spins.find { |spin| spin.category == :frontend }
35
+
36
+ spins.each do |spin|
37
+ case spin.category
38
+ when :qa
39
+ spin.optional_role = :maintainer if
40
+ categories.size > 1 && author_no_qa_capability?
41
+ when :test
42
+ spin.optional_role = :maintainer
43
+
44
+ if spin.no_reviewer?
45
+ # Fetch an already picked backend reviewer, or pick one otherwise
46
+ spin.reviewer = backend_spin&.reviewer || spin_for_category(:backend).reviewer
47
+ end
48
+ when :tooling
49
+ if spin.no_maintainer?
50
+ # Fetch an already picked backend maintainer, or pick one otherwise
51
+ spin.maintainer = backend_spin&.maintainer || spin_for_category(:backend).maintainer
52
+ end
53
+ when :ci_template # rubocop:disable Lint/DuplicateBranch -- bug?
54
+ if spin.no_maintainer?
55
+ # Fetch an already picked backend maintainer, or pick one otherwise
56
+ spin.maintainer = backend_spin&.maintainer || spin_for_category(:backend).maintainer
57
+ end
58
+ when :analytics_instrumentation
59
+ spin.optional_role = :maintainer
60
+
61
+ if spin.no_maintainer?
62
+ # Fetch an already picked maintainer, or pick one otherwise
63
+ spin.maintainer = backend_spin&.maintainer || frontend_spin&.maintainer || spin_for_category(:backend).maintainer
64
+ end
65
+ when :import_integrate_be, :import_integrate_fe
66
+ spin.optional_role = :maintainer
67
+ when :ux
68
+ spin.optional_role = :maintainer
69
+
70
+ # We want at least a UX reviewer who can review any wider community
71
+ # contribution even without a team designer. We assign this to Pedro.
72
+ spin.reviewer = ux_fallback_wider_community_reviewer if
73
+ labels.include?("Community contribution") &&
74
+ spin.no_reviewer? &&
75
+ spin.no_maintainer?
76
+ end
77
+ end
78
+
79
+ spins
80
+ end
81
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
82
+
83
+ # Spin a reviewer for a particular approval rule
84
+ #
85
+ # @param [Hash] rule of approval
86
+ #
87
+ # @return [Gitlab::Dangerfiles::Teammate]
88
+ def spin_for_approver(rule)
89
+ approvers = rule["eligible_approvers"].filter_map do |approver|
90
+ Gitlab::Dangerfiles::Teammate.find_member(
91
+ approver["username"], project: project)
92
+ end
93
+
94
+ spin_for_person(approvers) || spin_for_approver_fallback(rule)
95
+ end
96
+
97
+ private
98
+
99
+ attr_reader :random, :ux_fallback_wider_community_reviewer
100
+
101
+ # Reject Import and Integrate categories if the MR author has reviewing abilities for the category.
102
+ #
103
+ # @param [String] category name
104
+ # @return [Boolean]
105
+ def import_and_integrate_reject_category?(project, category, labels)
106
+ [:import_integrate_be, :import_integrate_fe].include?(category) && team_author &&
107
+ (team_author.reviewer?(project, category, labels) || team_author.maintainer?(project, category, labels))
108
+ end
109
+
110
+ # MR includes QA changes, but also other changes, and author isn't an SET
111
+ def author_no_qa_capability?
112
+ !(team_author && team_author.capabilities(project).any? { |capability| capability.end_with?("qa") })
113
+ end
114
+
115
+ def spin_for_category(category)
116
+ reviewers, traintainers, maintainers =
117
+ %i[reviewer traintainer maintainer].map do |role|
118
+ spin_role_for_category(role, category)
119
+ end
120
+
121
+ weighted_reviewers = Weightage::Reviewers.new(reviewers, traintainers).execute
122
+ weighted_maintainers = Weightage::Maintainers.new(maintainers).execute
123
+
124
+ reviewer = spin_for_person(weighted_reviewers)
125
+ maintainer = spin_for_person(weighted_maintainers)
126
+
127
+ # allow projects with small number of reviewers to take from maintainers if possible
128
+ if reviewer.nil? && weighted_maintainers.uniq.size > 1
129
+ weighted_maintainers.delete(maintainer)
130
+ reviewer = spin_for_person(weighted_maintainers)
131
+ end
132
+
133
+ Spin.new(category, reviewer, maintainer, false)
134
+ end
135
+
136
+ def spin_role_for_category(role, category)
137
+ team.select do |member|
138
+ member.public_send(:"#{role}?", project, category, labels)
139
+ end
140
+ end
141
+
142
+ # Known issue: If someone is rejected due to OOO, and then becomes not OOO, the
143
+ # selection will change on next spin.
144
+ #
145
+ # @param [Array<Gitlab::Dangerfiles::Teammate>] people
146
+ #
147
+ # @return [Gitlab::Dangerfiles::Teammate]
148
+ def spin_for_person(people)
149
+ shuffled_people = people.shuffle(random: random)
150
+
151
+ shuffled_people.find { |person| valid_person?(person) }
152
+ end
153
+
154
+ # @param [Gitlab::Dangerfiles::Teammate] person
155
+ # @return [Boolean]
156
+ def valid_person?(person)
157
+ person.username != author && person.available
158
+ end
159
+
160
+ # It can be possible that we don't have a valid reviewer for approval.
161
+ # In this case, we sample again without considering:
162
+ #
163
+ # * If they're available
164
+ # * If they're an actual reviewer from roulette data
165
+ #
166
+ # We do this because we strictly require an approval from the approvers.
167
+ #
168
+ # @param [Hash] rule of approval
169
+ #
170
+ # @return [Gitlab::Dangerfiles::Teammate]
171
+ def spin_for_approver_fallback(rule)
172
+ fallback_approvers = rule["eligible_approvers"].map do |approver|
173
+ Teammate.find_member(approver["username"]) || Teammate.new(approver)
174
+ end
175
+
176
+ # Intentionally not using `spin_for_person` to skip `valid_person?`.
177
+ # This should strictly return someone so we don't filter anything,
178
+ # and it's a fallback mechanism which should not happen often that
179
+ # deserves a complex algorithm.
180
+ fallback_approvers.sample(random: random)
181
+ end
182
+
183
+ # @return [Array<Gitlab::Dangerfiles::Teammate>]
184
+ def team
185
+ @team ||= Teammate.company_members.select do |member|
186
+ member.in_project?(project)
187
+ end
188
+ end
189
+ end
190
+ end
191
+ end
@@ -1,12 +1,84 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "category"
3
+ require "net/http"
4
+ require "json"
5
+
6
+ require_relative "capability"
4
7
 
5
8
  module Gitlab
6
9
  module Dangerfiles
7
10
  class Teammate
11
+ ROULETTE_DATA_URL = "https://gitlab-org.gitlab.io/gitlab-roulette/roulette.json"
12
+
13
+ def self.find_member(username, project: nil)
14
+ company_members.find do |member|
15
+ member.username == username &&
16
+ (project.nil? || member.in_project?(project))
17
+ end
18
+ end
19
+
20
+ def self.has_member_for_the_group?(category, labels:, **arguments)
21
+ capabilities = %i[reviewer maintainer].map do |kind|
22
+ # Use new to use the base class for original has_capability? method
23
+ Capability.new(category: category, kind: kind, labels: labels, **arguments)
24
+ end
25
+
26
+ company_members.any? do |teammate|
27
+ capabilities.any? do |capability|
28
+ capability.has_capability?(teammate) &&
29
+ teammate.member_of_the_group?(labels)
30
+ end
31
+ end
32
+ end
33
+
34
+ # Looks up the current list of GitLab team members and parses it into a
35
+ # useful form.
36
+ #
37
+ # @return [Array<Gitlab::Dangerfiles::Teammate>]
38
+ def self.company_members
39
+ @company_members ||= fetch_company_members
40
+ end
41
+
42
+ def self.fetch_company_members
43
+ data = http_get_json(ROULETTE_DATA_URL) || []
44
+ data.map { |hash| Teammate.new(hash) }
45
+ rescue JSON::ParserError
46
+ warnings << "Failed to parse JSON response from #{ROULETTE_DATA_URL}"
47
+ []
48
+ end
49
+
50
+ # Fetches the given +url+ and parse its response as JSON.
51
+ #
52
+ # @param [String] url
53
+ #
54
+ # @return [Hash, Array, NilClass]
55
+ def self.http_get_json(url)
56
+ rsp = Net::HTTP.get_response(URI.parse(url))
57
+
58
+ if rsp.is_a?(Net::HTTPRedirection)
59
+ uri = URI.parse(rsp.header["location"])
60
+
61
+ uri.query = nil if uri
62
+
63
+ warnings << "Redirection detected: #{uri}."
64
+ return nil
65
+ end
66
+
67
+ unless rsp.is_a?(Net::HTTPOK)
68
+ message = rsp.message[0, 30]
69
+ warnings << "HTTPError: Failed to read #{url}: #{rsp.code} #{message}."
70
+ return nil
71
+ end
72
+
73
+ JSON.parse(rsp.body)
74
+ end
75
+
76
+ def self.warnings
77
+ @warnings ||= []
78
+ end
79
+
8
80
  attr_reader :options, :username, :name, :role, :specialty, :projects, :available, :hungry, :reduced_capacity, :tz_offset_hours,
9
- :only_maintainer_reviews
81
+ :only_maintainer_reviews
10
82
 
11
83
  # The options data are produced by https://gitlab.com/gitlab-org/gitlab-roulette/-/blob/main/lib/team_member.rb
12
84
  def initialize(options = {})
@@ -14,7 +86,7 @@ module Gitlab
14
86
  @username = options["username"]
15
87
  @name = options["name"]
16
88
  @markdown_name = options["markdown_name"] ||
17
- default_markdown_name(*options.values_at("username", "name"))
89
+ default_markdown_name(options["username"])
18
90
  @role = options["role"]
19
91
  @specialty = options["specialty"]
20
92
  @projects = process_projects(options["projects"])
@@ -25,6 +97,20 @@ module Gitlab
25
97
  @only_maintainer_reviews = options["only_maintainer_reviews"]
26
98
  end
27
99
 
100
+ def member_of_the_group?(labels)
101
+ # Specialty can be:
102
+ # Source Code
103
+ # [Growth: Activation, Growth: Expansion]
104
+ # Runner
105
+ group_labels = Array(specialty).map do |field|
106
+ group = field.strip.sub(/^.+: ?/, "").downcase
107
+
108
+ "group::#{group}"
109
+ end
110
+
111
+ (group_labels & labels).any?
112
+ end
113
+
28
114
  def to_h
29
115
  options
30
116
  end
@@ -55,18 +141,6 @@ module Gitlab
55
141
  has_capability?(project, category, :maintainer, labels)
56
142
  end
57
143
 
58
- def import_integrate_be?(project, category, labels)
59
- return false unless category == :import_integrate_be
60
-
61
- has_capability?(project, category, :reviewer, labels)
62
- end
63
-
64
- def import_integrate_fe?(project, category, labels)
65
- return false unless category == :import_integrate_fe
66
-
67
- has_capability?(project, category, :reviewer, labels)
68
- end
69
-
70
144
  def markdown_name(author: nil)
71
145
  "#{@markdown_name}#{utc_offset_text(author)}"
72
146
  end
@@ -89,8 +163,8 @@ module Gitlab
89
163
 
90
164
  private
91
165
 
92
- def default_markdown_name(username, name)
93
- "[#{name}](https://gitlab.com/#{username}) (`@#{username}`)"
166
+ def default_markdown_name(username)
167
+ "`@#{username}` [![profile link](https://gitlab.com/gitlab-org/gitlab-svgs/-/raw/main/sprite_icons/user.svg?ref_type=heads)](https://gitlab.com/#{username})"
94
168
  end
95
169
 
96
170
  def process_projects(projects)
@@ -119,16 +193,16 @@ module Gitlab
119
193
 
120
194
  def offset_diff_compared_to_author(author)
121
195
  diff = floored_offset_hours - author.floored_offset_hours
122
- return "same timezone as `@#{author.username}`" if diff == 0
196
+ return "same timezone as author" if diff == 0
123
197
 
124
198
  ahead_or_behind = diff < 0 ? "behind" : "ahead of"
125
199
  pluralized_hours = pluralize(diff.abs, "hour", "hours")
126
200
 
127
- "#{pluralized_hours} #{ahead_or_behind} `@#{author.username}`"
201
+ "#{pluralized_hours} #{ahead_or_behind} author"
128
202
  end
129
203
 
130
204
  def has_capability?(project, category, kind, labels)
131
- Category.for(category, project: project, kind: kind, labels: labels).has_capability?(self)
205
+ Capability.for(category, project: project, kind: kind, labels: labels).has_capability?(self)
132
206
  end
133
207
 
134
208
  def pluralize(count, singular, plural)
@@ -8,8 +8,8 @@ module Gitlab
8
8
  security: %w[type::bug bug::vulnerability],
9
9
  performance: %w[type::bug bug::performance],
10
10
  added: %w[type::feature feature::addition],
11
- deprecated: %w[type::feature feature::removal],
12
- removed: %w[type::feature feature::removal],
11
+ deprecated: %w[type::maintenance maintenance::removal],
12
+ removed: %w[type::maintenance maintenance::removal]
13
13
  }.freeze
14
14
 
15
15
  def labels_from_changelog_categories(categories)
@@ -1,5 +1,5 @@
1
1
  module Gitlab
2
2
  module Dangerfiles
3
- VERSION = "3.13.0"
3
+ VERSION = "4.10.0"
4
4
  end
5
5
  end
@@ -8,7 +8,6 @@ module Gitlab
8
8
  metadata
9
9
  simple_roulette
10
10
  type_label
11
- subtype_label
12
11
  z_add_labels
13
12
  z_retry_link
14
13
  ].freeze
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitlab-dangerfiles
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.13.0
4
+ version: 4.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitLab
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-08-02 00:00:00.000000000 Z
11
+ date: 2025-07-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '13.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: '13.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: danger-gitlab
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -44,28 +44,70 @@ dependencies:
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: 8.4.5
47
+ version: 9.3.0
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: 8.4.5
54
+ version: 9.3.0
55
55
  - !ruby/object:Gem::Dependency
56
- name: rspec
56
+ name: climate_control
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: gitlab-styles
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
73
  - - "~>"
60
74
  - !ruby/object:Gem::Version
61
- version: '3.0'
75
+ version: '10.0'
62
76
  type: :development
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
80
  - - "~>"
67
81
  - !ruby/object:Gem::Version
68
- version: '3.0'
82
+ version: '10.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: guard-rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 4.7.3
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 4.7.3
97
+ - !ruby/object:Gem::Dependency
98
+ name: lefthook
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.3'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.3'
69
111
  - !ruby/object:Gem::Dependency
70
112
  name: rspec-parameterized
71
113
  requirement: !ruby/object:Gem::Requirement
@@ -81,21 +123,49 @@ dependencies:
81
123
  - !ruby/object:Gem::Version
82
124
  version: '0'
83
125
  - !ruby/object:Gem::Dependency
84
- name: timecop
126
+ name: rspec
85
127
  requirement: !ruby/object:Gem::Requirement
86
128
  requirements:
87
- - - ">="
129
+ - - "~>"
88
130
  - !ruby/object:Gem::Version
89
- version: '0'
131
+ version: '3.8'
90
132
  type: :development
91
133
  prerelease: false
92
134
  version_requirements: !ruby/object:Gem::Requirement
93
135
  requirements:
94
- - - ">="
136
+ - - "~>"
95
137
  - !ruby/object:Gem::Version
96
- version: '0'
138
+ version: '3.8'
97
139
  - !ruby/object:Gem::Dependency
98
- name: webmock
140
+ name: racc
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '1.8'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '1.8'
153
+ - !ruby/object:Gem::Dependency
154
+ name: rubocop-rails
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "<"
158
+ - !ruby/object:Gem::Version
159
+ version: 2.21.2
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "<"
165
+ - !ruby/object:Gem::Version
166
+ version: 2.21.2
167
+ - !ruby/object:Gem::Dependency
168
+ name: timecop
99
169
  requirement: !ruby/object:Gem::Requirement
100
170
  requirements:
101
171
  - - ">="
@@ -109,7 +179,7 @@ dependencies:
109
179
  - !ruby/object:Gem::Version
110
180
  version: '0'
111
181
  - !ruby/object:Gem::Dependency
112
- name: climate_control
182
+ name: webmock
113
183
  requirement: !ruby/object:Gem::Requirement
114
184
  requirements:
115
185
  - - ">="
@@ -123,7 +193,7 @@ dependencies:
123
193
  - !ruby/object:Gem::Version
124
194
  version: '0'
125
195
  - !ruby/object:Gem::Dependency
126
- name: rufo
196
+ name: yard
127
197
  requirement: !ruby/object:Gem::Requirement
128
198
  requirements:
129
199
  - - ">="
@@ -157,6 +227,7 @@ files:
157
227
  - CONTRIBUTING.md
158
228
  - Dangerfile
159
229
  - Gemfile
230
+ - Gemfile.lock
160
231
  - Guardfile
161
232
  - LICENSE.txt
162
233
  - README.md
@@ -168,29 +239,33 @@ files:
168
239
  - gitlab-dangerfiles.gemspec
169
240
  - lefthook.yml
170
241
  - lib/danger/plugins/changelog.rb
242
+ - lib/danger/plugins/duo_code.rb
171
243
  - lib/danger/plugins/internal/helper.rb
172
244
  - lib/danger/plugins/roulette.rb
173
245
  - lib/danger/rules/changelog/Dangerfile
174
246
  - lib/danger/rules/changes_size/Dangerfile
175
247
  - lib/danger/rules/commit_messages/Dangerfile
176
248
  - lib/danger/rules/commits_counter/Dangerfile
249
+ - lib/danger/rules/duo_code_review/Dangerfile
177
250
  - lib/danger/rules/metadata/Dangerfile
178
251
  - lib/danger/rules/simple_roulette/Dangerfile
179
- - lib/danger/rules/subtype_label/Dangerfile
180
252
  - lib/danger/rules/type_label/Dangerfile
181
253
  - lib/danger/rules/z_add_labels/Dangerfile
182
254
  - lib/danger/rules/z_retry_link/Dangerfile
183
255
  - lib/gitlab-dangerfiles.rb
184
256
  - lib/gitlab/Dangerfile
185
257
  - lib/gitlab/dangerfiles.rb
258
+ - lib/gitlab/dangerfiles/approval.rb
186
259
  - lib/gitlab/dangerfiles/base_linter.rb
187
- - lib/gitlab/dangerfiles/category.rb
260
+ - lib/gitlab/dangerfiles/capability.rb
188
261
  - lib/gitlab/dangerfiles/changes.rb
189
262
  - lib/gitlab/dangerfiles/commit_linter.rb
190
263
  - lib/gitlab/dangerfiles/config.rb
191
264
  - lib/gitlab/dangerfiles/emoji_checker.rb
192
265
  - lib/gitlab/dangerfiles/merge_request_linter.rb
193
266
  - lib/gitlab/dangerfiles/spec_helper.rb
267
+ - lib/gitlab/dangerfiles/spin.rb
268
+ - lib/gitlab/dangerfiles/spinner.rb
194
269
  - lib/gitlab/dangerfiles/task_loader.rb
195
270
  - lib/gitlab/dangerfiles/tasks/main.rake
196
271
  - lib/gitlab/dangerfiles/teammate.rb
@@ -208,7 +283,7 @@ metadata:
208
283
  homepage_uri: https://gitlab.com/gitlab-org/ruby/gems/gitlab-dangerfiles
209
284
  source_code_uri: https://gitlab.com/gitlab-org/ruby/gems/gitlab-dangerfiles
210
285
  changelog_uri: https://gitlab.com/gitlab-org/ruby/gems/gitlab-dangerfiles/-/releases
211
- post_install_message:
286
+ post_install_message:
212
287
  rdoc_options: []
213
288
  require_paths:
214
289
  - lib
@@ -223,8 +298,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
223
298
  - !ruby/object:Gem::Version
224
299
  version: '0'
225
300
  requirements: []
226
- rubygems_version: 3.1.6
227
- signing_key:
301
+ rubygems_version: 3.5.22
302
+ signing_key:
228
303
  specification_version: 4
229
304
  summary: This gem provides common Dangerfile and plugins for GitLab projects.
230
305
  test_files: []
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- SUBTYPE_LABEL_MISSING_MESSAGE = "Please add a [merge request subtype](https://about.gitlab.com/handbook/engineering/metrics/#work-type-classification) to this merge request."
4
-
5
- types = %w(bug feature maintenance)
6
- types.each do |type|
7
- return if helper.has_scoped_label_with_scope?(type)
8
- end
9
-
10
- if ENV['DANGER_ERROR_WHEN_SUBTYPE_LABEL_IS_MISSING'] == 'true'
11
- fail SUBTYPE_LABEL_MISSING_MESSAGE
12
- else
13
- warn SUBTYPE_LABEL_MISSING_MESSAGE
14
- end