gitlab-dangerfiles 4.6.0 → 4.8.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.
@@ -17,7 +17,7 @@ module DangerSpecHelper
17
17
  "GITLAB_CI" => "true",
18
18
  "DANGER_GITLAB_HOST" => "gitlab.example.com",
19
19
  "CI_MERGE_REQUEST_IID" => 28_493,
20
- "DANGER_GITLAB_API_TOKEN" => "123sbdq54erfsd3422gdfio",
20
+ "DANGER_GITLAB_API_TOKEN" => "123sbdq54erfsd3422gdfio"
21
21
  }
22
22
  end
23
23
 
@@ -45,6 +45,19 @@ module DangerSpecHelper
45
45
  end
46
46
  end
47
47
 
48
+ RSpec::Matchers.define :match_teammates do |expected|
49
+ match do |actual|
50
+ expected.each do |expected_person|
51
+ matched_person = actual.find { |actual_person| actual_person.name == expected_person.username }
52
+
53
+ matched_person &&
54
+ matched_person.name == expected_person.name &&
55
+ matched_person.role == expected_person.role &&
56
+ matched_person.projects == expected_person.projects
57
+ end
58
+ end
59
+ end
60
+
48
61
  RSpec.shared_context "with dangerfile" do
49
62
  let(:dangerfile) { DangerSpecHelper.testing_dangerfile }
50
63
  let(:added_files) { %w[added-from-git] }
@@ -68,3 +81,220 @@ RSpec.shared_context "with dangerfile" do
68
81
  allow(dangerfile.helper).to receive(:changes).and_return(changes) if dangerfile.respond_to?(:helper)
69
82
  end
70
83
  end
84
+
85
+ RSpec.shared_context "with teammates" do
86
+ let(:backend_available) { true }
87
+ let(:backend_tz_offset_hours) { 2.0 }
88
+ let(:backend_maintainer_project) { { "gitlab" => "maintainer backend" } }
89
+ let(:backend_maintainer) do
90
+ Gitlab::Dangerfiles::Teammate.new(
91
+ "username" => "backend-maintainer",
92
+ "name" => "Backend maintainer",
93
+ "role" => "Backend engineer",
94
+ "projects" => backend_maintainer_project,
95
+ "available" => backend_available,
96
+ "tz_offset_hours" => backend_tz_offset_hours
97
+ )
98
+ end
99
+
100
+ let(:another_backend_maintainer) do
101
+ Gitlab::Dangerfiles::Teammate.new(
102
+ "username" => "another-backend-maintainer",
103
+ "name" => "Another Backend Maintainer",
104
+ "role" => "Backend engineer",
105
+ "projects" => backend_maintainer_project,
106
+ "available" => backend_available,
107
+ "tz_offset_hours" => backend_tz_offset_hours
108
+ )
109
+ end
110
+
111
+ let(:backend_reviewer_available) { true }
112
+ let(:backend_reviewer) do
113
+ Gitlab::Dangerfiles::Teammate.new(
114
+ "username" => "backend-reviewer",
115
+ "name" => "Backend reviewer",
116
+ "role" => "Backend engineer",
117
+ "projects" => { "gitlab" => "reviewer backend" },
118
+ "available" => backend_reviewer_available,
119
+ "tz_offset_hours" => 1.0
120
+ )
121
+ end
122
+
123
+ let(:frontend_reviewer) do
124
+ Gitlab::Dangerfiles::Teammate.new(
125
+ "username" => "frontend-reviewer",
126
+ "name" => "Frontend reviewer",
127
+ "role" => "Frontend engineer",
128
+ "projects" => { "gitlab" => "reviewer frontend" },
129
+ "available" => true,
130
+ "tz_offset_hours" => 2.0
131
+ )
132
+ end
133
+
134
+ let(:frontend_maintainer) do
135
+ Gitlab::Dangerfiles::Teammate.new(
136
+ "username" => "frontend-maintainer",
137
+ "name" => "Frontend maintainer",
138
+ "role" => "Frontend engineer",
139
+ "projects" => { "gitlab" => "maintainer frontend" },
140
+ "available" => true,
141
+ "tz_offset_hours" => 2.0
142
+ )
143
+ end
144
+
145
+ let(:ux_reviewer) do
146
+ Gitlab::Dangerfiles::Teammate.new(
147
+ "username" => "ux-reviewer",
148
+ "name" => "UX reviewer",
149
+ "role" => "Product Designer",
150
+ "projects" => { "gitlab" => "reviewer ux" },
151
+ "specialty" => "Create: Source Code",
152
+ "available" => true,
153
+ "tz_offset_hours" => 2.0
154
+ )
155
+ end
156
+
157
+ let(:software_engineer_in_test) do
158
+ Gitlab::Dangerfiles::Teammate.new(
159
+ "username" => "software-engineer-in-test",
160
+ "name" => "Software Engineer in Test",
161
+ "role" => "Software Engineer in Test, Create:Source Code",
162
+ "projects" => { "gitlab" => "maintainer qa", "gitlab-qa" => "maintainer" },
163
+ "available" => true,
164
+ "tz_offset_hours" => 2.0
165
+ )
166
+ end
167
+
168
+ let(:software_engineer_in_import_integrate_fe) do
169
+ Gitlab::Dangerfiles::Teammate.new(
170
+ "username" => "software-engineer-in-import-and-integrate-fe",
171
+ "name" => "Software Engineer in Import and Integrate FE",
172
+ "role" => "Frontend Engineer, Manage:Import and Integrate",
173
+ "projects" => { "gitlab" => "reviewer frontend" },
174
+ "available" => true,
175
+ "tz_offset_hours" => 2.0
176
+ )
177
+ end
178
+
179
+ let(:software_engineer_in_import_integrate_be) do
180
+ Gitlab::Dangerfiles::Teammate.new(
181
+ "username" => "software-engineer-in-import-and-integrate-be",
182
+ "name" => "Software Engineer in Import and Integrate BE",
183
+ "role" => "Backend Engineer, Manage:Import and Integrate",
184
+ "projects" => { "gitlab" => "reviewer backend" },
185
+ "available" => true,
186
+ "tz_offset_hours" => 2.0
187
+ )
188
+ end
189
+
190
+ let(:tooling_reviewer) do
191
+ Gitlab::Dangerfiles::Teammate.new(
192
+ "username" => "eng-prod-reviewer",
193
+ "name" => "EP engineer",
194
+ "role" => "Engineering Productivity",
195
+ "projects" => { "gitlab" => "reviewer tooling" },
196
+ "available" => true,
197
+ "tz_offset_hours" => 2.0
198
+ )
199
+ end
200
+
201
+ let(:ci_template_reviewer) do
202
+ Gitlab::Dangerfiles::Teammate.new(
203
+ "username" => "ci-template-maintainer",
204
+ "name" => "CI Template engineer",
205
+ "role" => '~"ci::templates"',
206
+ "projects" => { "gitlab" => "reviewer ci_template" },
207
+ "available" => true,
208
+ "tz_offset_hours" => 2.0
209
+ )
210
+ end
211
+
212
+ let(:analytics_instrumentation_reviewer) do
213
+ Gitlab::Dangerfiles::Teammate.new(
214
+ "username" => "analytics-instrumentation-reviewer",
215
+ "name" => "PI engineer",
216
+ "role" => "Backend Engineer, Analytics: Analytics Instrumentation",
217
+ "projects" => { "gitlab" => "reviewer analytics_instrumentation" },
218
+ "available" => true,
219
+ "tz_offset_hours" => 2.0
220
+ )
221
+ end
222
+
223
+ let(:import_and_integrate_backend_reviewer) do
224
+ Gitlab::Dangerfiles::Teammate.new(
225
+ "username" => "import-and-integrate-backend-reviewer",
226
+ "name" => "Import and Integrate BE engineer",
227
+ "role" => "Backend Engineer, Manage:Import and Integrate",
228
+ "projects" => { "gitlab" => "reviewer backend" },
229
+ "available" => backend_reviewer_available,
230
+ "tz_offset_hours" => 2.0
231
+ )
232
+ end
233
+
234
+ let(:import_and_integrate_frontend_reviewer) do
235
+ Gitlab::Dangerfiles::Teammate.new(
236
+ "username" => "import-and-integrate-frontend-reviewer",
237
+ "name" => "Import and Integrate FE engineer",
238
+ "role" => "Frontend Engineer, Manage:Import and Integrate",
239
+ "projects" => { "gitlab" => "reviewer frontend" },
240
+ "available" => true,
241
+ "tz_offset_hours" => 2.0
242
+ )
243
+ end
244
+
245
+ let(:workhorse_reviewer) do
246
+ Gitlab::Dangerfiles::Teammate.new(
247
+ "username" => "workhorse-reviewer",
248
+ "name" => "Workhorse reviewer",
249
+ "role" => "Backend engineer",
250
+ "projects" => { "gitlab-workhorse" => "reviewer" },
251
+ "available" => true,
252
+ "tz_offset_hours" => 2.0
253
+ )
254
+ end
255
+
256
+ let(:workhorse_maintainer) do
257
+ Gitlab::Dangerfiles::Teammate.new(
258
+ "username" => "workhorse-maintainer",
259
+ "name" => "Workhorse maintainer",
260
+ "role" => "Backend engineer",
261
+ "projects" => { "gitlab-workhorse" => "maintainer" },
262
+ "available" => true,
263
+ "tz_offset_hours" => 2.0
264
+ )
265
+ end
266
+
267
+ let(:teammates) do
268
+ [
269
+ backend_maintainer.to_h,
270
+ backend_reviewer.to_h,
271
+ frontend_maintainer.to_h,
272
+ frontend_reviewer.to_h,
273
+ ux_reviewer.to_h,
274
+ software_engineer_in_test.to_h,
275
+ tooling_reviewer.to_h,
276
+ ci_template_reviewer.to_h,
277
+ workhorse_reviewer.to_h,
278
+ workhorse_maintainer.to_h,
279
+ analytics_instrumentation_reviewer.to_h,
280
+ import_and_integrate_backend_reviewer.to_h,
281
+ import_and_integrate_frontend_reviewer.to_h,
282
+ software_engineer_in_import_integrate_fe.to_h,
283
+ software_engineer_in_import_integrate_be.to_h
284
+ ]
285
+ end
286
+
287
+ let(:teammate_json) { teammates.to_json }
288
+ let(:teammate_pedroms) { instance_double(Gitlab::Dangerfiles::Teammate, name: "Pedro") }
289
+ let(:company_members) { Gitlab::Dangerfiles::Teammate.fetch_company_members }
290
+
291
+ before do
292
+ WebMock
293
+ .stub_request(:get, Gitlab::Dangerfiles::Teammate::ROULETTE_DATA_URL)
294
+ .to_return(body: teammate_json)
295
+
296
+ # This avoid changing the internal state of the class
297
+ allow(Gitlab::Dangerfiles::Teammate).to receive(:warnings).and_return([])
298
+ allow(Gitlab::Dangerfiles::Teammate).to receive(:company_members).and_return(company_members)
299
+ end
300
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module Dangerfiles
5
+ Spin = Struct.new(:category, :reviewer, :maintainer, :optional_role) do
6
+ def no_reviewer?
7
+ reviewer.nil?
8
+ end
9
+
10
+ def no_maintainer?
11
+ maintainer.nil?
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,190 @@
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?(category)
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
+ # @param [String] category name
102
+ # @return [Boolean]
103
+ def import_and_integrate_reject_category?(category)
104
+ # Reject Import and Integrate categories if the MR author has reviewing abilities for the category.
105
+ team_author&.import_integrate_be?(project, category, labels) ||
106
+ team_author&.import_integrate_fe?(project, category, labels)
107
+ end
108
+
109
+ # MR includes QA changes, but also other changes, and author isn't an SET
110
+ def author_no_qa_capability?
111
+ !(team_author && team_author.capabilities(project).any? { |capability| capability.end_with?("qa") })
112
+ end
113
+
114
+ def spin_for_category(category)
115
+ reviewers, traintainers, maintainers =
116
+ %i[reviewer traintainer maintainer].map do |role|
117
+ spin_role_for_category(role, category)
118
+ end
119
+
120
+ weighted_reviewers = Weightage::Reviewers.new(reviewers, traintainers).execute
121
+ weighted_maintainers = Weightage::Maintainers.new(maintainers).execute
122
+
123
+ reviewer = spin_for_person(weighted_reviewers)
124
+ maintainer = spin_for_person(weighted_maintainers)
125
+
126
+ # allow projects with small number of reviewers to take from maintainers if possible
127
+ if reviewer.nil? && weighted_maintainers.uniq.size > 1
128
+ weighted_maintainers.delete(maintainer)
129
+ reviewer = spin_for_person(weighted_maintainers)
130
+ end
131
+
132
+ Spin.new(category, reviewer, maintainer, false)
133
+ end
134
+
135
+ def spin_role_for_category(role, category)
136
+ team.select do |member|
137
+ member.public_send(:"#{role}?", project, category, labels)
138
+ end
139
+ end
140
+
141
+ # Known issue: If someone is rejected due to OOO, and then becomes not OOO, the
142
+ # selection will change on next spin.
143
+ #
144
+ # @param [Array<Gitlab::Dangerfiles::Teammate>] people
145
+ #
146
+ # @return [Gitlab::Dangerfiles::Teammate]
147
+ def spin_for_person(people)
148
+ shuffled_people = people.shuffle(random: random)
149
+
150
+ shuffled_people.find { |person| valid_person?(person) }
151
+ end
152
+
153
+ # @param [Gitlab::Dangerfiles::Teammate] person
154
+ # @return [Boolean]
155
+ def valid_person?(person)
156
+ person.username != author && person.available
157
+ end
158
+
159
+ # It can be possible that we don't have a valid reviewer for approval.
160
+ # In this case, we sample again without considering:
161
+ #
162
+ # * If they're available
163
+ # * If they're an actual reviewer from roulette data
164
+ #
165
+ # We do this because we strictly require an approval from the approvers.
166
+ #
167
+ # @param [Hash] rule of approval
168
+ #
169
+ # @return [Gitlab::Dangerfiles::Teammate]
170
+ def spin_for_approver_fallback(rule)
171
+ fallback_approvers = rule["eligible_approvers"].map do |approver|
172
+ Teammate.find_member(approver["username"]) || Teammate.new(approver)
173
+ end
174
+
175
+ # Intentionally not using `spin_for_person` to skip `valid_person?`.
176
+ # This should strictly return someone so we don't filter anything,
177
+ # and it's a fallback mechanism which should not happen often that
178
+ # deserves a complex algorithm.
179
+ fallback_approvers.sample(random: random)
180
+ end
181
+
182
+ # @return [Array<Gitlab::Dangerfiles::Teammate>]
183
+ def team
184
+ @team ||= Teammate.company_members.select do |member|
185
+ member.in_project?(project)
186
+ end
187
+ end
188
+ end
189
+ end
190
+ end
@@ -1,10 +1,82 @@
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
81
  :only_maintainer_reviews
10
82
 
@@ -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["username"])
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
@@ -128,7 +214,7 @@ module Gitlab
128
214
  end
129
215
 
130
216
  def has_capability?(project, category, kind, labels)
131
- Category.for(category, project: project, kind: kind, labels: labels).has_capability?(self)
217
+ Capability.for(category, project: project, kind: kind, labels: labels).has_capability?(self)
132
218
  end
133
219
 
134
220
  def pluralize(count, singular, plural)
@@ -9,7 +9,7 @@ module Gitlab
9
9
  performance: %w[type::bug bug::performance],
10
10
  added: %w[type::feature feature::addition],
11
11
  deprecated: %w[type::maintenance maintenance::removal],
12
- removed: %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 = "4.6.0"
3
+ VERSION = "4.8.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: 4.6.0
4
+ version: 4.8.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-06 00:00:00.000000000 Z
11
+ date: 2024-06-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -213,6 +213,7 @@ files:
213
213
  - CONTRIBUTING.md
214
214
  - Dangerfile
215
215
  - Gemfile
216
+ - Gemfile.lock
216
217
  - Guardfile
217
218
  - LICENSE.txt
218
219
  - README.md
@@ -238,14 +239,17 @@ files:
238
239
  - lib/gitlab-dangerfiles.rb
239
240
  - lib/gitlab/Dangerfile
240
241
  - lib/gitlab/dangerfiles.rb
242
+ - lib/gitlab/dangerfiles/approval.rb
241
243
  - lib/gitlab/dangerfiles/base_linter.rb
242
- - lib/gitlab/dangerfiles/category.rb
244
+ - lib/gitlab/dangerfiles/capability.rb
243
245
  - lib/gitlab/dangerfiles/changes.rb
244
246
  - lib/gitlab/dangerfiles/commit_linter.rb
245
247
  - lib/gitlab/dangerfiles/config.rb
246
248
  - lib/gitlab/dangerfiles/emoji_checker.rb
247
249
  - lib/gitlab/dangerfiles/merge_request_linter.rb
248
250
  - lib/gitlab/dangerfiles/spec_helper.rb
251
+ - lib/gitlab/dangerfiles/spin.rb
252
+ - lib/gitlab/dangerfiles/spinner.rb
249
253
  - lib/gitlab/dangerfiles/task_loader.rb
250
254
  - lib/gitlab/dangerfiles/tasks/main.rake
251
255
  - lib/gitlab/dangerfiles/teammate.rb
@@ -278,7 +282,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
278
282
  - !ruby/object:Gem::Version
279
283
  version: '0'
280
284
  requirements: []
281
- rubygems_version: 3.3.26
285
+ rubygems_version: 3.3.27
282
286
  signing_key:
283
287
  specification_version: 4
284
288
  summary: This gem provides common Dangerfile and plugins for GitLab projects.