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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c4ade1a23e5ec1cdced5c02494d9e063cc985eea40b3957c3b7ad33f25117e59
4
- data.tar.gz: 305a91852cb860e83b8996a23e073dd5cab2e6d153b1456f2f2372fbce7eb4c6
3
+ metadata.gz: bf55eb8d37288cec3ce8e828f6705c552d78707084648062b303a75bc7d0a063
4
+ data.tar.gz: 40a0b1d17eeb986534b812f2668a79eeee4ecf2fb21ec40fe1a672dce8b61a34
5
5
  SHA512:
6
- metadata.gz: 90f5d6dd76eb3639d5c666c2fc9ef9d144450967276fe0f3d52880413aaf6cc20f6cf540b90a482b4db7a02876ebfa0abcef8fd94615f62280f5b3ec4f197f6f
7
- data.tar.gz: 9e2b4d97743d716c48da4878e3801e2f6fb155708d2ca3e6749af69a47ec4e1bf516063281388fe748b7fc46ad1762ea6c2ec1ec3f2031afd68d987bd8b21794
6
+ metadata.gz: 7fd6aad0e254c9e0efebff094266fa4528bd640a1671a26c8523d86daf4944c72e8116f55bbb87d74bf5f194ada216624f28a3d0de10d962541f768e8c720344
7
+ data.tar.gz: 38ae84cbcb7888349e1309d6f0008dd62f6c537818ba93197abbf40eed406222c6bad00e990c193f4d6dcc569038bb81011fe4570b8051ea09a98587d7c3a99a
data/.rubocop.yml CHANGED
@@ -1,3 +1,6 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.6
3
+
1
4
  Lint/RaiseException:
2
5
  Enabled: false
3
6
 
data/Gemfile CHANGED
@@ -1,4 +1,6 @@
1
- source "https://rubygems.org"
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in rubocop-changes.gemspec
4
6
  gemspec
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- codemonitor (0.1.0)
4
+ codemonitor (0.2.0)
5
5
  dogapi (~> 1.45)
6
6
 
7
7
  GEM
data/bin/console CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- require "bundler/setup"
4
- require "rubocop/changes"
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 "irb"
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('..', __FILE__)) do
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/semgrep/extractor'
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
- rubocop: Engines::Rubocop::Extractor
27
+ sorbet: Engines::Sorbet::Extractor
22
28
  }.freeze
23
29
 
24
30
  config_provider = ENV['CODEMONITOR_PROVIDER'] || 'console'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CodeMonitor
4
- VERSION = '0.2.0'
4
+ VERSION = '0.3.0'
5
5
  end
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.2.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-18 00:00:00.000000000 Z
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: rake
42
+ name: pry
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '13.0'
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: '13.0'
54
+ version: 0.13.1
55
55
  - !ruby/object:Gem::Dependency
56
- name: rspec
56
+ name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '3.9'
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: '3.9'
68
+ version: '13.0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: pry
70
+ name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 0.13.1
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: 0.13.1
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