modularization_statistics 1.38.0 → 1.39.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: 1ab5b40d2d974d45aae986a4a0418e8d50984c4d4d39e963815dfd5fb875efc6
4
- data.tar.gz: 91a571c247677445e408cd8aa0d2cc0a4adc2e5daed55ce4a6a8cc2e69429b81
3
+ metadata.gz: c11bc9704708d387bff6b5d7245832c6d57c9291a7dcc306513e3942afb53311
4
+ data.tar.gz: 7d5403d37a5811f5ef1798a3a8bfb96b304124ada289b75dba14db0844fd252e
5
5
  SHA512:
6
- metadata.gz: e3454d7e5f523f3d6030e1b1789fa1d0b363fbcc6c7069170797c4efd4256a463a77d43dbfa94da1fce24b13283592eb016f7923591b28406038ed9e44fd0eb5
7
- data.tar.gz: 5718efcffc45331f23b185f8b7565301cd35d8c1735eca4e9723b3086725ec30b7b6c399c16fdcc0788795fa4d39654c7bfa8348ec8b6188d3522584e55de147
6
+ metadata.gz: 2c82a234d983ddc50d494f6eb8933633a0b61a7e82783d375f5d22b02c1e12fb476f9fb70ca35885ecadc879dd1fc94179cf6db3b1d52f47501afe38c6349651
7
+ data.tar.gz: ec00762292cdec0eb441ad424bdd5e80733a9acd418925f82c92142988df9d4b3b6843b8e4de1d9b8190e48cf23f6818b2e4f7176bf263a6541fa490181c38b0
@@ -37,37 +37,112 @@ module ModularizationStatistics
37
37
  if p.metadata['protections']
38
38
  p.violation_behavior_for(protection.identifier) == violation_behavior
39
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
40
+ should_count_package?(p.original_package, protection, violation_behavior)
65
41
  end
66
42
  end
67
43
  GaugeMetric.for(metric_name, count_of_packages, package_tags)
68
44
  end
69
45
  end
70
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['strictly_enforce_dependencies']
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['strictly_enforce_privacy']
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/TypedPublicApi',
123
+ 'PackageProtections/NamespacedUnderPackageName' => 'Packs/NamespaceConvention',
124
+ 'PackageProtections/OnlyClassMethods' => 'Packs/ClassMethodsAsPublicApis',
125
+ 'PackageProtections/RequireDocumentedPublicApis' => 'Packs/RequireDocumentedPublicApis',
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
71
146
  end
72
147
  end
73
148
  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.38.0
4
+ version: 1.39.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-10-26 00:00:00.000000000 Z
11
+ date: 2022-11-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: code_teams