modularization_statistics 1.37.0 → 1.38.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: 252db0bdd5ec50e555d34ce4c7468df4a5bf731274fafd137a319eaf1a1100b9
4
- data.tar.gz: 8983a207179da6a93b34464f98c3b478a23087b34946f63d4c1cf95992d10f9e
3
+ metadata.gz: 1ab5b40d2d974d45aae986a4a0418e8d50984c4d4d39e963815dfd5fb875efc6
4
+ data.tar.gz: 91a571c247677445e408cd8aa0d2cc0a4adc2e5daed55ce4a6a8cc2e69429b81
5
5
  SHA512:
6
- metadata.gz: cebc018b3841416b6194e3cef53779f3529f2d56463bbd8c6d79a6fb322f9c1c1a81d0a357fb8140cd48853abe6d5d1de160e707414b2d71eccbdbbb36dc9993
7
- data.tar.gz: d837d652fed0baca80bfc6e1613d1ab75e1ac5b5b7d798c7df544a53e3c27c5c20ab82d8d39891aa29034541086d0e6a6b3e806d22b5b575c836951a1f96cac7
6
+ metadata.gz: e3454d7e5f523f3d6030e1b1789fa1d0b363fbcc6c7069170797c4efd4256a463a77d43dbfa94da1fce24b13283592eb016f7923591b28406038ed9e44fd0eb5
7
+ data.tar.gz: 5718efcffc45331f23b185f8b7565301cd35d8c1735eca4e9723b3086725ec30b7b6c399c16fdcc0788795fa4d39654c7bfa8348ec8b6188d3522584e55de147
@@ -17,36 +17,34 @@ module ModularizationStatistics
17
17
  all_metrics = []
18
18
  app_level_tag = Tag.for('app', app_name)
19
19
  package_tags = T.let([app_level_tag], T::Array[Tag])
20
- protected_packages = packages.map { |p| PackageProtections::ProtectedPackage.from(p) }
21
20
 
22
21
  all_metrics << GaugeMetric.for('all_packages.count', packages.count, package_tags)
23
22
  all_metrics << GaugeMetric.for('all_packages.dependencies.count', packages.sum { |package| package.dependencies.count }, package_tags)
24
- all_metrics << GaugeMetric.for('all_packages.dependency_violations.count', protected_packages.sum { |package| Metrics.file_count(package.violations.select(&:dependency?)) }, package_tags)
25
- all_metrics << GaugeMetric.for('all_packages.privacy_violations.count', protected_packages.sum { |package| Metrics.file_count(package.violations.select(&:privacy?)) }, package_tags)
23
+ all_metrics << GaugeMetric.for('all_packages.dependency_violations.count', packages.sum { |package| Metrics.file_count(package.violations.select(&:dependency?)) }, package_tags)
24
+ all_metrics << GaugeMetric.for('all_packages.privacy_violations.count', packages.sum { |package| Metrics.file_count(package.violations.select(&:privacy?)) }, package_tags)
26
25
  all_metrics << GaugeMetric.for('all_packages.enforcing_dependencies.count', packages.count(&:enforces_dependencies?), package_tags)
27
26
  all_metrics << GaugeMetric.for('all_packages.enforcing_privacy.count', packages.count(&:enforces_privacy?), package_tags)
28
27
 
29
28
  all_metrics << GaugeMetric.for('all_packages.notify_on_package_yml_changes.count', packages.count { |p| p.metadata['notify_on_package_yml_changes'] }, package_tags)
30
29
  all_metrics << GaugeMetric.for('all_packages.notify_on_new_violations.count', packages.count { |p| p.metadata['notify_on_new_violations'] }, package_tags)
31
30
 
32
- all_metrics << GaugeMetric.for('all_packages.with_violations.count', protected_packages.count { |package| package.violations.any? }, package_tags)
31
+ all_metrics << GaugeMetric.for('all_packages.with_violations.count', packages.count { |package| package.violations.any? }, package_tags)
33
32
  all_metrics += Metrics::PublicUsage.get_public_usage_metrics('all_packages', packages, package_tags)
34
33
  all_metrics << GaugeMetric.for('all_packages.has_readme.count', packages.count { |package| Metrics.has_readme?(package) }, package_tags)
35
34
 
36
- all_metrics += Metrics::ProtectionUsage.get_protections_metrics('all_packages', protected_packages, package_tags)
37
- all_metrics += Metrics::RubocopProtectionsExclusions.get_rubocop_exclusions('all_packages', protected_packages, package_tags)
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)
38
37
  all_metrics << GaugeMetric.for('all_packages.package_based_file_ownership.count', packages.count { |package| !package.metadata['owner'].nil? }, package_tags)
39
38
 
40
- inbound_violations_by_package = protected_packages.flat_map(&:violations).group_by(&:to_package_name)
39
+ inbound_violations_by_package = packages.flat_map(&:violations).group_by(&:to_package_name)
41
40
 
42
- protected_packages.each do |protected_package|
43
- package = protected_package.original_package
41
+ packages.each do |package|
44
42
  package_tags = Metrics.tags_for_package(package, app_name)
45
43
 
46
44
  #
47
45
  # VIOLATIONS (implicit dependencies)
48
46
  #
49
- outbound_violations = protected_package.violations
47
+ outbound_violations = package.violations
50
48
  inbound_violations = inbound_violations_by_package[package.name] || []
51
49
  all_dependency_violations = (outbound_violations + inbound_violations).select(&:dependency?)
52
50
  all_privacy_violations = (outbound_violations + inbound_violations).select(&:privacy?)
@@ -62,7 +60,7 @@ module ModularizationStatistics
62
60
 
63
61
  all_metrics += Metrics::PublicUsage.get_public_usage_metrics('by_package', [package], package_tags)
64
62
 
65
- protected_package.violations.group_by(&:to_package_name).each do |to_package_name, violations|
63
+ package.violations.group_by(&:to_package_name).each do |to_package_name, violations|
66
64
  to_package = ParsePackwerk.find(to_package_name)
67
65
  if to_package.nil?
68
66
  raise StandardError, "Could not find matching package #{to_package_name}"
@@ -16,25 +16,25 @@ module ModularizationStatistics
16
16
  def self.get_package_metrics_by_team(all_packages, app_name)
17
17
  all_metrics = T.let([], T::Array[GaugeMetric])
18
18
  app_level_tag = Tag.for('app', app_name)
19
- all_protected_packages = all_packages.map { |p| PackageProtections::ProtectedPackage.from(p) }
20
- all_protected_packages.group_by { |protected_package| CodeOwnership.for_package(protected_package.original_package)&.name }.each do |team_name, protected_packages_by_team|
19
+
20
+ all_packages.group_by { |package| CodeOwnership.for_package(package)&.name }.each do |team_name, packages_by_team|
21
21
  # We look at `all_packages` because we care about ALL inbound violations across all teams
22
- inbound_violations_by_package = all_protected_packages.flat_map(&:violations).group_by(&:to_package_name)
22
+ inbound_violations_by_package = all_packages.flat_map(&:violations).group_by(&:to_package_name)
23
23
 
24
24
  team_tags = Metrics.tags_for_team(team_name) + [app_level_tag]
25
- all_metrics << GaugeMetric.for('by_team.all_packages.count', protected_packages_by_team.count, team_tags)
26
- all_metrics += Metrics::ProtectionUsage.get_protections_metrics('by_team', protected_packages_by_team, team_tags)
27
- all_metrics += Metrics::PublicUsage.get_public_usage_metrics('by_team', protected_packages_by_team.map(&:original_package), team_tags)
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)
27
+ all_metrics += Metrics::PublicUsage.get_public_usage_metrics('by_team', packages_by_team, team_tags)
28
28
 
29
- all_metrics << GaugeMetric.for('by_team.notify_on_package_yml_changes.count', protected_packages_by_team.count { |p| p.metadata['notify_on_package_yml_changes'] }, team_tags)
30
- all_metrics << GaugeMetric.for('by_team.notify_on_new_violations.count', protected_packages_by_team.count { |p| p.metadata['notify_on_new_violations'] }, team_tags)
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)
30
+ all_metrics << GaugeMetric.for('by_team.notify_on_new_violations.count', packages_by_team.count { |p| p.metadata['notify_on_new_violations'] }, team_tags)
31
31
 
32
32
  #
33
33
  # VIOLATIONS (implicit dependencies)
34
34
  #
35
- outbound_violations = protected_packages_by_team.flat_map(&:violations)
35
+ outbound_violations = packages_by_team.flat_map(&:violations)
36
36
  # Here we only look at packages_by_team because we only care about inbound violations onto packages for this team
37
- inbound_violations = protected_packages_by_team.flat_map { |package| inbound_violations_by_package[package.name] || [] }
37
+ inbound_violations = packages_by_team.flat_map { |package| inbound_violations_by_package[package.name] || [] }
38
38
  all_dependency_violations = (outbound_violations + inbound_violations).select(&:dependency?)
39
39
  all_privacy_violations = (outbound_violations + inbound_violations).select(&:privacy?)
40
40
 
@@ -47,7 +47,7 @@ module ModularizationStatistics
47
47
  all_metrics << GaugeMetric.for('by_team.outbound_privacy_violations.count', Metrics.file_count(outbound_violations.select(&:privacy?)), team_tags)
48
48
  all_metrics << GaugeMetric.for('by_team.inbound_privacy_violations.count', Metrics.file_count(inbound_violations.select(&:privacy?)), team_tags)
49
49
 
50
- all_metrics << GaugeMetric.for('by_team.has_readme.count', protected_packages_by_team.count { |protected_package| Metrics.has_readme?(protected_package.original_package) }, team_tags)
50
+ all_metrics << GaugeMetric.for('by_team.has_readme.count', packages_by_team.count { |package| Metrics.has_readme?(package) }, team_tags)
51
51
 
52
52
  grouped_outbound_violations = outbound_violations.group_by do |violation|
53
53
  to_package = ParsePackwerk.find(violation.to_package_name)
@@ -7,8 +7,9 @@ module ModularizationStatistics
7
7
  class ProtectionUsage
8
8
  extend T::Sig
9
9
 
10
- sig { params(prefix: String, protected_packages: T::Array[PackageProtections::ProtectedPackage], package_tags: T::Array[Tag]).returns(T::Array[GaugeMetric]) }
11
- def self.get_protections_metrics(prefix, protected_packages, package_tags)
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) }
12
13
  PackageProtections.all.flat_map do |protection|
13
14
  PackageProtections::ViolationBehavior.each_value.map do |violation_behavior|
14
15
  # https://github.com/Gusto/package_protections/pull/42 changed the public API of these violation behaviors.
@@ -22,7 +23,47 @@ module ModularizationStatistics
22
23
  }
23
24
  violation_behavior_name = violation_behavior_map[violation_behavior]
24
25
  metric_name = "#{prefix}.#{protection.identifier}.#{violation_behavior_name}.count"
25
- count_of_packages = protected_packages.count { |p| p.violation_behavior_for(protection.identifier) == violation_behavior }
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.strictly_enforce_x`.
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
+ case violation_behavior
41
+ when PackageProtections::ViolationBehavior::FailOnAny
42
+ # There is not yet an implementation for `FailOnAny` for systems that don't use package protections
43
+ false
44
+ when PackageProtections::ViolationBehavior::FailNever
45
+ if protection.identifier == 'prevent_this_package_from_violating_its_stated_dependencies'
46
+ !p.original_package.enforces_dependencies?
47
+ elsif protection.identifier == 'prevent_other_packages_from_using_this_packages_internals'
48
+ !p.original_package.enforces_privacy?
49
+ else
50
+ # This is not applicable if you're not using package protections
51
+ true
52
+ end
53
+ when PackageProtections::ViolationBehavior::FailOnNew
54
+ if protection.identifier == 'prevent_this_package_from_violating_its_stated_dependencies'
55
+ p.original_package.enforces_dependencies?
56
+ elsif protection.identifier == 'prevent_other_packages_from_using_this_packages_internals'
57
+ p.original_package.enforces_privacy?
58
+ else
59
+ # This is not applicable if you're not using package protections
60
+ false
61
+ end
62
+ else
63
+ T.absurd(violation_behavior)
64
+ end
65
+ end
66
+ end
26
67
  GaugeMetric.for(metric_name, count_of_packages, package_tags)
27
68
  end
28
69
  end
@@ -7,8 +7,10 @@ module ModularizationStatistics
7
7
  class RubocopProtectionsExclusions
8
8
  extend T::Sig
9
9
 
10
- sig { params(prefix: String, protected_packages: T::Array[PackageProtections::ProtectedPackage], package_tags: T::Array[Tag]).returns(T::Array[GaugeMetric]) }
11
- def self.get_rubocop_exclusions(prefix, protected_packages, package_tags)
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
+
12
14
  rubocop_based_package_protections = T.cast(PackageProtections.all.select { |p| p.is_a?(PackageProtections::RubocopProtectionInterface) }, T::Array[PackageProtections::RubocopProtectionInterface])
13
15
  rubocop_based_package_protections.flat_map do |rubocop_based_package_protection|
14
16
  metric_name = "#{prefix}.#{rubocop_based_package_protection.identifier}.rubocop_exclusions.count"
@@ -17,6 +19,7 @@ module ModularizationStatistics
17
19
  end
18
20
  end
19
21
 
22
+ # TODO: `rubocop-packs` may want to expose API for this
20
23
  sig { params(package: ParsePackwerk::Package, protection: PackageProtections::RubocopProtectionInterface).returns(Integer) }
21
24
  def self.exclude_count_for_package_and_protection(package, protection)
22
25
  rubocop_todo = package.directory.join('.rubocop_todo.yml')
@@ -15,7 +15,7 @@ module ParsePackwerk
15
15
  sig { params(name: ::String).returns(T.nilable(::ParsePackwerk::Package)) }
16
16
  def find(name); end
17
17
 
18
- sig { params(file_path: T.any(::Pathname, ::String)).returns(T.nilable(::ParsePackwerk::Package)) }
18
+ sig { params(file_path: T.any(::Pathname, ::String)).returns(::ParsePackwerk::Package) }
19
19
  def package_from_path(file_path); end
20
20
 
21
21
  sig { params(package: ::ParsePackwerk::Package).void }
@@ -51,6 +51,7 @@ end
51
51
 
52
52
  ParsePackwerk::DEFAULT_EXCLUDE_GLOBS = T.let(T.unsafe(nil), Array)
53
53
  ParsePackwerk::DEFAULT_PACKAGE_PATHS = T.let(T.unsafe(nil), Array)
54
+ ParsePackwerk::DEFAULT_PUBLIC_PATH = T.let(T.unsafe(nil), String)
54
55
  ParsePackwerk::DEPENDENCIES = T.let(T.unsafe(nil), String)
55
56
  ParsePackwerk::DEPRECATED_REFERENCES_YML_NAME = T.let(T.unsafe(nil), String)
56
57
 
@@ -81,6 +82,7 @@ end
81
82
 
82
83
  ParsePackwerk::PACKAGE_YML_NAME = T.let(T.unsafe(nil), String)
83
84
  ParsePackwerk::PACKWERK_YML_NAME = T.let(T.unsafe(nil), String)
85
+ ParsePackwerk::PUBLIC_PATH = T.let(T.unsafe(nil), String)
84
86
 
85
87
  class ParsePackwerk::Package < ::T::Struct
86
88
  const :dependencies, T::Array[::String]
@@ -88,6 +90,7 @@ class ParsePackwerk::Package < ::T::Struct
88
90
  const :enforce_privacy, T::Boolean
89
91
  const :metadata, T::Hash[T.untyped, T.untyped]
90
92
  const :name, ::String
93
+ const :public_path, ::String, default: T.unsafe(nil)
91
94
 
92
95
  sig { returns(::Pathname) }
93
96
  def directory; end
@@ -98,6 +101,12 @@ class ParsePackwerk::Package < ::T::Struct
98
101
  sig { returns(T::Boolean) }
99
102
  def enforces_privacy?; end
100
103
 
104
+ sig { returns(::Pathname) }
105
+ def public_directory; end
106
+
107
+ sig { returns(T::Array[::ParsePackwerk::Violation]) }
108
+ def violations; end
109
+
101
110
  sig { returns(::Pathname) }
102
111
  def yml; end
103
112
 
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.37.0
4
+ version: 1.38.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-09-07 00:00:00.000000000 Z
11
+ date: 2022-10-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: code_teams
@@ -194,7 +194,7 @@ files:
194
194
  - sorbet/rbi/gems/dogapi@1.45.0.rbi
195
195
  - sorbet/rbi/gems/manual.rbi
196
196
  - sorbet/rbi/gems/package_protections@1.4.0.rbi
197
- - sorbet/rbi/gems/parse_packwerk@0.12.0.rbi
197
+ - sorbet/rbi/gems/parse_packwerk@0.14.0.rbi
198
198
  - sorbet/rbi/gems/rspec@3.10.0.rbi
199
199
  - sorbet/rbi/todo.rbi
200
200
  homepage: https://github.com/rubyatscale/modularization_statistics
@@ -220,7 +220,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
220
220
  - !ruby/object:Gem::Version
221
221
  version: '0'
222
222
  requirements: []
223
- rubygems_version: 3.3.7
223
+ rubygems_version: 3.1.6
224
224
  signing_key:
225
225
  specification_version: 4
226
226
  summary: A gem to collect statistics about modularization progress in a Rails application