modularization_statistics 1.41.0 → 1.43.0

Sign up to get free protection for your applications and to get access to all the features.
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