modularization_statistics 1.41.0 → 1.43.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: 98507b7d02a58d6a68c9ba40d9962abf6369dc68959d7a95f6d3a49384f902f4
4
- data.tar.gz: 5d12d05d262833e8b1534a6b38f8162b2a3c4bd57d584ceb260a5c8d6c99ab0a
3
+ metadata.gz: f62a7a832093f586bea43e63af693a848f52cf0e4528348746424d4a80c10d12
4
+ data.tar.gz: a7d15eff1dc8014fd5552372081d6a171dff2625dade956b6ef0554e45631c3f
5
5
  SHA512:
6
- metadata.gz: 41ddf6056104fcc66a39f44bf50e4783cd69fe70aa88414bd5459c365bd0285439d3bfe8651b4ab3059f849759b8e37afe5502fdf907654798640a6c9cade2ff
7
- data.tar.gz: f72b2b1c78f6bddbeac30bfd074b3a8b2bcc0b18e20ad9fc0b311e32ee4514aabc95683d12642b0287cbea41457e46f7468fa849f6b198ff06703f69f768534a
6
+ metadata.gz: 2b510bef418709597c3c215d24752de7db71f411765517c350cfc4e8ebf5e396ecb7399ab340defbdc8bb6538e38cdb713f2d209407c5ced0ed4ff0a17f9b04a
7
+ data.tar.gz: 3dc87181542fcb8bcb37561d9aa12df9ebe152f397da7c5f01c3b5b579c048102e9640929d1d6e6d3d806d6bbf5386524b411d2679324bf483e335d8b8065730
data/README.md CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  This gem is used to report opinionated statistics about modularization to DataDog and other observability systems.
4
4
 
5
+ # Configuring Ownership
6
+ The gem reports metrics per-team, where each team is configured based on metadata included in Packwerk package.yml files.
7
+
8
+ Define your teams as described in the [Code Team - Package Based Ownership](https://github.com/rubyatscale/code_ownership#package-based-ownership) documentation.
9
+
5
10
  # Usage
6
11
  The main method to this gem is `ModularizationStatistics#report_to_datadog!`. Refer to the Sorbet signature for this method for the exact types to be passed in.
7
12
 
@@ -19,8 +24,8 @@ ModularizationStatistics.report_to_datadog!(
19
24
  # Example: Time.now
20
25
  #
21
26
  report_time: report_time
22
- #
23
- # This is used to determine what files to look at for building statistics about what types of files are packaged, componentized, or unpackaged.
27
+ #
28
+ # This is used to determine what files to look at for building statistics about what types of files are packaged, componentized, or unpackaged.
24
29
  # This is an array of `Pathname`. `Pathname` can be relative or absolute paths.
25
30
  #
26
31
  # Example: source_code_pathnames = Pathname.glob('./**/**.rb')
@@ -33,7 +38,7 @@ ModularizationStatistics.report_to_datadog!(
33
38
  # Example: [Pathname.new("./gems")]
34
39
  #
35
40
  componentized_source_code_locations: componentized_source_code_locations,
36
- #
41
+ #
37
42
  # A file is determined to be packaged if it exists in any of these directories.
38
43
  # This is an array of `Pathname`. `Pathname` can be relative or absolute paths.
39
44
  #
@@ -5,8 +5,8 @@ require 'dogapi'
5
5
  require 'modularization_statistics/private/metrics'
6
6
  require 'modularization_statistics/private/metrics/files'
7
7
  require 'modularization_statistics/private/metrics/public_usage'
8
- require 'modularization_statistics/private/metrics/protection_usage'
9
- require 'modularization_statistics/private/metrics/rubocop_protections_exclusions'
8
+ require 'modularization_statistics/private/metrics/packwerk_checker_usage'
9
+ require 'modularization_statistics/private/metrics/rubocop_usage'
10
10
  require 'modularization_statistics/private/metrics/packages'
11
11
  require 'modularization_statistics/private/metrics/packages_by_team'
12
12
  require 'modularization_statistics/private/metrics/nested_packs'
@@ -32,8 +32,8 @@ module ModularizationStatistics
32
32
  all_metrics += Metrics::PublicUsage.get_public_usage_metrics('all_packages', packages, package_tags)
33
33
  all_metrics << GaugeMetric.for('all_packages.has_readme.count', packages.count { |package| Metrics.has_readme?(package) }, package_tags)
34
34
 
35
- all_metrics += Metrics::ProtectionUsage.get_protections_metrics('all_packages', packages, package_tags)
36
- all_metrics += Metrics::RubocopProtectionsExclusions.get_rubocop_exclusions('all_packages', packages, package_tags)
35
+ all_metrics += Metrics::PackwerkCheckerUsage.get_checker_metrics('all_packages', packages, package_tags)
36
+ all_metrics += Metrics::RubocopUsage.get_metrics('all_packages', packages, package_tags)
37
37
  all_metrics << GaugeMetric.for('all_packages.package_based_file_ownership.count', packages.count { |package| !package.metadata['owner'].nil? }, package_tags)
38
38
 
39
39
  inbound_violations_by_package = packages.flat_map(&:violations).group_by(&:to_package_name)
@@ -23,7 +23,7 @@ module ModularizationStatistics
23
23
 
24
24
  team_tags = Metrics.tags_for_team(team_name) + [app_level_tag]
25
25
  all_metrics << GaugeMetric.for('by_team.all_packages.count', packages_by_team.count, team_tags)
26
- all_metrics += Metrics::ProtectionUsage.get_protections_metrics('by_team', packages_by_team, team_tags)
26
+ all_metrics += Metrics::PackwerkCheckerUsage.get_checker_metrics('by_team', packages_by_team, team_tags)
27
27
  all_metrics += Metrics::PublicUsage.get_public_usage_metrics('by_team', packages_by_team, team_tags)
28
28
 
29
29
  all_metrics << GaugeMetric.for('by_team.notify_on_package_yml_changes.count', packages_by_team.count { |p| p.metadata['notify_on_package_yml_changes'] }, team_tags)
@@ -0,0 +1,57 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require 'rubocop-packs'
5
+
6
+ module ModularizationStatistics
7
+ module Private
8
+ module Metrics
9
+ class PackwerkCheckerUsage
10
+ extend T::Sig
11
+
12
+ # Later, we might find a way we can get this directly from `packwerk`
13
+ class PackwerkChecker < T::Struct
14
+ const :setting, String
15
+ const :strict_mode, String
16
+ # Later, we might convert to legacy metric names later so new clients get more sensible metric names
17
+ # That is, we might want to see metrics that are more closely connected to the new API.
18
+ # e.g. instead of `all_packages.prevent_this_package_from_violating_its_stated_dependencies.fail_on_any.count`, we'd see `all_packages.checkers.enforce_dependencies.strict.count`
19
+ # e.g. instead of `all_packages.prevent_this_package_from_creating_other_namespaces.fail_on_new.count`, `all_packages.cops.packs_namespaceconvention.true.count`
20
+ const :legacy_metric_name, String
21
+ end
22
+
23
+ sig { params(prefix: String, packages: T::Array[ParsePackwerk::Package], package_tags: T::Array[Tag]).returns(T::Array[GaugeMetric]) }
24
+ def self.get_checker_metrics(prefix, packages, package_tags)
25
+ metrics = T.let([], T::Array[GaugeMetric])
26
+
27
+ checkers = [
28
+ PackwerkChecker.new(setting: 'enforce_dependencies', strict_mode: 'enforce_dependencies_strictly', legacy_metric_name: 'prevent_this_package_from_violating_its_stated_dependencies'),
29
+ PackwerkChecker.new(setting: 'enforce_privacy', strict_mode: 'enforce_privacy_strictly', legacy_metric_name: 'prevent_other_packages_from_using_this_packages_internals')
30
+ ]
31
+
32
+ checkers.each do |checker|
33
+ ['no', 'fail_the_build_if_new_instances_appear', 'fail_the_build_on_any_instances'].each do |violation_behavior|
34
+ count_of_packages = ParsePackwerk.all.count do |package|
35
+ strict_mode = package.metadata[checker.strict_mode]
36
+ enabled = YAML.load_file(package.yml)[checker.setting]
37
+ case violation_behavior
38
+ when 'fail_the_build_on_any_instances'
39
+ !!strict_mode
40
+ when 'no'
41
+ !enabled
42
+ when 'fail_the_build_if_new_instances_appear'
43
+ enabled && !strict_mode
44
+ end
45
+ end
46
+
47
+ metric_name = "#{prefix}.#{checker.legacy_metric_name}.#{violation_behavior}.count"
48
+ metrics << GaugeMetric.for(metric_name, count_of_packages, package_tags)
49
+ end
50
+ end
51
+
52
+ metrics
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,94 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module ModularizationStatistics
5
+ module Private
6
+ module Metrics
7
+ class RubocopUsage
8
+ extend T::Sig
9
+
10
+ sig { params(prefix: String, packages: T::Array[ParsePackwerk::Package], package_tags: T::Array[Tag]).returns(T::Array[GaugeMetric]) }
11
+ def self.get_metrics(prefix, packages, package_tags)
12
+ [
13
+ *get_rubocop_exclusions(prefix, packages, package_tags),
14
+ *get_rubocop_usage_metrics(prefix, packages, package_tags)
15
+ ]
16
+ end
17
+
18
+ sig { params(prefix: String, packages: T::Array[ParsePackwerk::Package], package_tags: T::Array[Tag]).returns(T::Array[GaugeMetric]) }
19
+ def self.get_rubocop_usage_metrics(prefix, packages, package_tags)
20
+ # Rubocops
21
+ metrics = T.let([], T::Array[GaugeMetric])
22
+
23
+ rubocop_legacy_metric_map.each do |cop_name, legacy_name|
24
+ ['no', 'fail_the_build_if_new_instances_appear', 'fail_the_build_on_any_instances'].each do |violation_behavior|
25
+ count_of_packages = ParsePackwerk.all.count do |package|
26
+ # We will likely want a rubocop-packs API for this, to be able to ask if a cop is enabled for a pack.
27
+ # It's possible we will want to allow these to be enabled at the top-level `.rubocop.yml`,
28
+ # in which case we wouldn't get the right metrics with this approach. However, we can also accept
29
+ # that as a current limitation.
30
+ rubocop_yml_file = package.directory.join(RuboCop::Packs::PACK_LEVEL_RUBOCOP_YML)
31
+ next false if !rubocop_yml_file.exist?
32
+ rubocop_yml = YAML.load_file(rubocop_yml_file)
33
+ cop_config = rubocop_yml[cop_name]
34
+
35
+ strict_mode = cop_config && cop_config['FailureMode'] == 'strict'
36
+ enabled = cop_config && cop_config['Enabled']
37
+ case violation_behavior
38
+ when 'fail_the_build_on_any_instances'
39
+ !!strict_mode
40
+ when 'no'
41
+ !enabled
42
+ when 'fail_the_build_if_new_instances_appear'
43
+ enabled && !strict_mode
44
+ end
45
+ end
46
+
47
+ metric_name = "#{prefix}.#{legacy_name}.#{violation_behavior}.count"
48
+ metrics << GaugeMetric.for(metric_name, count_of_packages, package_tags)
49
+ end
50
+ end
51
+
52
+ metrics
53
+ end
54
+
55
+ sig { params(prefix: String, packages: T::Array[ParsePackwerk::Package], package_tags: T::Array[Tag]).returns(T::Array[GaugeMetric]) }
56
+ def self.get_rubocop_exclusions(prefix, packages, package_tags)
57
+ rubocop_legacy_metric_map.flat_map do |cop_name, legacy_name|
58
+ metric_name = "#{prefix}.#{legacy_name}.rubocop_exclusions.count"
59
+ all_exclusions_count = ParsePackwerk.all.sum { |package| exclude_count_for_package_and_protection(package, cop_name)}
60
+ GaugeMetric.for(metric_name, all_exclusions_count, package_tags)
61
+ end
62
+ end
63
+
64
+ # TODO: `rubocop-packs` may want to expose API for this
65
+ sig { params(package: ParsePackwerk::Package, cop_name: String).returns(Integer) }
66
+ def self.exclude_count_for_package_and_protection(package, cop_name)
67
+ if package.name == ParsePackwerk::ROOT_PACKAGE_NAME
68
+ rubocop_todo = package.directory.join('.rubocop_todo.yml')
69
+ else
70
+ rubocop_todo = package.directory.join(RuboCop::Packs::PACK_LEVEL_RUBOCOP_TODO_YML)
71
+ end
72
+
73
+ if rubocop_todo.exist?
74
+ loaded_rubocop_todo = YAML.load_file(rubocop_todo)
75
+ cop_config = loaded_rubocop_todo.fetch(cop_name, {})
76
+ cop_config.fetch('Exclude', []).count
77
+ else
78
+ 0
79
+ end
80
+ end
81
+
82
+ sig { returns(T::Hash[String, String])}
83
+ def self.rubocop_legacy_metric_map
84
+ {
85
+ 'Packs/ClassMethodsAsPublicApis' => 'prevent_this_package_from_exposing_an_untyped_api',
86
+ 'Packs/RootNamespaceIsPackName' => 'prevent_this_package_from_creating_other_namespaces',
87
+ 'Packs/TypedPublicApis' => 'prevent_this_package_from_exposing_an_untyped_api',
88
+ 'Packs/DocumentedPublicApis' => 'prevent_this_package_from_exposing_undocumented_public_apis',
89
+ }
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -10,7 +10,6 @@ require 'pathname'
10
10
  require 'modularization_statistics/private/source_code_file'
11
11
  require 'modularization_statistics/private/datadog_reporter'
12
12
  require 'parse_packwerk'
13
- require 'package_protections'
14
13
  require 'modularization_statistics/tag'
15
14
  require 'modularization_statistics/tags'
16
15
  require 'modularization_statistics/gauge_metric'
@@ -0,0 +1,141 @@
1
+ # typed: true
2
+
3
+ # DO NOT EDIT MANUALLY
4
+ # This is an autogenerated file for types exported from the `rubocop-packs` gem.
5
+ # Please instead update this file by running `bin/tapioca gem rubocop-packs`.
6
+
7
+ module RuboCop; end
8
+ module RuboCop::Cop; end
9
+ module RuboCop::Cop::Packs; end
10
+
11
+ class RuboCop::Cop::Packs::RootNamespaceIsPackName::DesiredZeitwerkApi
12
+ sig do
13
+ params(
14
+ relative_filename: ::String,
15
+ package_for_path: ::ParsePackwerk::Package
16
+ ).returns(T.nilable(::RuboCop::Cop::Packs::RootNamespaceIsPackName::DesiredZeitwerkApi::NamespaceContext))
17
+ end
18
+ def for_file(relative_filename, package_for_path); end
19
+
20
+ sig { params(pack: ::ParsePackwerk::Package).returns(::String) }
21
+ def get_pack_based_namespace(pack); end
22
+
23
+ private
24
+
25
+ sig { params(remaining_file_path: ::String, package_name: ::String).returns(::String) }
26
+ def get_actual_namespace(remaining_file_path, package_name); end
27
+
28
+ sig { params(pack: ::ParsePackwerk::Package).returns(::String) }
29
+ def get_package_last_name(pack); end
30
+
31
+ sig { returns(::Pathname) }
32
+ def root_pathname; end
33
+ end
34
+
35
+ class RuboCop::Cop::Packs::RootNamespaceIsPackName::DesiredZeitwerkApi::NamespaceContext < ::T::Struct
36
+ const :current_fully_qualified_constant, ::String
37
+ const :current_namespace, ::String
38
+ const :expected_filepath, ::String
39
+ const :expected_namespace, ::String
40
+
41
+ class << self
42
+ def inherited(s); end
43
+ end
44
+ end
45
+
46
+ module RuboCop::Cop::PackwerkLite; end
47
+ class RuboCop::Cop::PackwerkLite::ConstantResolver; end
48
+
49
+ module RuboCop::Packs
50
+ class << self
51
+ sig { params(packs: T::Array[::ParsePackwerk::Package]).void }
52
+ def auto_generate_rubocop_todo(packs:); end
53
+
54
+ sig { void }
55
+ def bust_cache!; end
56
+
57
+ sig { returns(::RuboCop::Packs::Private::Configuration) }
58
+ def config; end
59
+
60
+ sig { params(blk: T.proc.params(arg0: ::RuboCop::Packs::Private::Configuration).void).void }
61
+ def configure(&blk); end
62
+
63
+ sig { params(rule: ::String).returns(T::Set[::String]) }
64
+ def exclude_for_rule(rule); end
65
+
66
+ sig { params(root_pathname: ::String).returns(::String) }
67
+ def pack_based_rubocop_config(root_pathname: T.unsafe(nil)); end
68
+
69
+ sig { params(packs: T::Array[::ParsePackwerk::Package]).void }
70
+ def set_default_rubocop_yml(packs:); end
71
+
72
+ sig { returns(T::Array[::String]) }
73
+ def validate; end
74
+ end
75
+ end
76
+
77
+ RuboCop::Packs::CONFIG = T.let(T.unsafe(nil), Hash)
78
+ RuboCop::Packs::CONFIG_DEFAULT = T.let(T.unsafe(nil), Pathname)
79
+ class RuboCop::Packs::Error < ::StandardError; end
80
+
81
+ module RuboCop::Packs::Inject
82
+ class << self
83
+ sig { void }
84
+ def defaults!; end
85
+ end
86
+ end
87
+
88
+ RuboCop::Packs::PACK_LEVEL_RUBOCOP_TODO_YML = T.let(T.unsafe(nil), String)
89
+ RuboCop::Packs::PACK_LEVEL_RUBOCOP_YML = T.let(T.unsafe(nil), String)
90
+ RuboCop::Packs::PROJECT_ROOT = T.let(T.unsafe(nil), Pathname)
91
+
92
+ module RuboCop::Packs::Private
93
+ class << self
94
+ sig { void }
95
+ def bust_cache!; end
96
+
97
+ sig { params(rule: ::String).returns(T::Set[::String]) }
98
+ def exclude_for_rule(rule); end
99
+
100
+ sig { void }
101
+ def load_client_configuration; end
102
+
103
+ sig { returns(T::Array[T::Hash[T.untyped, T.untyped]]) }
104
+ def rubocop_todo_ymls; end
105
+
106
+ sig { params(package: ::ParsePackwerk::Package).returns(T::Array[::String]) }
107
+ def validate_failure_mode_strict(package); end
108
+
109
+ sig { params(package: ::ParsePackwerk::Package).returns(T::Array[::String]) }
110
+ def validate_rubocop_todo_yml(package); end
111
+
112
+ sig { params(package: ::ParsePackwerk::Package).returns(T::Array[::String]) }
113
+ def validate_rubocop_yml(package); end
114
+ end
115
+ end
116
+
117
+ class RuboCop::Packs::Private::Configuration
118
+ sig { void }
119
+ def initialize; end
120
+
121
+ sig { void }
122
+ def bust_cache!; end
123
+
124
+ sig { returns(T::Array[::String]) }
125
+ def globally_permitted_namespaces; end
126
+
127
+ def globally_permitted_namespaces=(_arg0); end
128
+
129
+ sig { returns(T::Array[::String]) }
130
+ def permitted_pack_level_cops; end
131
+
132
+ def permitted_pack_level_cops=(_arg0); end
133
+
134
+ sig { returns(T::Array[::String]) }
135
+ def required_pack_level_cops; end
136
+
137
+ def required_pack_level_cops=(_arg0); end
138
+ end
139
+
140
+ module RuboCop::PackwerkLite; end
141
+ class RuboCop::PackwerkLite::Error < ::StandardError; end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: modularization_statistics
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.41.0
4
+ version: 1.43.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gusto Engineers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-11-14 00:00:00.000000000 Z
11
+ date: 2022-11-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: code_teams
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: package_protections
56
+ name: parse_packwerk
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -67,7 +67,7 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: parse_packwerk
70
+ name: sorbet-runtime
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
@@ -81,7 +81,7 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: sorbet-runtime
84
+ name: rubocop-packs
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - ">="
@@ -182,9 +182,9 @@ files:
182
182
  - lib/modularization_statistics/private/metrics/nested_packs.rb
183
183
  - lib/modularization_statistics/private/metrics/packages.rb
184
184
  - lib/modularization_statistics/private/metrics/packages_by_team.rb
185
- - lib/modularization_statistics/private/metrics/protection_usage.rb
185
+ - lib/modularization_statistics/private/metrics/packwerk_checker_usage.rb
186
186
  - lib/modularization_statistics/private/metrics/public_usage.rb
187
- - lib/modularization_statistics/private/metrics/rubocop_protections_exclusions.rb
187
+ - lib/modularization_statistics/private/metrics/rubocop_usage.rb
188
188
  - lib/modularization_statistics/private/source_code_file.rb
189
189
  - lib/modularization_statistics/tag.rb
190
190
  - lib/modularization_statistics/tags.rb
@@ -193,9 +193,9 @@ files:
193
193
  - sorbet/rbi/gems/code_teams@1.0.0.rbi
194
194
  - sorbet/rbi/gems/dogapi@1.45.0.rbi
195
195
  - sorbet/rbi/gems/manual.rbi
196
- - sorbet/rbi/gems/package_protections@1.4.0.rbi
197
196
  - sorbet/rbi/gems/parse_packwerk@0.14.0.rbi
198
197
  - sorbet/rbi/gems/rspec@3.10.0.rbi
198
+ - sorbet/rbi/gems/rubocop-packs@0.0.20.rbi
199
199
  - sorbet/rbi/todo.rbi
200
200
  homepage: https://github.com/rubyatscale/modularization_statistics
201
201
  licenses:
@@ -1,149 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- module ModularizationStatistics
5
- module Private
6
- module Metrics
7
- class ProtectionUsage
8
- extend T::Sig
9
-
10
- sig { params(prefix: String, packages: T::Array[ParsePackwerk::Package], package_tags: T::Array[Tag]).returns(T::Array[GaugeMetric]) }
11
- def self.get_protections_metrics(prefix, packages, package_tags)
12
- protected_packages = packages.map { |p| PackageProtections::ProtectedPackage.from(p) }
13
- PackageProtections.all.flat_map do |protection|
14
- PackageProtections::ViolationBehavior.each_value.map do |violation_behavior|
15
- # https://github.com/Gusto/package_protections/pull/42 changed the public API of these violation behaviors.
16
- # To preserve our ability to understand historical trends, we map to the old values.
17
- # This allows our dashboards to continue to operate as expected.
18
- # Note if we ever open source mod stats, we should probably inject this behavior so that new clients can see the new keys in their metrics.
19
- violation_behavior_map = {
20
- PackageProtections::ViolationBehavior::FailOnAny => 'fail_the_build_on_any_instances',
21
- PackageProtections::ViolationBehavior::FailNever => 'no',
22
- PackageProtections::ViolationBehavior::FailOnNew => 'fail_the_build_if_new_instances_appear',
23
- }
24
- violation_behavior_name = violation_behavior_map[violation_behavior]
25
- metric_name = "#{prefix}.#{protection.identifier}.#{violation_behavior_name}.count"
26
- count_of_packages = protected_packages.count do |p|
27
- #
28
- # This is temporarily in place until we migrate off of `package_protections` in favor of `rubocop-packs`.
29
- # At that point, we want to delete this branch and instead it we'd probably have two separate branches.
30
- # One branch would look at `enforce_x` and `metadata.enforce_x_strictly`.
31
- # The other branch would look at `.pack_rubocop.yml`.
32
- # Later on, we could generalize this so that it automatically incorporates new cops from `rubocop-packs`,
33
- # or even new packwerk plugins.
34
- #
35
- # Regardless, we'll want to keep the way we are naming these behaviors for now to preserve historical trends in the data.
36
- #
37
- if p.metadata['protections']
38
- p.violation_behavior_for(protection.identifier) == violation_behavior
39
- else
40
- should_count_package?(p.original_package, protection, violation_behavior)
41
- end
42
- end
43
- GaugeMetric.for(metric_name, count_of_packages, package_tags)
44
- end
45
- end
46
- end
47
-
48
- #
49
- # Later, when we remove package protections, we can make this simpler by iterating over
50
- # packwerk checkers and rubocop packs specifically. That would let us use a common, simple
51
- # strategy to get metrics for both of them. For the first iteration, we'll want to continue
52
- # to map the old names of things to the "protection" names. After that, I think we will want to
53
- # extract that mapping into a tool that transforms the metrics that can be optionally turned off
54
- # so that we can see metrics that are more closely connected to the new API.
55
- # e.g. instead of `all_packages.prevent_this_package_from_violating_its_stated_dependencies.fail_on_any.count`, we'd see
56
- # e.g. instead of `all_packages.checkers.enforce_dependencies.strict.count`, we'd see
57
- # e.g. instead of `all_packages.prevent_this_package_from_creating_other_namespaces.fail_on_new.count`, we'd see
58
- # e.g. instead of `all_packages.cops.packs_namespaceconvention.true.count`, we'd see
59
- #
60
- sig do
61
- params(
62
- package: ParsePackwerk::Package,
63
- protection: PackageProtections::ProtectionInterface,
64
- violation_behavior: PackageProtections::ViolationBehavior
65
- ).returns(T::Boolean)
66
- end
67
- def self.should_count_package?(package, protection, violation_behavior)
68
- if protection.identifier == 'prevent_this_package_from_violating_its_stated_dependencies'
69
- strict_mode = package.metadata['enforce_dependencies_strictly']
70
- enabled = package.enforces_dependencies?
71
-
72
- case violation_behavior
73
- when PackageProtections::ViolationBehavior::FailOnAny
74
- !!strict_mode
75
- when PackageProtections::ViolationBehavior::FailNever
76
- !enabled
77
- when PackageProtections::ViolationBehavior::FailOnNew
78
- enabled && !strict_mode
79
- else
80
- T.absurd(violation_behavior)
81
- end
82
- elsif protection.identifier == 'prevent_other_packages_from_using_this_packages_internals'
83
- strict_mode = package.metadata['enforce_privacy_strictly']
84
- enabled = package.enforces_privacy?
85
-
86
- case violation_behavior
87
- when PackageProtections::ViolationBehavior::FailOnAny
88
- !!strict_mode
89
- when PackageProtections::ViolationBehavior::FailNever
90
- !enabled
91
- when PackageProtections::ViolationBehavior::FailOnNew
92
- enabled && !strict_mode
93
- else
94
- T.absurd(violation_behavior)
95
- end
96
- elsif protection.identifier == 'prevent_other_packages_from_using_this_package_without_explicit_visibility'
97
- case violation_behavior
98
- when PackageProtections::ViolationBehavior::FailOnAny
99
- # We'd probably not want to support this right away
100
- false
101
- when PackageProtections::ViolationBehavior::FailNever
102
- # We'd need to add this to `parse_packwerk` so that we can get other arbitrary top-level keys.
103
- # Alternatively we can put this in `metadata` for the time being to unblock us.
104
- # package.config['enforce_visibility']
105
- !package.metadata['enforce_visibility']
106
- when PackageProtections::ViolationBehavior::FailOnNew
107
- !!package.metadata['enforce_visibility']
108
- else
109
- T.absurd(violation_behavior)
110
- end
111
- else
112
- # Otherwise, we're in a rubocop case
113
- rubocop_yml_file = package.directory.join('.rubocop.yml')
114
- return false if !rubocop_yml_file.exist?
115
- rubocop_yml = YAML.load_file(rubocop_yml_file)
116
- protection = T.cast(protection, PackageProtections::RubocopProtectionInterface)
117
- # We will likely want a rubocop-packs API for this, to be able to ask if a cop is enabled for a pack.
118
- # It's possible we will want to allow these to be enabled at the top-level `.rubocop.yml`,
119
- # in which case we wouldn't get the right metrics with this approach. However, we can also accept
120
- # that as a current limitation.
121
- cop_map = {
122
- 'PackageProtections/TypedPublicApi' => 'Packs/TypedPublicApis',
123
- 'PackageProtections/NamespacedUnderPackageName' => 'Packs/RootNamespaceIsPackName',
124
- 'PackageProtections/OnlyClassMethods' => 'Packs/ClassMethodsAsPublicApis',
125
- 'PackageProtections/RequireDocumentedPublicApis' => 'Packs/DocumentedPublicApis',
126
- }
127
- # We want to use the cop names from `rubocop-packs`. Eventually, we'll just literate over these
128
- # cop names directly, or ask `rubocop-packs` for the list of cops to care about.
129
- cop_config = rubocop_yml[cop_map[protection.cop_name]]
130
- return false if cop_config.nil?
131
- enabled = cop_config['Enabled']
132
- strict_mode = cop_config['FailureMode'] == 'strict'
133
-
134
- case violation_behavior
135
- when PackageProtections::ViolationBehavior::FailOnAny
136
- !!strict_mode
137
- when PackageProtections::ViolationBehavior::FailNever
138
- !enabled
139
- when PackageProtections::ViolationBehavior::FailOnNew
140
- enabled && !strict_mode
141
- else
142
- T.absurd(violation_behavior)
143
- end
144
- end
145
- end
146
- end
147
- end
148
- end
149
- end
@@ -1,37 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- module ModularizationStatistics
5
- module Private
6
- module Metrics
7
- class RubocopProtectionsExclusions
8
- extend T::Sig
9
-
10
- sig { params(prefix: String, packages: T::Array[ParsePackwerk::Package], package_tags: T::Array[Tag]).returns(T::Array[GaugeMetric]) }
11
- def self.get_rubocop_exclusions(prefix, packages, package_tags)
12
- protected_packages = packages.map { |p| PackageProtections::ProtectedPackage.from(p) }
13
-
14
- rubocop_based_package_protections = T.cast(PackageProtections.all.select { |p| p.is_a?(PackageProtections::RubocopProtectionInterface) }, T::Array[PackageProtections::RubocopProtectionInterface])
15
- rubocop_based_package_protections.flat_map do |rubocop_based_package_protection|
16
- metric_name = "#{prefix}.#{rubocop_based_package_protection.identifier}.rubocop_exclusions.count"
17
- all_exclusions_count = ParsePackwerk.all.sum { |package| exclude_count_for_package_and_protection(package, rubocop_based_package_protection)}
18
- GaugeMetric.for(metric_name, all_exclusions_count, package_tags)
19
- end
20
- end
21
-
22
- # TODO: `rubocop-packs` may want to expose API for this
23
- sig { params(package: ParsePackwerk::Package, protection: PackageProtections::RubocopProtectionInterface).returns(Integer) }
24
- def self.exclude_count_for_package_and_protection(package, protection)
25
- rubocop_todo = package.directory.join('.rubocop_todo.yml')
26
- if rubocop_todo.exist?
27
- loaded_rubocop_todo = YAML.load_file(rubocop_todo)
28
- cop_config = loaded_rubocop_todo.fetch(protection.cop_name, {})
29
- cop_config.fetch('Exclude', []).count
30
- else
31
- 0
32
- end
33
- end
34
- end
35
- end
36
- end
37
- end
@@ -1,581 +0,0 @@
1
- # typed: true
2
-
3
- # DO NOT EDIT MANUALLY
4
- # This is an autogenerated file for types exported from the `package_protections` gem.
5
- # Please instead update this file by running `bin/tapioca gem package_protections`.
6
-
7
- module PackageProtections
8
- class << self
9
- sig { returns(T::Array[::PackageProtections::ProtectionInterface]) }
10
- def all; end
11
-
12
- sig { void }
13
- def bust_cache!; end
14
-
15
- sig { params(blk: T.proc.params(arg0: ::PackageProtections::Private::Configuration).void).void }
16
- def configure(&blk); end
17
-
18
- sig do
19
- params(
20
- packages: T::Array[::ParsePackwerk::Package],
21
- new_violations: T::Array[::PackageProtections::PerFileViolation]
22
- ).returns(T::Array[::PackageProtections::Offense])
23
- end
24
- def get_offenses(packages:, new_violations:); end
25
-
26
- sig { params(identifier: ::String).returns(T::Hash[T.untyped, T.untyped]) }
27
- def private_cop_config(identifier); end
28
-
29
- sig { params(root_pathname: ::Pathname).returns(::String) }
30
- def rubocop_yml(root_pathname: T.unsafe(nil)); end
31
-
32
- sig do
33
- params(
34
- packages: T::Array[::ParsePackwerk::Package],
35
- protection_identifiers: T::Array[::String],
36
- verbose: T::Boolean
37
- ).void
38
- end
39
- def set_defaults!(packages, protection_identifiers: T.unsafe(nil), verbose: T.unsafe(nil)); end
40
-
41
- sig { params(identifier: ::String).returns(::PackageProtections::ProtectionInterface) }
42
- def with_identifier(identifier); end
43
- end
44
- end
45
-
46
- PackageProtections::EXPECTED_PACK_DIRECTORIES = T.let(T.unsafe(nil), Array)
47
- PackageProtections::Identifier = T.type_alias { ::String }
48
- class PackageProtections::IncorrectPublicApiUsageError < ::StandardError; end
49
-
50
- class PackageProtections::Offense < ::T::Struct
51
- const :file, ::String
52
- const :message, ::String
53
- const :package, ::ParsePackwerk::Package
54
- const :violation_type, ::String
55
-
56
- sig { returns(::String) }
57
- def package_name; end
58
-
59
- class << self
60
- def inherited(s); end
61
- end
62
- end
63
-
64
- PackageProtections::PROTECTIONS_TODO_YML = T.let(T.unsafe(nil), String)
65
-
66
- class PackageProtections::PerFileViolation < ::T::Struct
67
- const :class_name, ::String
68
- const :constant_source_package, ::String
69
- const :filepath, ::String
70
- const :reference_source_package, ::ParsePackwerk::Package
71
- const :type, ::String
72
-
73
- sig { returns(T::Boolean) }
74
- def dependency?; end
75
-
76
- sig { returns(T::Boolean) }
77
- def privacy?; end
78
-
79
- class << self
80
- sig do
81
- params(
82
- violation: ::ParsePackwerk::Violation,
83
- reference_source_package: ::ParsePackwerk::Package
84
- ).returns(T::Array[::PackageProtections::PerFileViolation])
85
- end
86
- def from(violation, reference_source_package); end
87
-
88
- def inherited(s); end
89
- end
90
- end
91
-
92
- module PackageProtections::Private
93
- class << self
94
- sig { returns(T::Array[::PackageProtections::ProtectedPackage]) }
95
- def all_protected_packages; end
96
-
97
- sig { void }
98
- def bust_cache!; end
99
-
100
- sig { returns(::PackageProtections::Private::Configuration) }
101
- def config; end
102
-
103
- sig do
104
- params(
105
- packages: T::Array[::ParsePackwerk::Package],
106
- new_violations: T::Array[::PackageProtections::PerFileViolation]
107
- ).returns(T::Array[::PackageProtections::Offense])
108
- end
109
- def get_offenses(packages:, new_violations:); end
110
-
111
- sig { params(name: ::String).returns(::PackageProtections::ProtectedPackage) }
112
- def get_package_with_name(name); end
113
-
114
- sig { params(identifier: ::String).returns(T::Hash[T.untyped, T.untyped]) }
115
- def private_cop_config(identifier); end
116
-
117
- sig { params(root_pathname: ::Pathname).returns(::String) }
118
- def rubocop_yml(root_pathname:); end
119
-
120
- sig do
121
- params(
122
- packages: T::Array[::ParsePackwerk::Package],
123
- protection_identifiers: T::Array[::String],
124
- verbose: T::Boolean
125
- ).void
126
- end
127
- def set_defaults!(packages, protection_identifiers:, verbose:); end
128
- end
129
- end
130
-
131
- class PackageProtections::Private::ColorizedString
132
- sig { params(original_string: ::String, color: ::PackageProtections::Private::ColorizedString::Color).void }
133
- def initialize(original_string, color = T.unsafe(nil)); end
134
-
135
- sig { returns(::PackageProtections::Private::ColorizedString) }
136
- def blue; end
137
-
138
- sig { returns(::String) }
139
- def colorized_to_s; end
140
-
141
- sig { returns(::PackageProtections::Private::ColorizedString) }
142
- def green; end
143
-
144
- sig { returns(::PackageProtections::Private::ColorizedString) }
145
- def light_blue; end
146
-
147
- sig { returns(::PackageProtections::Private::ColorizedString) }
148
- def pink; end
149
-
150
- sig { returns(::PackageProtections::Private::ColorizedString) }
151
- def red; end
152
-
153
- sig { returns(::String) }
154
- def to_s; end
155
-
156
- sig { returns(::PackageProtections::Private::ColorizedString) }
157
- def white; end
158
-
159
- sig { returns(::PackageProtections::Private::ColorizedString) }
160
- def yellow; end
161
-
162
- private
163
-
164
- sig { returns(::Integer) }
165
- def color_code; end
166
-
167
- sig do
168
- params(
169
- color: ::PackageProtections::Private::ColorizedString::Color
170
- ).returns(::PackageProtections::Private::ColorizedString)
171
- end
172
- def colorize(color); end
173
- end
174
-
175
- class PackageProtections::Private::ColorizedString::Color < ::T::Enum
176
- enums do
177
- Black = new
178
- Red = new
179
- Green = new
180
- Yellow = new
181
- Blue = new
182
- Pink = new
183
- LightBlue = new
184
- White = new
185
- end
186
- end
187
-
188
- class PackageProtections::Private::Configuration
189
- sig { void }
190
- def initialize; end
191
-
192
- sig { void }
193
- def bust_cache!; end
194
-
195
- sig { returns(T::Array[::PackageProtections::ProtectionInterface]) }
196
- def default_protections; end
197
-
198
- sig { returns(T::Array[::PackageProtections::ProtectionInterface]) }
199
- def protections; end
200
-
201
- sig { params(protections: T::Array[::PackageProtections::ProtectionInterface]).void }
202
- def protections=(protections); end
203
- end
204
-
205
- class PackageProtections::Private::IncomingPrivacyProtection
206
- include ::PackageProtections::ProtectionInterface
207
-
208
- sig do
209
- override
210
- .params(
211
- protected_packages: T::Array[::PackageProtections::ProtectedPackage]
212
- ).returns(T::Array[::PackageProtections::Offense])
213
- end
214
- def get_offenses_for_existing_violations(protected_packages); end
215
-
216
- sig do
217
- override
218
- .params(
219
- new_violations: T::Array[::PackageProtections::PerFileViolation]
220
- ).returns(T::Array[::PackageProtections::Offense])
221
- end
222
- def get_offenses_for_new_violations(new_violations); end
223
-
224
- sig { override.returns(::String) }
225
- def humanized_protection_description; end
226
-
227
- sig { override.returns(::String) }
228
- def humanized_protection_name; end
229
-
230
- sig { override.returns(::String) }
231
- def identifier; end
232
-
233
- sig do
234
- override
235
- .params(
236
- behavior: ::PackageProtections::ViolationBehavior,
237
- package: ::ParsePackwerk::Package
238
- ).returns(T.nilable(::String))
239
- end
240
- def unmet_preconditions_for_behavior(behavior, package); end
241
-
242
- private
243
-
244
- sig { params(per_file_violation: ::PackageProtections::PerFileViolation).returns(::String) }
245
- def message_for_fail_on_any(per_file_violation); end
246
-
247
- sig { params(per_file_violation: ::PackageProtections::PerFileViolation).returns(::String) }
248
- def message_for_fail_on_new(per_file_violation); end
249
- end
250
-
251
- PackageProtections::Private::IncomingPrivacyProtection::IDENTIFIER = T.let(T.unsafe(nil), String)
252
-
253
- class PackageProtections::Private::MetadataModifiers
254
- class << self
255
- sig do
256
- params(
257
- package: ::ParsePackwerk::Package,
258
- protection_identifier: ::String,
259
- violation_behavior: ::PackageProtections::ViolationBehavior
260
- ).returns(::ParsePackwerk::Package)
261
- end
262
- def package_with_modified_protection(package, protection_identifier, violation_behavior); end
263
- end
264
- end
265
-
266
- class PackageProtections::Private::OutgoingDependencyProtection
267
- include ::PackageProtections::ProtectionInterface
268
-
269
- sig do
270
- override
271
- .params(
272
- protected_packages: T::Array[::PackageProtections::ProtectedPackage]
273
- ).returns(T::Array[::PackageProtections::Offense])
274
- end
275
- def get_offenses_for_existing_violations(protected_packages); end
276
-
277
- sig do
278
- override
279
- .params(
280
- new_violations: T::Array[::PackageProtections::PerFileViolation]
281
- ).returns(T::Array[::PackageProtections::Offense])
282
- end
283
- def get_offenses_for_new_violations(new_violations); end
284
-
285
- sig { override.returns(::String) }
286
- def humanized_protection_description; end
287
-
288
- sig { override.returns(::String) }
289
- def humanized_protection_name; end
290
-
291
- sig { override.returns(::String) }
292
- def identifier; end
293
-
294
- sig do
295
- override
296
- .params(
297
- behavior: ::PackageProtections::ViolationBehavior,
298
- package: ::ParsePackwerk::Package
299
- ).returns(T.nilable(::String))
300
- end
301
- def unmet_preconditions_for_behavior(behavior, package); end
302
-
303
- private
304
-
305
- sig { params(per_file_violation: ::PackageProtections::PerFileViolation).returns(::String) }
306
- def message_for_fail_on_any(per_file_violation); end
307
-
308
- sig { params(per_file_violation: ::PackageProtections::PerFileViolation).returns(::String) }
309
- def message_for_fail_on_new(per_file_violation); end
310
- end
311
-
312
- PackageProtections::Private::OutgoingDependencyProtection::IDENTIFIER = T.let(T.unsafe(nil), String)
313
-
314
- class PackageProtections::Private::Output
315
- class << self
316
- sig { params(str: ::String).void }
317
- def p(str); end
318
-
319
- sig { params(str: ::PackageProtections::Private::ColorizedString, colorized: T::Boolean).void }
320
- def p_colorized(str, colorized:); end
321
- end
322
- end
323
-
324
- class PackageProtections::Private::VisibilityProtection
325
- include ::PackageProtections::ProtectionInterface
326
-
327
- sig { returns(::PackageProtections::ViolationBehavior) }
328
- def default_behavior; end
329
-
330
- sig do
331
- override
332
- .params(
333
- protected_packages: T::Array[::PackageProtections::ProtectedPackage]
334
- ).returns(T::Array[::PackageProtections::Offense])
335
- end
336
- def get_offenses_for_existing_violations(protected_packages); end
337
-
338
- sig do
339
- override
340
- .params(
341
- new_violations: T::Array[::PackageProtections::PerFileViolation]
342
- ).returns(T::Array[::PackageProtections::Offense])
343
- end
344
- def get_offenses_for_new_violations(new_violations); end
345
-
346
- sig { override.returns(::String) }
347
- def humanized_protection_description; end
348
-
349
- sig { override.returns(::String) }
350
- def humanized_protection_name; end
351
-
352
- sig { override.returns(::String) }
353
- def identifier; end
354
-
355
- sig do
356
- override
357
- .params(
358
- behavior: ::PackageProtections::ViolationBehavior,
359
- package: ::ParsePackwerk::Package
360
- ).returns(T.nilable(::String))
361
- end
362
- def unmet_preconditions_for_behavior(behavior, package); end
363
-
364
- private
365
-
366
- sig { params(per_file_violation: ::PackageProtections::PerFileViolation).returns(::String) }
367
- def message_for_fail_on_any(per_file_violation); end
368
-
369
- sig { params(per_file_violation: ::PackageProtections::PerFileViolation).returns(::String) }
370
- def message_for_fail_on_new(per_file_violation); end
371
- end
372
-
373
- PackageProtections::Private::VisibilityProtection::IDENTIFIER = T.let(T.unsafe(nil), String)
374
-
375
- class PackageProtections::ProtectedPackage < ::T::Struct
376
- const :deprecated_references, ::ParsePackwerk::DeprecatedReferences
377
- const :original_package, ::ParsePackwerk::Package
378
- const :protections, T::Hash[::String, ::PackageProtections::ViolationBehavior]
379
-
380
- sig { returns(T::Array[::String]) }
381
- def dependencies; end
382
-
383
- sig { returns(T::Hash[T.untyped, T.untyped]) }
384
- def metadata; end
385
-
386
- sig { returns(::String) }
387
- def name; end
388
-
389
- sig { params(key: ::String).returns(::PackageProtections::ViolationBehavior) }
390
- def violation_behavior_for(key); end
391
-
392
- sig { returns(T::Array[::ParsePackwerk::Violation]) }
393
- def violations; end
394
-
395
- sig { returns(T::Set[::String]) }
396
- def visible_to; end
397
-
398
- sig { returns(::Pathname) }
399
- def yml; end
400
-
401
- class << self
402
- sig { params(original_package: ::ParsePackwerk::Package).returns(::PackageProtections::ProtectedPackage) }
403
- def from(original_package); end
404
-
405
- sig do
406
- params(
407
- protection: ::PackageProtections::ProtectionInterface,
408
- metadata: T::Hash[T.untyped, T.untyped],
409
- package: ::ParsePackwerk::Package
410
- ).returns(::PackageProtections::ViolationBehavior)
411
- end
412
- def get_violation_behavior(protection, metadata, package); end
413
-
414
- def inherited(s); end
415
- end
416
- end
417
-
418
- module PackageProtections::ProtectionInterface
419
- requires_ancestor { Kernel }
420
-
421
- abstract!
422
-
423
- sig { returns(::PackageProtections::ViolationBehavior) }
424
- def default_behavior; end
425
-
426
- sig do
427
- params(
428
- protected_packages: T::Array[::PackageProtections::ProtectedPackage],
429
- new_violations: T::Array[::PackageProtections::PerFileViolation]
430
- ).returns(T::Array[::PackageProtections::Offense])
431
- end
432
- def get_offenses(protected_packages, new_violations); end
433
-
434
- sig do
435
- abstract
436
- .params(
437
- protected_packages: T::Array[::PackageProtections::ProtectedPackage]
438
- ).returns(T::Array[::PackageProtections::Offense])
439
- end
440
- def get_offenses_for_existing_violations(protected_packages); end
441
-
442
- sig do
443
- abstract
444
- .params(
445
- new_violations: T::Array[::PackageProtections::PerFileViolation]
446
- ).returns(T::Array[::PackageProtections::Offense])
447
- end
448
- def get_offenses_for_new_violations(new_violations); end
449
-
450
- sig { abstract.returns(::String) }
451
- def humanized_protection_description; end
452
-
453
- sig { abstract.returns(::String) }
454
- def humanized_protection_name; end
455
-
456
- sig { abstract.returns(::String) }
457
- def identifier; end
458
-
459
- sig do
460
- params(
461
- behavior: ::PackageProtections::ViolationBehavior,
462
- package: ::ParsePackwerk::Package
463
- ).returns(T::Boolean)
464
- end
465
- def supports_violation_behavior?(behavior, package); end
466
-
467
- sig do
468
- abstract
469
- .params(
470
- behavior: ::PackageProtections::ViolationBehavior,
471
- package: ::ParsePackwerk::Package
472
- ).returns(T.nilable(::String))
473
- end
474
- def unmet_preconditions_for_behavior(behavior, package); end
475
- end
476
-
477
- module PackageProtections::RubocopProtectionInterface
478
- include ::PackageProtections::ProtectionInterface
479
-
480
- abstract!
481
-
482
- sig do
483
- params(
484
- packages: T::Array[::PackageProtections::ProtectedPackage]
485
- ).returns(T::Array[::PackageProtections::RubocopProtectionInterface::CopConfig])
486
- end
487
- def cop_configs(packages); end
488
-
489
- sig { abstract.returns(::String) }
490
- def cop_name; end
491
-
492
- sig { params(package: ::PackageProtections::ProtectedPackage).returns(T::Hash[T.untyped, T.untyped]) }
493
- def custom_cop_config(package); end
494
-
495
- sig do
496
- override
497
- .params(
498
- protected_packages: T::Array[::PackageProtections::ProtectedPackage]
499
- ).returns(T::Array[::PackageProtections::Offense])
500
- end
501
- def get_offenses_for_existing_violations(protected_packages); end
502
-
503
- sig do
504
- override
505
- .params(
506
- new_violations: T::Array[::PackageProtections::PerFileViolation]
507
- ).returns(T::Array[::PackageProtections::Offense])
508
- end
509
- def get_offenses_for_new_violations(new_violations); end
510
-
511
- sig { abstract.returns(T::Array[::String]) }
512
- def included_globs_for_pack; end
513
-
514
- sig { abstract.params(file: ::String).returns(::String) }
515
- def message_for_fail_on_any(file); end
516
-
517
- sig do
518
- override
519
- .params(
520
- behavior: ::PackageProtections::ViolationBehavior,
521
- package: ::ParsePackwerk::Package
522
- ).returns(T.nilable(::String))
523
- end
524
- def unmet_preconditions_for_behavior(behavior, package); end
525
-
526
- private
527
-
528
- sig { params(rule: ::String).returns(T::Set[::String]) }
529
- def exclude_for_rule(rule); end
530
-
531
- class << self
532
- sig { void }
533
- def bust_rubocop_todo_yml_cache; end
534
-
535
- sig { returns(T.untyped) }
536
- def rubocop_todo_yml; end
537
- end
538
- end
539
-
540
- class PackageProtections::RubocopProtectionInterface::CopConfig < ::T::Struct
541
- const :enabled, T::Boolean, default: T.unsafe(nil)
542
- const :exclude_paths, T::Array[::String], default: T.unsafe(nil)
543
- const :include_paths, T::Array[::String], default: T.unsafe(nil)
544
- const :name, ::String
545
-
546
- sig { returns(::String) }
547
- def to_rubocop_yml_compatible_format; end
548
-
549
- class << self
550
- def inherited(s); end
551
- end
552
- end
553
-
554
- class PackageProtections::ViolationBehavior < ::T::Enum
555
- enums do
556
- FailOnAny = new
557
- FailOnNew = new
558
- FailNever = new
559
- end
560
-
561
- sig { returns(T::Boolean) }
562
- def enabled?; end
563
-
564
- sig { returns(T::Boolean) }
565
- def fail_never?; end
566
-
567
- sig { returns(T::Boolean) }
568
- def fail_on_any?; end
569
-
570
- sig { returns(T::Boolean) }
571
- def fail_on_new?; end
572
-
573
- class << self
574
- sig { params(value: T.untyped).returns(::PackageProtections::ViolationBehavior) }
575
- def from_raw_value(value); end
576
- end
577
- end
578
-
579
- module RuboCop; end
580
- module RuboCop::Cop; end
581
- module RuboCop::Cop::PackageProtections; end