modularization_statistics 1.43.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/modularization_statistics/private/metrics/packages.rb +0 -3
- data/lib/modularization_statistics/private/metrics/packages_by_team.rb +0 -4
- data/lib/modularization_statistics/private/metrics/packwerk_checker_usage.rb +9 -14
- data/lib/modularization_statistics/private/metrics/rubocop_usage.rb +23 -19
- data/lib/modularization_statistics/private.rb +46 -0
- data/lib/modularization_statistics.rb +27 -6
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8b92e63167f36749496d05a0aa09565ffa6fae7eedb473064ad4221eb3d42873
|
4
|
+
data.tar.gz: 6be0f2e6944809a2e3f1b049b026803735ae89db8f68021c48aa1829033af8fb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5c1c13787806460d19f695a6ef9ebec30a103f50dac6e47b262c8951b6f74de7c83ca57675a7f2c0fb0826ea1d4ac5c3a21fb3b74bb0fd940e73e6a13edacf74
|
7
|
+
data.tar.gz: 18e04253d74957dac478b8a886c74bfdf969c61e70f07b6980d9e807b6be69b591221d8671e1fb3620c571e6c462b07c833407142d0aaa365718332d286a7563
|
@@ -25,9 +25,6 @@ module ModularizationStatistics
|
|
25
25
|
all_metrics << GaugeMetric.for('all_packages.enforcing_dependencies.count', packages.count(&:enforces_dependencies?), package_tags)
|
26
26
|
all_metrics << GaugeMetric.for('all_packages.enforcing_privacy.count', packages.count(&:enforces_privacy?), package_tags)
|
27
27
|
|
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)
|
29
|
-
all_metrics << GaugeMetric.for('all_packages.notify_on_new_violations.count', packages.count { |p| p.metadata['notify_on_new_violations'] }, package_tags)
|
30
|
-
|
31
28
|
all_metrics << GaugeMetric.for('all_packages.with_violations.count', packages.count { |package| package.violations.any? }, package_tags)
|
32
29
|
all_metrics += Metrics::PublicUsage.get_public_usage_metrics('all_packages', packages, package_tags)
|
33
30
|
all_metrics << GaugeMetric.for('all_packages.has_readme.count', packages.count { |package| Metrics.has_readme?(package) }, package_tags)
|
@@ -25,10 +25,6 @@ module ModularizationStatistics
|
|
25
25
|
all_metrics << GaugeMetric.for('by_team.all_packages.count', packages_by_team.count, team_tags)
|
26
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
|
-
|
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
|
-
|
32
28
|
#
|
33
29
|
# VIOLATIONS (implicit dependencies)
|
34
30
|
#
|
@@ -13,11 +13,6 @@ module ModularizationStatistics
|
|
13
13
|
class PackwerkChecker < T::Struct
|
14
14
|
const :setting, String
|
15
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
16
|
end
|
22
17
|
|
23
18
|
sig { params(prefix: String, packages: T::Array[ParsePackwerk::Package], package_tags: T::Array[Tag]).returns(T::Array[GaugeMetric]) }
|
@@ -25,26 +20,26 @@ module ModularizationStatistics
|
|
25
20
|
metrics = T.let([], T::Array[GaugeMetric])
|
26
21
|
|
27
22
|
checkers = [
|
28
|
-
PackwerkChecker.new(setting: 'enforce_dependencies', strict_mode: 'enforce_dependencies_strictly'
|
29
|
-
PackwerkChecker.new(setting: 'enforce_privacy', strict_mode: 'enforce_privacy_strictly'
|
23
|
+
PackwerkChecker.new(setting: 'enforce_dependencies', strict_mode: 'enforce_dependencies_strictly'),
|
24
|
+
PackwerkChecker.new(setting: 'enforce_privacy', strict_mode: 'enforce_privacy_strictly')
|
30
25
|
]
|
31
26
|
|
32
27
|
checkers.each do |checker|
|
33
|
-
['
|
28
|
+
['false', 'true', 'strict'].each do |enabled_mode|
|
34
29
|
count_of_packages = ParsePackwerk.all.count do |package|
|
35
30
|
strict_mode = package.metadata[checker.strict_mode]
|
36
31
|
enabled = YAML.load_file(package.yml)[checker.setting]
|
37
|
-
case
|
38
|
-
when '
|
39
|
-
!!strict_mode
|
40
|
-
when 'no'
|
32
|
+
case enabled_mode
|
33
|
+
when 'false'
|
41
34
|
!enabled
|
42
|
-
when '
|
35
|
+
when 'true'
|
43
36
|
enabled && !strict_mode
|
37
|
+
when 'strict'
|
38
|
+
!!strict_mode
|
44
39
|
end
|
45
40
|
end
|
46
41
|
|
47
|
-
metric_name = "#{prefix}.#{checker.
|
42
|
+
metric_name = "#{prefix}.packwerk_checkers.#{checker.setting}.#{enabled_mode}.count"
|
48
43
|
metrics << GaugeMetric.for(metric_name, count_of_packages, package_tags)
|
49
44
|
end
|
50
45
|
end
|
@@ -17,11 +17,10 @@ module ModularizationStatistics
|
|
17
17
|
|
18
18
|
sig { params(prefix: String, packages: T::Array[ParsePackwerk::Package], package_tags: T::Array[Tag]).returns(T::Array[GaugeMetric]) }
|
19
19
|
def self.get_rubocop_usage_metrics(prefix, packages, package_tags)
|
20
|
-
# Rubocops
|
21
20
|
metrics = T.let([], T::Array[GaugeMetric])
|
22
21
|
|
23
|
-
|
24
|
-
['
|
22
|
+
rubocops.each do |cop_name|
|
23
|
+
['false', 'true', 'strict'].each do |enabled_mode|
|
25
24
|
count_of_packages = ParsePackwerk.all.count do |package|
|
26
25
|
# We will likely want a rubocop-packs API for this, to be able to ask if a cop is enabled for a pack.
|
27
26
|
# It's possible we will want to allow these to be enabled at the top-level `.rubocop.yml`,
|
@@ -34,17 +33,17 @@ module ModularizationStatistics
|
|
34
33
|
|
35
34
|
strict_mode = cop_config && cop_config['FailureMode'] == 'strict'
|
36
35
|
enabled = cop_config && cop_config['Enabled']
|
37
|
-
case
|
38
|
-
when '
|
39
|
-
!!strict_mode
|
40
|
-
when 'no'
|
36
|
+
case enabled_mode
|
37
|
+
when 'false'
|
41
38
|
!enabled
|
42
|
-
when '
|
39
|
+
when 'true'
|
43
40
|
enabled && !strict_mode
|
41
|
+
when 'strict'
|
42
|
+
!!strict_mode
|
44
43
|
end
|
45
44
|
end
|
46
45
|
|
47
|
-
metric_name = "#{prefix}.#{
|
46
|
+
metric_name = "#{prefix}.rubocops.#{to_tag_name(cop_name)}.#{enabled_mode}.count"
|
48
47
|
metrics << GaugeMetric.for(metric_name, count_of_packages, package_tags)
|
49
48
|
end
|
50
49
|
end
|
@@ -54,8 +53,8 @@ module ModularizationStatistics
|
|
54
53
|
|
55
54
|
sig { params(prefix: String, packages: T::Array[ParsePackwerk::Package], package_tags: T::Array[Tag]).returns(T::Array[GaugeMetric]) }
|
56
55
|
def self.get_rubocop_exclusions(prefix, packages, package_tags)
|
57
|
-
|
58
|
-
metric_name = "#{prefix}.#{
|
56
|
+
rubocops.flat_map do |cop_name|
|
57
|
+
metric_name = "#{prefix}.rubocops.#{to_tag_name(cop_name)}.exclusions.count"
|
59
58
|
all_exclusions_count = ParsePackwerk.all.sum { |package| exclude_count_for_package_and_protection(package, cop_name)}
|
60
59
|
GaugeMetric.for(metric_name, all_exclusions_count, package_tags)
|
61
60
|
end
|
@@ -79,14 +78,19 @@ module ModularizationStatistics
|
|
79
78
|
end
|
80
79
|
end
|
81
80
|
|
82
|
-
sig { returns(T::
|
83
|
-
def self.
|
84
|
-
|
85
|
-
'Packs/ClassMethodsAsPublicApis'
|
86
|
-
'Packs/RootNamespaceIsPackName'
|
87
|
-
'Packs/TypedPublicApis'
|
88
|
-
'Packs/DocumentedPublicApis'
|
89
|
-
|
81
|
+
sig { returns(T::Array[String])}
|
82
|
+
def self.rubocops
|
83
|
+
[
|
84
|
+
'Packs/ClassMethodsAsPublicApis',
|
85
|
+
'Packs/RootNamespaceIsPackName',
|
86
|
+
'Packs/TypedPublicApis',
|
87
|
+
'Packs/DocumentedPublicApis',
|
88
|
+
]
|
89
|
+
end
|
90
|
+
|
91
|
+
sig { params(cop_name: String).returns(String) }
|
92
|
+
def self.to_tag_name(cop_name)
|
93
|
+
cop_name.gsub('/', '_').downcase
|
90
94
|
end
|
91
95
|
end
|
92
96
|
end
|
@@ -2,6 +2,52 @@
|
|
2
2
|
|
3
3
|
module ModularizationStatistics
|
4
4
|
module Private
|
5
|
+
extend T::Sig
|
6
|
+
|
7
|
+
METRIC_REPLACEMENTS = T.let({
|
8
|
+
# enforce_dependencies
|
9
|
+
'packwerk_checkers.enforce_dependencies.false' => 'prevent_this_package_from_violating_its_stated_dependencies.no',
|
10
|
+
'packwerk_checkers.enforce_dependencies.true' => 'prevent_this_package_from_violating_its_stated_dependencies.fail_the_build_if_new_instances_appear',
|
11
|
+
'packwerk_checkers.enforce_dependencies.strict' => 'prevent_this_package_from_violating_its_stated_dependencies.fail_the_build_on_any_instances',
|
12
|
+
# enforce_privacy
|
13
|
+
'packwerk_checkers.enforce_privacy.false' => 'prevent_other_packages_from_using_this_packages_internals.no',
|
14
|
+
'packwerk_checkers.enforce_privacy.true' => 'prevent_other_packages_from_using_this_packages_internals.fail_the_build_if_new_instances_appear',
|
15
|
+
'packwerk_checkers.enforce_privacy.strict' => 'prevent_other_packages_from_using_this_packages_internals.fail_the_build_on_any_instances',
|
16
|
+
# Packs/TypedPublicApis
|
17
|
+
'rubocops.packs_typedpublicapis.false' => 'prevent_this_package_from_exposing_an_untyped_api.no',
|
18
|
+
'rubocops.packs_typedpublicapis.true' => 'prevent_this_package_from_exposing_an_untyped_api.fail_the_build_if_new_instances_appear',
|
19
|
+
'rubocops.packs_typedpublicapis.strict' => 'prevent_this_package_from_exposing_an_untyped_api.fail_the_build_on_any_instances',
|
20
|
+
'rubocops.packs_typedpublicapis.exclusions' => 'prevent_this_package_from_exposing_an_untyped_api.rubocop_exclusions',
|
21
|
+
# Packs/RootNamespaceIsPackName
|
22
|
+
'rubocops.packs_rootnamespaceispackname.false' => 'prevent_this_package_from_creating_other_namespaces.no',
|
23
|
+
'rubocops.packs_rootnamespaceispackname.true' => 'prevent_this_package_from_creating_other_namespaces.fail_the_build_if_new_instances_appear',
|
24
|
+
'rubocops.packs_rootnamespaceispackname.strict' => 'prevent_this_package_from_creating_other_namespaces.fail_the_build_on_any_instances',
|
25
|
+
'rubocops.packs_rootnamespaceispackname.exclusions' => 'prevent_this_package_from_creating_other_namespaces.rubocop_exclusions',
|
26
|
+
# Packs/ClassMethodsAsPublicApis
|
27
|
+
'rubocops.packs_classmethodsaspublicapis.false' => 'prevent_this_package_from_exposing_instance_method_public_apis.no',
|
28
|
+
'rubocops.packs_classmethodsaspublicapis.true' => 'prevent_this_package_from_exposing_instance_method_public_apis.fail_the_build_if_new_instances_appear',
|
29
|
+
'rubocops.packs_classmethodsaspublicapis.strict' => 'prevent_this_package_from_exposing_instance_method_public_apis.fail_the_build_on_any_instances',
|
30
|
+
'rubocops.packs_classmethodsaspublicapis.exclusions' => 'prevent_this_package_from_exposing_instance_method_public_apis.rubocop_exclusions',
|
31
|
+
# Packs/DocumentedPublicApis
|
32
|
+
'rubocops.packs_documentedpublicapis.false' => 'prevent_this_package_from_exposing_undocumented_public_apis.no',
|
33
|
+
'rubocops.packs_documentedpublicapis.true' => 'prevent_this_package_from_exposing_undocumented_public_apis.fail_the_build_if_new_instances_appear',
|
34
|
+
'rubocops.packs_documentedpublicapis.strict' => 'prevent_this_package_from_exposing_undocumented_public_apis.fail_the_build_on_any_instances',
|
35
|
+
'rubocops.packs_documentedpublicapis.exclusions' => 'prevent_this_package_from_exposing_undocumented_public_apis.rubocop_exclusions',
|
36
|
+
}, T::Hash[String, String])
|
37
|
+
|
38
|
+
sig { params(metrics: T::Array[GaugeMetric]).returns(T::Array[GaugeMetric]) }
|
39
|
+
def self.convert_metrics_to_legacy(metrics)
|
40
|
+
metrics.map do |metric|
|
41
|
+
new_metric = metric
|
42
|
+
METRIC_REPLACEMENTS.each do |current_name, legacy_name|
|
43
|
+
new_metric = new_metric.with(
|
44
|
+
name: new_metric.name.gsub(current_name, legacy_name)
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
new_metric
|
49
|
+
end
|
50
|
+
end
|
5
51
|
end
|
6
52
|
|
7
53
|
private_constant :Private
|
@@ -7,6 +7,7 @@ require 'benchmark'
|
|
7
7
|
require 'code_teams'
|
8
8
|
require 'code_ownership'
|
9
9
|
require 'pathname'
|
10
|
+
require 'modularization_statistics/private'
|
10
11
|
require 'modularization_statistics/private/source_code_file'
|
11
12
|
require 'modularization_statistics/private/datadog_reporter'
|
12
13
|
require 'parse_packwerk'
|
@@ -41,7 +42,9 @@ module ModularizationStatistics
|
|
41
42
|
componentized_source_code_locations: T::Array[Pathname],
|
42
43
|
packaged_source_code_locations: T::Array[Pathname],
|
43
44
|
report_time: Time,
|
44
|
-
verbose: T::Boolean
|
45
|
+
verbose: T::Boolean,
|
46
|
+
# See note on get_metrics
|
47
|
+
use_gusto_legacy_names: T::Boolean
|
45
48
|
).void
|
46
49
|
end
|
47
50
|
def self.report_to_datadog!(
|
@@ -51,14 +54,16 @@ module ModularizationStatistics
|
|
51
54
|
componentized_source_code_locations: DEFAULT_COMPONENTIZED_SOURCE_CODE_LOCATIONS,
|
52
55
|
packaged_source_code_locations: DEFAULT_PACKAGED_SOURCE_CODE_LOCATIONS,
|
53
56
|
report_time: Time.now, # rubocop:disable Rails/TimeZone
|
54
|
-
verbose: false
|
57
|
+
verbose: false,
|
58
|
+
use_gusto_legacy_names: false
|
55
59
|
)
|
56
60
|
|
57
61
|
all_metrics = self.get_metrics(
|
58
62
|
source_code_pathnames: source_code_pathnames,
|
59
63
|
componentized_source_code_locations: componentized_source_code_locations,
|
60
64
|
packaged_source_code_locations: packaged_source_code_locations,
|
61
|
-
app_name: app_name
|
65
|
+
app_name: app_name,
|
66
|
+
use_gusto_legacy_names: use_gusto_legacy_names,
|
62
67
|
)
|
63
68
|
|
64
69
|
# This helps us debug what metrics are being sent
|
@@ -68,6 +73,10 @@ module ModularizationStatistics
|
|
68
73
|
end
|
69
74
|
end
|
70
75
|
|
76
|
+
if use_gusto_legacy_names
|
77
|
+
all_metrics = Private.convert_metrics_to_legacy(all_metrics)
|
78
|
+
end
|
79
|
+
|
71
80
|
Private::DatadogReporter.report!(
|
72
81
|
datadog_client: datadog_client,
|
73
82
|
report_time: report_time,
|
@@ -80,16 +89,22 @@ module ModularizationStatistics
|
|
80
89
|
source_code_pathnames: T::Array[Pathname],
|
81
90
|
componentized_source_code_locations: T::Array[Pathname],
|
82
91
|
packaged_source_code_locations: T::Array[Pathname],
|
83
|
-
app_name: String
|
92
|
+
app_name: String,
|
93
|
+
# It is not recommended to set this to true.
|
94
|
+
# Gusto uses this to preserve historical trends in Dashboards as the names of
|
95
|
+
# things changed, but new dashboards can use names that better match current tooling conventions.
|
96
|
+
# The behavior of setting this parameter to true might change without warning
|
97
|
+
use_gusto_legacy_names: T::Boolean
|
84
98
|
).returns(T::Array[GaugeMetric])
|
85
99
|
end
|
86
100
|
def self.get_metrics(
|
87
101
|
source_code_pathnames:,
|
88
102
|
componentized_source_code_locations:,
|
89
103
|
packaged_source_code_locations:,
|
90
|
-
app_name
|
104
|
+
app_name:,
|
105
|
+
use_gusto_legacy_names: false
|
91
106
|
)
|
92
|
-
Private::DatadogReporter.get_metrics(
|
107
|
+
all_metrics = Private::DatadogReporter.get_metrics(
|
93
108
|
source_code_files: source_code_files(
|
94
109
|
source_code_pathnames: source_code_pathnames,
|
95
110
|
componentized_source_code_locations: componentized_source_code_locations,
|
@@ -97,6 +112,12 @@ module ModularizationStatistics
|
|
97
112
|
),
|
98
113
|
app_name: app_name
|
99
114
|
)
|
115
|
+
|
116
|
+
if use_gusto_legacy_names
|
117
|
+
all_metrics = Private.convert_metrics_to_legacy(all_metrics)
|
118
|
+
end
|
119
|
+
|
120
|
+
all_metrics
|
100
121
|
end
|
101
122
|
|
102
123
|
sig do
|