danger-packwerk 0.7.1 → 0.9.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.
@@ -0,0 +1,60 @@
1
+ # typed: strict
2
+
3
+ require 'code_ownership'
4
+
5
+ module DangerPackwerk
6
+ module Private
7
+ class OwnershipInformation < T::Struct
8
+ extend T::Sig
9
+
10
+ const :owning_team, T.nilable(CodeTeams::Team)
11
+ const :github_team, T.nilable(String)
12
+ const :slack_channel, T.nilable(String)
13
+ const :org_name, T.nilable(String)
14
+
15
+ sig { params(package: ParsePackwerk::Package, org_name: String).returns(OwnershipInformation) }
16
+ def self.for_package(package, org_name)
17
+ team = CodeOwnership.for_package(package)
18
+
19
+ if team.nil?
20
+ OwnershipInformation.new
21
+ else
22
+ OwnershipInformation.new(
23
+ owning_team: team,
24
+ github_team: team.raw_hash.fetch('github', {}).fetch('team', nil),
25
+ slack_channel: team.raw_hash.fetch('slack', {}).fetch('room_for_humans', nil),
26
+ org_name: org_name
27
+ )
28
+ end
29
+ end
30
+
31
+ sig { returns(String) }
32
+ def ownership_copy
33
+ github_team_flow_sensitive = github_team
34
+ slack_channel_flow_sensitive = slack_channel
35
+
36
+ if owning_team && github_team_flow_sensitive && slack_channel_flow_sensitive
37
+ team_slack_link = markdown_link_to_slack_room
38
+ "- Owned by #{markdown_link_to_github_members_no_tag} (Slack: #{team_slack_link})"
39
+ else
40
+ '- This pack is unowned.'
41
+ end
42
+ end
43
+
44
+ sig { returns(String) }
45
+ def markdown_link_to_slack_room
46
+ "[<ins>#{slack_channel}</ins>](https://slack.com/app_redirect?channel=#{T.must(slack_channel).delete('#')})"
47
+ end
48
+
49
+ #
50
+ # Note this will NOT tag the team on Github, but it will link
51
+ # to the mentioned team's members page. If you want to tag and
52
+ # link the team, simply use the string and Github will handle it.
53
+ #
54
+ sig { returns(String) }
55
+ def markdown_link_to_github_members_no_tag
56
+ "[<ins>#{github_team}</ins>](https://github.com/orgs/#{org_name}/teams/#{T.must(github_team).gsub("@#{org_name}/", '')}/members)"
57
+ end
58
+ end
59
+ end
60
+ end
@@ -3,7 +3,7 @@
3
3
  module DangerPackwerk
4
4
  module Private
5
5
  #
6
- # The `Violation` and `DeprecatedReferences` classes come from Gusto's private `ParsePackwerk` gem.
6
+ # The `Violation` and `PackageTodo` classes come from Gusto's private `ParsePackwerk` gem.
7
7
  # Until we decide to open source that gem, we inline these as a private implementation detail of `DangerPackwerk` for now.
8
8
  #
9
9
  class Violation < T::Struct
@@ -25,22 +25,22 @@ module DangerPackwerk
25
25
  end
26
26
  end
27
27
 
28
- class DeprecatedReferences < T::Struct
28
+ class PackageTodo < T::Struct
29
29
  extend T::Sig
30
30
 
31
31
  const :pathname, Pathname
32
32
  const :violations, T::Array[Violation]
33
33
 
34
- sig { params(pathname: Pathname).returns(DeprecatedReferences) }
34
+ sig { params(pathname: Pathname).returns(PackageTodo) }
35
35
  def self.from(pathname)
36
36
  if pathname.exist?
37
- deprecated_references_loaded_yml = YAML.load_file(pathname)
37
+ package_todo_loaded_yml = YAML.load_file(pathname)
38
38
 
39
39
  all_violations = []
40
- deprecated_references_loaded_yml&.each_key do |to_package_name|
41
- deprecated_references_per_package = deprecated_references_loaded_yml[to_package_name]
42
- deprecated_references_per_package.each_key do |class_name|
43
- symbol_usage = deprecated_references_per_package[class_name]
40
+ package_todo_loaded_yml&.each_key do |to_package_name|
41
+ package_todo_per_package = package_todo_loaded_yml[to_package_name]
42
+ package_todo_per_package.each_key do |class_name|
43
+ symbol_usage = package_todo_per_package[class_name]
44
44
  files = symbol_usage['files']
45
45
  violations = symbol_usage['violations']
46
46
  all_violations << Violation.new(type: 'dependency', to_package_name: to_package_name, class_name: class_name, files: files) if violations.include? 'dependency'
@@ -1,7 +1,7 @@
1
1
  # typed: strict
2
2
 
3
- require 'danger-packwerk/private/deprecated_references'
4
- require 'danger-packwerk/private/default_offenses_formatter'
3
+ require 'danger-packwerk/private/package_todo'
4
+ require 'danger-packwerk/private/ownership_information'
5
5
  require 'constant_resolver'
6
6
 
7
7
  module DangerPackwerk
@@ -0,0 +1,67 @@
1
+ # typed: strict
2
+
3
+ module DangerPackwerk
4
+ module Update
5
+ class DefaultFormatter
6
+ extend T::Sig
7
+ include OffensesFormatter
8
+
9
+ sig do
10
+ params(
11
+ custom_help_message: T.nilable(String)
12
+ ).void
13
+ end
14
+ def initialize(custom_help_message: nil)
15
+ @custom_help_message = custom_help_message
16
+ end
17
+
18
+ sig { override.params(offenses: T::Array[BasicReferenceOffense], repo_link: String, org_name: String).returns(String) }
19
+ def format_offenses(offenses, repo_link, org_name)
20
+ violation = T.must(offenses.first)
21
+ referencing_file_pack = ParsePackwerk.package_from_path(violation.file)
22
+ # We remove leading double colons as they feel like an implementation detail of packwerk.
23
+ constant_name = violation.class_name.delete_prefix('::')
24
+ constant_source_package_name = violation.to_package_name
25
+
26
+ constant_source_package = T.must(ParsePackwerk.find(constant_source_package_name))
27
+ constant_source_package_owner = Private::OwnershipInformation.for_package(constant_source_package, org_name)
28
+
29
+ package_referring_to_constant_owner = Private::OwnershipInformation.for_package(referencing_file_pack, org_name)
30
+
31
+ disclaimer = 'We noticed you ran `bin/packwerk update-deprecations`. Check out [the docs](https://github.com/Shopify/packwerk/blob/main/RESOLVING_VIOLATIONS.md) to see other ways to resolve violations.'
32
+ pluralized_violation = offenses.count > 1 ? 'these violations' : 'this violation'
33
+ request_to_add_context = "- Could you add some context as a reply here about why we needed to add #{pluralized_violation}?\n"
34
+
35
+ dependency_violation_message = "- cc #{package_referring_to_constant_owner.github_team} (#{package_referring_to_constant_owner.markdown_link_to_slack_room}) for the dependency violation.\n" if package_referring_to_constant_owner.owning_team
36
+
37
+ privacy_violation_message = "- cc #{constant_source_package_owner.github_team} (#{constant_source_package_owner.markdown_link_to_slack_room}) for the privacy violation.\n" if constant_source_package_owner.owning_team
38
+
39
+ if offenses.any?(&:dependency?) && offenses.any?(&:privacy?)
40
+ <<~MESSAGE.chomp
41
+ Hi again! It looks like `#{constant_name}` is private API of `#{constant_source_package_name}`, which is also not in `#{referencing_file_pack.name}`'s list of dependencies.
42
+ #{disclaimer}
43
+
44
+ #{request_to_add_context}#{dependency_violation_message}#{privacy_violation_message}
45
+ #{@custom_help_message}
46
+ MESSAGE
47
+ elsif offenses.any?(&:dependency?)
48
+ <<~MESSAGE.chomp
49
+ Hi again! It looks like `#{constant_name}` belongs to `#{constant_source_package_name}`, which is not in `#{referencing_file_pack.name}`'s list of dependencies.
50
+ #{disclaimer}
51
+
52
+ #{request_to_add_context}#{dependency_violation_message}
53
+ #{@custom_help_message}
54
+ MESSAGE
55
+ else # violations.any?(&:privacy?)
56
+ <<~MESSAGE.chomp
57
+ Hi again! It looks like `#{constant_name}` is private API of `#{constant_source_package_name}`.
58
+ #{disclaimer}
59
+
60
+ #{request_to_add_context}#{privacy_violation_message}
61
+ #{@custom_help_message}
62
+ MESSAGE
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,23 @@
1
+ # typed: strict
2
+
3
+ require 'code_ownership'
4
+
5
+ module DangerPackwerk
6
+ module Update
7
+ module OffensesFormatter
8
+ extend T::Sig
9
+ extend T::Helpers
10
+
11
+ interface!
12
+
13
+ sig do
14
+ abstract.params(
15
+ offenses: T::Array[BasicReferenceOffense],
16
+ repo_link: String,
17
+ org_name: String
18
+ ).returns(String)
19
+ end
20
+ def format_offenses(offenses, repo_link, org_name); end
21
+ end
22
+ end
23
+ end
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module DangerPackwerk
5
- VERSION = '0.7.1'
5
+ VERSION = '0.9.0'
6
6
  end
@@ -5,8 +5,14 @@
5
5
  require 'sorbet-runtime'
6
6
 
7
7
  module DangerPackwerk
8
- DEPRECATED_REFERENCES_PATTERN = T.let(/.*?deprecated_references\.yml\z/.freeze, Regexp)
8
+ PACKAGE_TODO_PATTERN = T.let(/.*?package_todo\.yml\z/.freeze, Regexp)
9
+ DEPENDENCY_VIOLATION_TYPE = 'dependency'
10
+ PRIVACY_VIOLATION_TYPE = 'privacy'
9
11
 
10
12
  require 'danger-packwerk/danger_packwerk'
11
- require 'danger-packwerk/danger_deprecated_references_yml_changes'
13
+ require 'danger-packwerk/danger_package_todo_yml_changes'
14
+ require 'danger-packwerk/check/offenses_formatter'
15
+ require 'danger-packwerk/check/default_formatter'
16
+ require 'danger-packwerk/update/offenses_formatter'
17
+ require 'danger-packwerk/update/default_formatter'
12
18
  end
@@ -0,0 +1,336 @@
1
+ # typed: true
2
+
3
+ # DO NOT EDIT MANUALLY
4
+ # This is an autogenerated file for types exported from the `code_ownership` gem.
5
+ # Please instead update this file by running `bin/tapioca gem code_ownership`.
6
+
7
+ module CodeOwnership
8
+ extend ::CodeOwnership
9
+
10
+ requires_ancestor { Kernel }
11
+
12
+ sig do
13
+ params(
14
+ backtrace: T.nilable(T::Array[::String]),
15
+ excluded_teams: T::Array[::CodeTeams::Team]
16
+ ).returns(T.nilable(::CodeTeams::Team))
17
+ end
18
+ def for_backtrace(backtrace, excluded_teams: T.unsafe(nil)); end
19
+
20
+ sig { params(klass: T.nilable(T.any(::Class, ::Module))).returns(T.nilable(::CodeTeams::Team)) }
21
+ def for_class(klass); end
22
+
23
+ sig { params(file: ::String).returns(T.nilable(::CodeTeams::Team)) }
24
+ def for_file(file); end
25
+
26
+ sig { params(package: ::ParsePackwerk::Package).returns(T.nilable(::CodeTeams::Team)) }
27
+ def for_package(package); end
28
+
29
+ sig { params(team: T.any(::CodeTeams::Team, ::String)).returns(::String) }
30
+ def for_team(team); end
31
+
32
+ sig { params(files: T::Array[::String], autocorrect: T::Boolean, stage_changes: T::Boolean).void }
33
+ def validate!(files: T.unsafe(nil), autocorrect: T.unsafe(nil), stage_changes: T.unsafe(nil)); end
34
+
35
+ class << self
36
+ sig { void }
37
+ def bust_caches!; end
38
+
39
+ sig { params(filename: ::String).void }
40
+ def remove_file_annotation!(filename); end
41
+ end
42
+ end
43
+
44
+ class CodeOwnership::Cli
45
+ class << self
46
+ def for_file(argv); end
47
+ def for_team(argv); end
48
+ def run!(argv); end
49
+
50
+ private
51
+
52
+ def validate!(argv); end
53
+ end
54
+ end
55
+
56
+ class CodeOwnership::InvalidCodeOwnershipConfigurationError < ::StandardError; end
57
+
58
+ module CodeOwnership::Private
59
+ class << self
60
+ sig { void }
61
+ def bust_caches!; end
62
+
63
+ sig { returns(::CodeOwnership::Private::Configuration) }
64
+ def configuration; end
65
+
66
+ sig { returns(::CodeOwnership::Private::OwnershipMappers::FileAnnotations) }
67
+ def file_annotations_mapper; end
68
+
69
+ sig { params(files: T::Array[::String]).returns(T::Hash[::String, T::Array[::String]]) }
70
+ def files_by_mapper(files); end
71
+
72
+ sig { params(team_name: ::String, location_of_reference: ::String).returns(::CodeTeams::Team) }
73
+ def find_team!(team_name, location_of_reference); end
74
+
75
+ sig { returns(T::Array[::CodeOwnership::Private::OwnershipMappers::Interface]) }
76
+ def mappers; end
77
+
78
+ sig { params(klass: T.nilable(T.any(::Class, ::Module))).returns(T.nilable(::String)) }
79
+ def path_from_klass(klass); end
80
+
81
+ sig { returns(T::Array[::String]) }
82
+ def tracked_files; end
83
+
84
+ sig { params(files: T::Array[::String], autocorrect: T::Boolean, stage_changes: T::Boolean).void }
85
+ def validate!(files:, autocorrect: T.unsafe(nil), stage_changes: T.unsafe(nil)); end
86
+ end
87
+ end
88
+
89
+ class CodeOwnership::Private::Configuration < ::T::Struct
90
+ const :js_package_paths, T::Array[::String]
91
+ const :owned_globs, T::Array[::String]
92
+ const :skip_codeowners_validation, T::Boolean
93
+ const :unowned_globs, T::Array[::String]
94
+
95
+ class << self
96
+ sig { returns(::CodeOwnership::Private::Configuration) }
97
+ def fetch; end
98
+
99
+ def inherited(s); end
100
+
101
+ sig { params(config_hash: T::Hash[T.untyped, T.untyped]).returns(T::Array[::String]) }
102
+ def js_package_paths(config_hash); end
103
+ end
104
+ end
105
+
106
+ CodeOwnership::Private::Configuration::DEFAULT_JS_PACKAGE_PATHS = T.let(T.unsafe(nil), Array)
107
+ module CodeOwnership::Private::OwnershipMappers; end
108
+
109
+ class CodeOwnership::Private::OwnershipMappers::FileAnnotations
110
+ include ::CodeOwnership::Private::OwnershipMappers::Interface
111
+
112
+ sig { override.void }
113
+ def bust_caches!; end
114
+
115
+ sig { override.returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) }
116
+ def codeowners_lines_to_owners; end
117
+
118
+ sig { override.returns(::String) }
119
+ def description; end
120
+
121
+ sig { params(filename: ::String).returns(T.nilable(::CodeTeams::Team)) }
122
+ def file_annotation_based_owner(filename); end
123
+
124
+ sig { override.params(file: ::String).returns(T.nilable(::CodeTeams::Team)) }
125
+ def map_file_to_owner(file); end
126
+
127
+ sig { override.params(files: T::Array[::String]).returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) }
128
+ def map_files_to_owners(files); end
129
+
130
+ sig { params(filename: ::String).void }
131
+ def remove_file_annotation!(filename); end
132
+ end
133
+
134
+ CodeOwnership::Private::OwnershipMappers::FileAnnotations::TEAM_PATTERN = T.let(T.unsafe(nil), Regexp)
135
+
136
+ module CodeOwnership::Private::OwnershipMappers::Interface
137
+ interface!
138
+
139
+ sig { abstract.void }
140
+ def bust_caches!; end
141
+
142
+ sig { abstract.returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) }
143
+ def codeowners_lines_to_owners; end
144
+
145
+ sig { abstract.returns(::String) }
146
+ def description; end
147
+
148
+ sig { abstract.params(file: ::String).returns(T.nilable(::CodeTeams::Team)) }
149
+ def map_file_to_owner(file); end
150
+
151
+ sig { abstract.params(files: T::Array[::String]).returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) }
152
+ def map_files_to_owners(files); end
153
+ end
154
+
155
+ class CodeOwnership::Private::OwnershipMappers::JsPackageOwnership
156
+ include ::CodeOwnership::Private::OwnershipMappers::Interface
157
+
158
+ sig { override.void }
159
+ def bust_caches!; end
160
+
161
+ sig { override.returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) }
162
+ def codeowners_lines_to_owners; end
163
+
164
+ sig { override.returns(::String) }
165
+ def description; end
166
+
167
+ sig { override.params(file: ::String).returns(T.nilable(::CodeTeams::Team)) }
168
+ def map_file_to_owner(file); end
169
+
170
+ sig { override.params(files: T::Array[::String]).returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) }
171
+ def map_files_to_owners(files); end
172
+
173
+ sig { params(package: ::CodeOwnership::Private::ParseJsPackages::Package).returns(T.nilable(::CodeTeams::Team)) }
174
+ def owner_for_package(package); end
175
+
176
+ private
177
+
178
+ sig { params(file: ::String).returns(T.nilable(::CodeOwnership::Private::ParseJsPackages::Package)) }
179
+ def map_file_to_relevant_package(file); end
180
+ end
181
+
182
+ class CodeOwnership::Private::OwnershipMappers::PackageOwnership
183
+ include ::CodeOwnership::Private::OwnershipMappers::Interface
184
+
185
+ sig { override.void }
186
+ def bust_caches!; end
187
+
188
+ sig { override.returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) }
189
+ def codeowners_lines_to_owners; end
190
+
191
+ sig { override.returns(::String) }
192
+ def description; end
193
+
194
+ sig { override.params(file: ::String).returns(T.nilable(::CodeTeams::Team)) }
195
+ def map_file_to_owner(file); end
196
+
197
+ sig { override.params(files: T::Array[::String]).returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) }
198
+ def map_files_to_owners(files); end
199
+
200
+ sig { params(package: ::ParsePackwerk::Package).returns(T.nilable(::CodeTeams::Team)) }
201
+ def owner_for_package(package); end
202
+ end
203
+
204
+ class CodeOwnership::Private::OwnershipMappers::TeamGlobs
205
+ include ::CodeOwnership::Private::OwnershipMappers::Interface
206
+
207
+ sig { override.void }
208
+ def bust_caches!; end
209
+
210
+ sig { override.returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) }
211
+ def codeowners_lines_to_owners; end
212
+
213
+ sig { override.returns(::String) }
214
+ def description; end
215
+
216
+ sig { override.params(file: ::String).returns(T.nilable(::CodeTeams::Team)) }
217
+ def map_file_to_owner(file); end
218
+
219
+ sig { override.params(files: T::Array[::String]).returns(T::Hash[::String, T.nilable(::CodeTeams::Team)]) }
220
+ def map_files_to_owners(files); end
221
+ end
222
+
223
+ module CodeOwnership::Private::ParseJsPackages
224
+ class << self
225
+ sig { returns(T::Array[::CodeOwnership::Private::ParseJsPackages::Package]) }
226
+ def all; end
227
+ end
228
+ end
229
+
230
+ CodeOwnership::Private::ParseJsPackages::METADATA = T.let(T.unsafe(nil), String)
231
+ CodeOwnership::Private::ParseJsPackages::PACKAGE_JSON_NAME = T.let(T.unsafe(nil), String)
232
+
233
+ class CodeOwnership::Private::ParseJsPackages::Package < ::T::Struct
234
+ const :metadata, T::Hash[::String, T.untyped]
235
+ const :name, ::String
236
+
237
+ sig { returns(::Pathname) }
238
+ def directory; end
239
+
240
+ class << self
241
+ sig { params(pathname: ::Pathname).returns(::CodeOwnership::Private::ParseJsPackages::Package) }
242
+ def from(pathname); end
243
+
244
+ def inherited(s); end
245
+ end
246
+ end
247
+
248
+ CodeOwnership::Private::ParseJsPackages::ROOT_PACKAGE_NAME = T.let(T.unsafe(nil), String)
249
+ module CodeOwnership::Private::TeamPlugins; end
250
+
251
+ class CodeOwnership::Private::TeamPlugins::Github < ::CodeTeams::Plugin
252
+ sig { returns(::CodeOwnership::Private::TeamPlugins::Github::GithubStruct) }
253
+ def github; end
254
+ end
255
+
256
+ class CodeOwnership::Private::TeamPlugins::Github::GithubStruct < ::Struct
257
+ def do_not_add_to_codeowners_file; end
258
+ def do_not_add_to_codeowners_file=(_); end
259
+ def team; end
260
+ def team=(_); end
261
+
262
+ class << self
263
+ def [](*_arg0); end
264
+ def inspect; end
265
+ def members; end
266
+ def new(*_arg0); end
267
+ end
268
+ end
269
+
270
+ class CodeOwnership::Private::TeamPlugins::Ownership < ::CodeTeams::Plugin
271
+ sig { returns(T::Array[::String]) }
272
+ def owned_globs; end
273
+ end
274
+
275
+ module CodeOwnership::Private::Validations; end
276
+
277
+ class CodeOwnership::Private::Validations::FilesHaveOwners
278
+ include ::CodeOwnership::Private::Validations::Interface
279
+
280
+ sig do
281
+ override
282
+ .params(
283
+ files: T::Array[::String],
284
+ autocorrect: T::Boolean,
285
+ stage_changes: T::Boolean
286
+ ).returns(T::Array[::String])
287
+ end
288
+ def validation_errors(files:, autocorrect: T.unsafe(nil), stage_changes: T.unsafe(nil)); end
289
+ end
290
+
291
+ class CodeOwnership::Private::Validations::FilesHaveUniqueOwners
292
+ include ::CodeOwnership::Private::Validations::Interface
293
+
294
+ sig do
295
+ override
296
+ .params(
297
+ files: T::Array[::String],
298
+ autocorrect: T::Boolean,
299
+ stage_changes: T::Boolean
300
+ ).returns(T::Array[::String])
301
+ end
302
+ def validation_errors(files:, autocorrect: T.unsafe(nil), stage_changes: T.unsafe(nil)); end
303
+ end
304
+
305
+ class CodeOwnership::Private::Validations::GithubCodeownersUpToDate
306
+ include ::CodeOwnership::Private::Validations::Interface
307
+
308
+ sig do
309
+ override
310
+ .params(
311
+ files: T::Array[::String],
312
+ autocorrect: T::Boolean,
313
+ stage_changes: T::Boolean
314
+ ).returns(T::Array[::String])
315
+ end
316
+ def validation_errors(files:, autocorrect: T.unsafe(nil), stage_changes: T.unsafe(nil)); end
317
+
318
+ private
319
+
320
+ sig { returns(T::Array[::String]) }
321
+ def codeowners_file_lines; end
322
+ end
323
+
324
+ module CodeOwnership::Private::Validations::Interface
325
+ interface!
326
+
327
+ sig do
328
+ abstract
329
+ .params(
330
+ files: T::Array[::String],
331
+ autocorrect: T::Boolean,
332
+ stage_changes: T::Boolean
333
+ ).returns(T::Array[::String])
334
+ end
335
+ def validation_errors(files:, autocorrect: T.unsafe(nil), stage_changes: T.unsafe(nil)); end
336
+ end
@@ -0,0 +1,120 @@
1
+ # typed: true
2
+
3
+ # DO NOT EDIT MANUALLY
4
+ # This is an autogenerated file for types exported from the `code_teams` gem.
5
+ # Please instead update this file by running `bin/tapioca gem code_teams`.
6
+
7
+ module CodeTeams
8
+ class << self
9
+ sig { returns(T::Array[::CodeTeams::Team]) }
10
+ def all; end
11
+
12
+ sig { void }
13
+ def bust_caches!; end
14
+
15
+ sig { params(name: ::String).returns(T.nilable(::CodeTeams::Team)) }
16
+ def find(name); end
17
+
18
+ sig { params(dir: ::String).returns(T::Array[::CodeTeams::Team]) }
19
+ def for_directory(dir); end
20
+
21
+ sig { params(string: ::String).returns(::String) }
22
+ def tag_value_for(string); end
23
+
24
+ sig { params(teams: T::Array[::CodeTeams::Team]).returns(T::Array[::String]) }
25
+ def validation_errors(teams); end
26
+ end
27
+ end
28
+
29
+ class CodeTeams::IncorrectPublicApiUsageError < ::StandardError; end
30
+
31
+ class CodeTeams::Plugin
32
+ abstract!
33
+
34
+ sig { params(team: ::CodeTeams::Team).void }
35
+ def initialize(team); end
36
+
37
+ class << self
38
+ sig { returns(T::Array[T.class_of(CodeTeams::Plugin)]) }
39
+ def all_plugins; end
40
+
41
+ sig { params(team: ::CodeTeams::Team).returns(T.attached_class) }
42
+ def for(team); end
43
+
44
+ sig { params(base: T.untyped).void }
45
+ def inherited(base); end
46
+
47
+ sig { params(team: ::CodeTeams::Team, key: ::String).returns(::String) }
48
+ def missing_key_error_message(team, key); end
49
+
50
+ sig { params(teams: T::Array[::CodeTeams::Team]).returns(T::Array[::String]) }
51
+ def validation_errors(teams); end
52
+
53
+ private
54
+
55
+ sig { params(team: ::CodeTeams::Team).returns(T.attached_class) }
56
+ def register_team(team); end
57
+
58
+ sig { returns(T::Hash[T.nilable(::String), T::Hash[::Class, ::CodeTeams::Plugin]]) }
59
+ def registry; end
60
+ end
61
+ end
62
+
63
+ module CodeTeams::Plugins; end
64
+
65
+ class CodeTeams::Plugins::Identity < ::CodeTeams::Plugin
66
+ sig { returns(::CodeTeams::Plugins::Identity::IdentityStruct) }
67
+ def identity; end
68
+
69
+ class << self
70
+ sig { override.params(teams: T::Array[::CodeTeams::Team]).returns(T::Array[::String]) }
71
+ def validation_errors(teams); end
72
+ end
73
+ end
74
+
75
+ class CodeTeams::Plugins::Identity::IdentityStruct < ::Struct
76
+ def name; end
77
+ def name=(_); end
78
+
79
+ class << self
80
+ def [](*_arg0); end
81
+ def inspect; end
82
+ def members; end
83
+ def new(*_arg0); end
84
+ end
85
+ end
86
+
87
+ class CodeTeams::Team
88
+ sig { params(config_yml: T.nilable(::String), raw_hash: T::Hash[T.untyped, T.untyped]).void }
89
+ def initialize(config_yml:, raw_hash:); end
90
+
91
+ sig { params(other: ::Object).returns(T::Boolean) }
92
+ def ==(other); end
93
+
94
+ sig { returns(T.nilable(::String)) }
95
+ def config_yml; end
96
+
97
+ def eql?(*args, &blk); end
98
+
99
+ sig { returns(::Integer) }
100
+ def hash; end
101
+
102
+ sig { returns(::String) }
103
+ def name; end
104
+
105
+ sig { returns(T::Hash[T.untyped, T.untyped]) }
106
+ def raw_hash; end
107
+
108
+ sig { returns(::String) }
109
+ def to_tag; end
110
+
111
+ class << self
112
+ sig { params(raw_hash: T::Hash[T.untyped, T.untyped]).returns(::CodeTeams::Team) }
113
+ def from_hash(raw_hash); end
114
+
115
+ sig { params(config_yml: ::String).returns(::CodeTeams::Team) }
116
+ def from_yml(config_yml); end
117
+ end
118
+ end
119
+
120
+ CodeTeams::UNKNOWN_TEAM_STRING = T.let(T.unsafe(nil), String)