codemonitor 0.2.0 → 0.3.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: 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