codemonitor 0.2.0 → 0.3.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 +4 -4
- data/.rubocop.yml +3 -0
- data/Gemfile +3 -1
- data/Gemfile.lock +1 -1
- data/bin/console +4 -3
- data/codemonitor.gemspec +4 -2
- data/engines/eslint/extractor.rb +100 -0
- data/engines/packwerk/extractor.rb +64 -0
- data/engines/sorbet/extractor.rb +110 -0
- data/exe/codemonitor +8 -2
- data/lib/codemonitor/version.rb +1 -1
- metadata +14 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bf55eb8d37288cec3ce8e828f6705c552d78707084648062b303a75bc7d0a063
|
4
|
+
data.tar.gz: 40a0b1d17eeb986534b812f2668a79eeee4ecf2fb21ec40fe1a672dce8b61a34
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7fd6aad0e254c9e0efebff094266fa4528bd640a1671a26c8523d86daf4944c72e8116f55bbb87d74bf5f194ada216624f28a3d0de10d962541f768e8c720344
|
7
|
+
data.tar.gz: 38ae84cbcb7888349e1309d6f0008dd62f6c537818ba93197abbf40eed406222c6bad00e990c193f4d6dcc569038bb81011fe4570b8051ea09a98587d7c3a99a
|
data/.rubocop.yml
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
data/bin/console
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
|
-
require
|
4
|
-
require
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'rubocop/changes'
|
5
6
|
|
6
7
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
8
|
# with your gem easier. You can also use a different console, if you like.
|
@@ -10,5 +11,5 @@ require "rubocop/changes"
|
|
10
11
|
# require "pry"
|
11
12
|
# Pry.start
|
12
13
|
|
13
|
-
require
|
14
|
+
require 'irb'
|
14
15
|
IRB.start(__FILE__)
|
data/codemonitor.gemspec
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
lib = File.expand_path('lib', __dir__)
|
2
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
5
|
require 'codemonitor/version'
|
@@ -26,7 +28,7 @@ Gem::Specification.new do |spec|
|
|
26
28
|
# Specify which files should be added to the gem when it is released.
|
27
29
|
# The `git ls-files -z` loads the files in the RubyGem that have been added
|
28
30
|
# into git.
|
29
|
-
spec.files = Dir.chdir(File.expand_path(
|
31
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
30
32
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
31
33
|
end
|
32
34
|
spec.bindir = 'exe'
|
@@ -37,8 +39,8 @@ Gem::Specification.new do |spec|
|
|
37
39
|
spec.add_runtime_dependency 'dogapi', '~> 1.45'
|
38
40
|
|
39
41
|
spec.add_development_dependency 'bundler', '~> 2.0'
|
42
|
+
spec.add_development_dependency 'pry', '~> 0.13.1'
|
40
43
|
spec.add_development_dependency 'rake', '~> 13.0'
|
41
44
|
spec.add_development_dependency 'rspec', '~> 3.9'
|
42
|
-
spec.add_development_dependency 'pry', '~> 0.13.1'
|
43
45
|
spec.add_development_dependency 'rubocop', '~> 0.80'
|
44
46
|
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Engines
|
6
|
+
module Eslint
|
7
|
+
class Extractor
|
8
|
+
METRICS = %i[
|
9
|
+
eslint_number_of_offended_files
|
10
|
+
eslint_number_of_offenses
|
11
|
+
eslint_number_of_correctable
|
12
|
+
].freeze
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@threshold = ENV.fetch('CODEMONITOR_ESLINT_THRESHOLD', '10').to_i
|
16
|
+
end
|
17
|
+
|
18
|
+
def call(provider)
|
19
|
+
return unless requirements?
|
20
|
+
|
21
|
+
metrics = METRICS.map do |metric|
|
22
|
+
[metric, send(metric)]
|
23
|
+
end.to_h
|
24
|
+
|
25
|
+
metrics
|
26
|
+
.merge!(eslint_by_severity)
|
27
|
+
.merge!(eslint_by_rule)
|
28
|
+
|
29
|
+
provider.emit(metrics)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
attr_reader :threshold
|
35
|
+
|
36
|
+
def requirements?
|
37
|
+
# FIXME: Review if this is the only check we can do or there are more.
|
38
|
+
File.exist?('.eslintrc.js')
|
39
|
+
end
|
40
|
+
|
41
|
+
# NOTE: This output file must be created by an external command
|
42
|
+
def eslint
|
43
|
+
@eslint ||= JSON.parse(File.read('eslint.output.json'))
|
44
|
+
end
|
45
|
+
|
46
|
+
def eslint_files
|
47
|
+
eslint
|
48
|
+
end
|
49
|
+
|
50
|
+
def eslint_number_of_offended_files
|
51
|
+
eslint_files.length
|
52
|
+
end
|
53
|
+
|
54
|
+
def eslint_offenses
|
55
|
+
eslint_files
|
56
|
+
.map { |offense| offense['messages'] }
|
57
|
+
.flatten
|
58
|
+
end
|
59
|
+
|
60
|
+
def eslint_number_of_offenses
|
61
|
+
eslint_offenses.length
|
62
|
+
end
|
63
|
+
|
64
|
+
def eslint_number_of_correctable
|
65
|
+
eslint_offenses
|
66
|
+
.filter { |offense| offense['correctable'] }
|
67
|
+
.length
|
68
|
+
end
|
69
|
+
|
70
|
+
def eslint_by_severity
|
71
|
+
eslint_offenses
|
72
|
+
.each_with_object(Hash.new(0)) do |offense, total|
|
73
|
+
total[severity(offense['severity'])] += 1
|
74
|
+
end.map do |key, value|
|
75
|
+
["eslint_severity_#{key}", value]
|
76
|
+
end.to_h
|
77
|
+
end
|
78
|
+
|
79
|
+
def eslint_by_rule
|
80
|
+
eslint_offenses
|
81
|
+
.each_with_object(Hash.new(0)) do |offense, total|
|
82
|
+
total[offense['ruleId']] += 1
|
83
|
+
end.map do |key, value|
|
84
|
+
["eslint_rule_#{clean(key)}", value] if value >= threshold
|
85
|
+
end.compact.to_h
|
86
|
+
end
|
87
|
+
|
88
|
+
def clean(key)
|
89
|
+
key.gsub(%r{[-,./ ]}, '_').downcase
|
90
|
+
end
|
91
|
+
|
92
|
+
def severity(value)
|
93
|
+
return 'warning' if value == 1
|
94
|
+
return 'error' if value == 2
|
95
|
+
|
96
|
+
'unknown'
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module Engines
|
6
|
+
module Packwerk
|
7
|
+
class Extractor
|
8
|
+
METRICS = %i[
|
9
|
+
packwerk_number_of_dependency_violations
|
10
|
+
packwerk_number_of_privacy_violations
|
11
|
+
].freeze
|
12
|
+
|
13
|
+
def initialize; end
|
14
|
+
|
15
|
+
def call(provider)
|
16
|
+
return unless requirements?
|
17
|
+
|
18
|
+
metrics = METRICS.map do |metric|
|
19
|
+
[metric, send(metric)]
|
20
|
+
end.to_h
|
21
|
+
|
22
|
+
provider.emit(metrics)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def requirements?
|
28
|
+
packwerk_files.length.positive?
|
29
|
+
end
|
30
|
+
|
31
|
+
# NOTE: This output file must be created by an external command
|
32
|
+
def packwerk_files
|
33
|
+
Dir.glob('./**/deprecated_references.yml')
|
34
|
+
end
|
35
|
+
|
36
|
+
def packwerk_number_of_dependency_violations
|
37
|
+
packwerk_violations['dependency']
|
38
|
+
end
|
39
|
+
|
40
|
+
def packwerk_number_of_privacy_violations
|
41
|
+
packwerk_violations['privacy']
|
42
|
+
end
|
43
|
+
|
44
|
+
def packwerk_items
|
45
|
+
@packwerk_items ||= packwerk_files
|
46
|
+
.map { |file| YAML.load_file(file) }
|
47
|
+
.reduce({}, :merge)
|
48
|
+
.map { |_key, values| values }
|
49
|
+
.flatten
|
50
|
+
.reduce({}, :merge)
|
51
|
+
end
|
52
|
+
|
53
|
+
def packwerk_violations
|
54
|
+
packwerk_items
|
55
|
+
.values
|
56
|
+
.each_with_object(Hash.new(0)) do |offense, total|
|
57
|
+
offense['violations'].each do |violation|
|
58
|
+
total[violation] += 1
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Engines
|
6
|
+
module Sorbet
|
7
|
+
class Extractor
|
8
|
+
METRICS = %i[
|
9
|
+
sorbet_number_of_sig_count
|
10
|
+
sorbet_number_of_input_classes_total
|
11
|
+
sorbet_number_of_input_sends_total
|
12
|
+
sorbet_number_of_input_files
|
13
|
+
sorbet_number_of_input_methods_total
|
14
|
+
sorbet_number_of_input_modules_total
|
15
|
+
|
16
|
+
sorbet_number_of_sigil_true
|
17
|
+
sorbet_number_of_sigil_false
|
18
|
+
sorbet_number_of_sigil_autogenerated
|
19
|
+
sorbet_number_of_sigil_strong
|
20
|
+
sorbet_number_of_sigil_strict
|
21
|
+
sorbet_number_of_sigil_ignore
|
22
|
+
].freeze
|
23
|
+
|
24
|
+
def initialize; end
|
25
|
+
|
26
|
+
def call(provider)
|
27
|
+
return unless requirements?
|
28
|
+
|
29
|
+
metrics = METRICS.map do |metric|
|
30
|
+
[metric, send(metric)]
|
31
|
+
end.to_h
|
32
|
+
|
33
|
+
provider.emit(metrics)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def requirements?
|
39
|
+
File.exist?('sorbet.output.json')
|
40
|
+
end
|
41
|
+
|
42
|
+
# NOTE: This output file must be created by an external command
|
43
|
+
def sorbet
|
44
|
+
@sorbet ||= JSON.parse(File.read('sorbet.output.json'))
|
45
|
+
end
|
46
|
+
|
47
|
+
def sorbet_metrics
|
48
|
+
sorbet['metrics']
|
49
|
+
end
|
50
|
+
|
51
|
+
def find_metric(name, default = 0)
|
52
|
+
match = sorbet_metrics.find do |metric|
|
53
|
+
metric['name'] == name
|
54
|
+
end
|
55
|
+
|
56
|
+
return default if match.nil?
|
57
|
+
|
58
|
+
match['value']
|
59
|
+
end
|
60
|
+
|
61
|
+
def sorbet_number_of_sig_count
|
62
|
+
find_metric('codemetrics.types.sig.count')
|
63
|
+
end
|
64
|
+
|
65
|
+
def sorbet_number_of_input_classes_total
|
66
|
+
find_metric('codemetrics.types.input.classes.total')
|
67
|
+
end
|
68
|
+
|
69
|
+
def sorbet_number_of_input_sends_total
|
70
|
+
find_metric('codemetrics.types.input.sends.total')
|
71
|
+
end
|
72
|
+
|
73
|
+
def sorbet_number_of_input_files
|
74
|
+
find_metric('codemetrics.types.input.files')
|
75
|
+
end
|
76
|
+
|
77
|
+
def sorbet_number_of_input_methods_total
|
78
|
+
find_metric('codemetrics.types.input.methods.total')
|
79
|
+
end
|
80
|
+
|
81
|
+
def sorbet_number_of_input_modules_total
|
82
|
+
find_metric('codemetrics.types.input.modules.total')
|
83
|
+
end
|
84
|
+
|
85
|
+
def sorbet_number_of_sigil_true
|
86
|
+
find_metric('codemetrics.types.input.files.sigil.true')
|
87
|
+
end
|
88
|
+
|
89
|
+
def sorbet_number_of_sigil_false
|
90
|
+
find_metric('codemetrics.types.input.files.sigil.false')
|
91
|
+
end
|
92
|
+
|
93
|
+
def sorbet_number_of_sigil_autogenerated
|
94
|
+
find_metric('codemetrics.types.input.files.sigil.autogenerated')
|
95
|
+
end
|
96
|
+
|
97
|
+
def sorbet_number_of_sigil_strong
|
98
|
+
find_metric('codemetrics.types.input.files.sigil.strong')
|
99
|
+
end
|
100
|
+
|
101
|
+
def sorbet_number_of_sigil_strict
|
102
|
+
find_metric('codemetrics.types.input.files.sigil.strict')
|
103
|
+
end
|
104
|
+
|
105
|
+
def sorbet_number_of_sigil_ignore
|
106
|
+
find_metric('codemetrics.types.input.files.sigil.ignore')
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
data/exe/codemonitor
CHANGED
@@ -4,10 +4,13 @@
|
|
4
4
|
require_relative '../providers/console'
|
5
5
|
require_relative '../providers/datadog'
|
6
6
|
|
7
|
+
require_relative '../engines/eslint/extractor'
|
7
8
|
require_relative '../engines/git/extractor'
|
8
9
|
require_relative '../engines/npm/extractor'
|
9
|
-
require_relative '../engines/
|
10
|
+
require_relative '../engines/packwerk/extractor'
|
10
11
|
require_relative '../engines/rubocop/extractor'
|
12
|
+
require_relative '../engines/semgrep/extractor'
|
13
|
+
require_relative '../engines/sorbet/extractor'
|
11
14
|
|
12
15
|
PROVIDERS = {
|
13
16
|
console: Providers::Console,
|
@@ -15,10 +18,13 @@ PROVIDERS = {
|
|
15
18
|
}.freeze
|
16
19
|
|
17
20
|
EXTRACTORS = {
|
21
|
+
eslint: Engines::Eslint::Extractor,
|
18
22
|
git: Engines::Git::Extractor,
|
19
23
|
npm: Engines::Npm::Extractor,
|
24
|
+
packwerk: Engines::Packwerk::Extractor,
|
25
|
+
rubocop: Engines::Rubocop::Extractor,
|
20
26
|
semgrep: Engines::Semgrep::Extractor,
|
21
|
-
|
27
|
+
sorbet: Engines::Sorbet::Extractor
|
22
28
|
}.freeze
|
23
29
|
|
24
30
|
config_provider = ENV['CODEMONITOR_PROVIDER'] || 'console'
|
data/lib/codemonitor/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: codemonitor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ferran Basora
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-06-
|
11
|
+
date: 2021-06-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dogapi
|
@@ -39,47 +39,47 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '2.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: pry
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: 0.13.1
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: 0.13.1
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '13.0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '13.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: rspec
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
75
|
+
version: '3.9'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
82
|
+
version: '3.9'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: rubocop
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -115,10 +115,13 @@ files:
|
|
115
115
|
- bin/console
|
116
116
|
- bin/setup
|
117
117
|
- codemonitor.gemspec
|
118
|
+
- engines/eslint/extractor.rb
|
118
119
|
- engines/git/extractor.rb
|
119
120
|
- engines/npm/extractor.rb
|
121
|
+
- engines/packwerk/extractor.rb
|
120
122
|
- engines/rubocop/extractor.rb
|
121
123
|
- engines/semgrep/extractor.rb
|
124
|
+
- engines/sorbet/extractor.rb
|
122
125
|
- exe/codemonitor
|
123
126
|
- lib/codemonitor/version.rb
|
124
127
|
- lib/shell.rb
|