codemonitor 0.3.1 → 0.3.5

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: e7aff9a4482c1d98c0f2fb183509ce2c4570f3a9fd2a7bc5285fd242f002138a
4
- data.tar.gz: 458f94d6c2292633fbf06921f34606bb8c6f12390cb26d92ebcb9e4d7c29d9fe
3
+ metadata.gz: 54b2ce0b7c2997591225e5e7487433854b3fff767e3272b3d02210de337253cf
4
+ data.tar.gz: aa9a60e54480ec4602ec108f45b84323aa04aa46f3df622a4db2a303cb1e6ec3
5
5
  SHA512:
6
- metadata.gz: 23c3463de88a3926c3fbad214ba337fec330616f7f32e5c10218ffecef5ba0670af391c54b53c3888efb7806524e1f9df9ab8bc2dc536d07dd69862c30fd0f91
7
- data.tar.gz: 968f1343c883be353a5ecc08dcb5bf878573661f6bfaf6d52aea823b6eedd7b2098e8dce7ff42146a3566edfb759e7156b2bb02f764e9cdcc832d493c6842ca0
6
+ metadata.gz: 47fb68d254802463f047d96ef409b111ee3f65c6e007a74122bb90151a4e4d457ed2b7b3c4e2bb6da0cc7da45284a933a43167714b39d7d6ebe291f68e8a1822
7
+ data.tar.gz: 2a466e51f3cd2e5936600680068af4bdb0ee717e9fcbfcc657394d08640f2b00799e2f82a3f183093bd6e1e8c0ee286c2948b3f5f777b5eb8e2e45fd464d4fcf
data/Gemfile CHANGED
@@ -2,5 +2,5 @@
2
2
 
3
3
  source 'https://rubygems.org'
4
4
 
5
- # Specify your gem's dependencies in rubocop-changes.gemspec
5
+ # Specify your gem's dependencies in codemonitor.gemspec
6
6
  gemspec
data/README.md CHANGED
@@ -1,9 +1,120 @@
1
- # CodeMonitor
1
+ # 🖥️ CodeMonitor
2
2
 
3
3
  A engine to collect multiple metrics from your repository and push them to a
4
4
  time series provider.
5
5
 
6
6
 
7
- # Inspiration
7
+ # Engines
8
8
 
9
- https://github.com/scribd/github-action-datadog-reporting
9
+ ## Git
10
+
11
+ Collect multiple metrics from the a Git repository.
12
+
13
+ **Requirements / Setup**:
14
+
15
+ You need a `.git` folder present in the current folder:
16
+
17
+ **Options**:
18
+
19
+ `CODEMONITOR_GIT_FILES_THRESHOLD`: Don't emit metrics about number of files, from those that are above of this threshold. (Default: `0`)
20
+
21
+ ## Eslint
22
+
23
+ Collect multiple metrics from the a project with [Eslint](https://eslint.org/) configured.
24
+
25
+ **Requirements / Setup**:
26
+
27
+ You need a `.eslintrc.js` and a `eslint.output.json` file present in the current folder.
28
+
29
+ You can generate the `eslint.output.json` file with this example command:
30
+
31
+ ```
32
+ eslint -f json -o eslint.output.json
33
+ ```
34
+ **Options**:
35
+
36
+ `CODEMONITOR_ESLINT_THRESHOLD`: Don't emit metrics about eslint rules that are above of this threshold. (Default: `10`)
37
+
38
+
39
+ ## Npm
40
+
41
+ Collect multiple metrics from the a NodeJS.
42
+
43
+ **Requirements / Setup**:
44
+
45
+ You need a `package.json` file present in the current folder.
46
+
47
+ ## Packwerk
48
+
49
+ Collect multiple metrics from the a Ruby project with [Packwerk](https://github.com/Shopify/packwerk) configured.
50
+
51
+ **Requirements / Setup**:
52
+
53
+ You need a `deprecated_references.yml` files present in the current project.
54
+
55
+ ## Rubocop
56
+
57
+ Collect multiple metrics from the a Ruby project with [Rubocop](https://github.com/rubocop/rubocop) configured.
58
+
59
+ **Requirements / Setup**:
60
+
61
+ You need a `.rubocop.yml` and a `rubocop.output.json` file present in the current folder.
62
+
63
+ You can generate the `rubocop.output.json` file with this example command:
64
+
65
+ ```
66
+ bundle exec srb tc --metrics-prefix 'codemetrics' --metrics-file sorbet.output.json
67
+ ```
68
+
69
+ **Options**:
70
+
71
+ `CODEMONITOR_RUBOCOP_THRESHOLD`: Don't emit metrics about rubocop cops that are above of this threshold. (Default: `50`)
72
+
73
+
74
+ ## Semgrep
75
+
76
+ Collect multiple metrics from the a with [Semgrep](https://semgrep.dev/) configured.
77
+
78
+ **Requirements / Setup**:
79
+
80
+ You need a `.semgrep.yml` and a `semgrep.output.json` file present in the current folder.
81
+
82
+ You can generate the `semgrep.output.json` file with this example command:
83
+
84
+ ```
85
+ semgrep --json -o semgrep.output.json
86
+ ```
87
+
88
+ **Options**:
89
+
90
+ `CODEMONITOR_SEMGREP_THRESHOLD`: Don't emit metrics about rubocop cops that are above of this threshold. (Default: `50`)
91
+
92
+ ## Sorbet
93
+
94
+ Collect multiple metrics from the a with [Sorbet](https://sorbet.org/) configured.
95
+
96
+ **Requirements / Setup**:
97
+
98
+ You need a `sorbet.output.json` file present in the current folder.
99
+
100
+ You can generate the `sorbet.output.json` file with this example command:
101
+
102
+ ```
103
+ bundle exec srb tc --metrics-prefix 'codemetrics' --metrics-file sorbet.output.json
104
+ ```
105
+
106
+ # Providers
107
+
108
+ ## Console
109
+
110
+ TODO
111
+
112
+ ## Datadog
113
+
114
+ TODO
115
+
116
+ # Contribute
117
+
118
+ This project started as a side project, so I'm sure that is full
119
+ of mistakes and areas to be improve. If you think you can tweak the code to
120
+ make it better, I'll really appreciate a pull request. ;)
data/codemonitor.gemspec CHANGED
@@ -37,6 +37,7 @@ Gem::Specification.new do |spec|
37
37
  spec.require_paths = ['lib']
38
38
 
39
39
  spec.add_runtime_dependency 'dogapi', '~> 1.45'
40
+ spec.add_runtime_dependency 'octokit', '~> 4.0'
40
41
 
41
42
  spec.add_development_dependency 'bundler', '~> 2.0'
42
43
  spec.add_development_dependency 'pry', '~> 0.13.1'
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Engines
4
+ module Custom
5
+ class Extractor
6
+ def call(provider)
7
+ return unless requirements?
8
+
9
+ provider.emit(metrics)
10
+ end
11
+
12
+ private
13
+
14
+ def requirements?
15
+ custom_files.length.positive?
16
+ end
17
+
18
+ def custom_files
19
+ Dir.glob('./.codemonitor/*.rb')
20
+ end
21
+
22
+ def metrics
23
+ custom_files.map do |file|
24
+ values = begin
25
+ eval File.read(file)
26
+ rescue SyntaxError => e
27
+ raise "Unable to execute the custom codemonitor script `#{file}` file"
28
+ end
29
+
30
+ raise "Malformed return value from `#{file}` file. It must be a hash of metrics" unless values.is_a?(Hash)
31
+
32
+ values
33
+ end.reduce({}, :merge)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'octokit'
4
+ require 'date'
5
+
6
+ Octokit.configure do |c|
7
+ c.auto_paginate = true
8
+ end
9
+
10
+ module Engines
11
+ module Github
12
+ class Extractor
13
+ METRICS = %i[
14
+ github_number_of_open_pull_requests
15
+ github_number_of_lead_time_in_days
16
+ ].freeze
17
+
18
+ def initialize
19
+ @access_token = ENV['GITHUB_TOKEN']
20
+ @repository = ENV['GITHUB_REPOSITORY']
21
+ @since_days = ENV['GITHUB_SINCE_DAYS'] || 30
22
+ end
23
+
24
+ def call(provider)
25
+ return unless requirements?
26
+
27
+ metrics = METRICS.map do |metric|
28
+ [metric, send(metric)]
29
+ end.to_h
30
+
31
+ provider.emit(metrics)
32
+ end
33
+
34
+ private
35
+
36
+ attr_reader :access_token, :repository, :since_days
37
+
38
+ def github
39
+ @github ||= Octokit::Client.new(access_token: access_token)
40
+ end
41
+
42
+ def requirements?
43
+ !access_token.nil? && !repository.nil?
44
+ end
45
+
46
+ def since
47
+ (Date.today - since_days).to_time.iso8601
48
+ end
49
+
50
+ def github_number_of_open_pull_requests
51
+ github.issues(repository, state: 'open').length
52
+ end
53
+
54
+ def github_number_of_lead_time_in_days
55
+ diffs = github
56
+ .issues(repository, since: since, state: 'closed')
57
+ .map do |issue|
58
+ next nil if issue[:pull_request][:merged_at].nil? || issue[:created_at].nil?
59
+
60
+ merged_at = Time.at(issue[:pull_request][:merged_at])
61
+ created_at = Time.at(issue[:created_at])
62
+
63
+ merged_at - created_at
64
+ end.reject do |diff|
65
+ diff.nil?
66
+ end
67
+
68
+ value = (diffs.reduce(:+) / diffs.size.to_f / (24 * 60 * 60))
69
+
70
+ value.round(2)
71
+ end
72
+ end
73
+ end
74
+ end
data/exe/codemonitor CHANGED
@@ -7,11 +7,13 @@ require_relative '../providers/datadog'
7
7
  require_relative '../engines/eslint/extractor'
8
8
  require_relative '../engines/debug/extractor'
9
9
  require_relative '../engines/git/extractor'
10
+ require_relative '../engines/github/extractor'
10
11
  require_relative '../engines/npm/extractor'
11
12
  require_relative '../engines/packwerk/extractor'
12
13
  require_relative '../engines/rubocop/extractor'
13
14
  require_relative '../engines/semgrep/extractor'
14
15
  require_relative '../engines/sorbet/extractor'
16
+ require_relative '../engines/custom/extractor'
15
17
 
16
18
  PROVIDERS = {
17
19
  console: Providers::Console,
@@ -22,11 +24,13 @@ EXTRACTORS = {
22
24
  eslint: Engines::Eslint::Extractor,
23
25
  debug: Engines::Debug::Extractor,
24
26
  git: Engines::Git::Extractor,
27
+ github: Engines::Github::Extractor,
25
28
  npm: Engines::Npm::Extractor,
26
29
  packwerk: Engines::Packwerk::Extractor,
27
30
  rubocop: Engines::Rubocop::Extractor,
28
31
  semgrep: Engines::Semgrep::Extractor,
29
- sorbet: Engines::Sorbet::Extractor
32
+ sorbet: Engines::Sorbet::Extractor,
33
+ custom: Engines::Custom::Extractor
30
34
  }.freeze
31
35
 
32
36
  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.3.1'
4
+ VERSION = '0.3.5'
5
5
  end
data/providers/datadog.rb CHANGED
@@ -17,7 +17,7 @@ module Providers
17
17
  def send
18
18
  datadog_client.batch_metrics do
19
19
  pending.each do |metric, value|
20
- metric = metric_prefix + metric
20
+ metric = "#{metric_prefix}#{metric}"
21
21
  puts "#{metric}: #{value}"
22
22
  datadog_client.emit_point(metric, value, type: 'gauge')
23
23
  end
@@ -26,6 +26,6 @@ module Providers
26
26
 
27
27
  private
28
28
 
29
- attr_reader :pending, :datadog_client
29
+ attr_reader :pending, :metric_prefix, :datadog_client
30
30
  end
31
31
  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.3.1
4
+ version: 0.3.5
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-30 00:00:00.000000000 Z
11
+ date: 2022-01-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dogapi
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.45'
27
+ - !ruby/object:Gem::Dependency
28
+ name: octokit
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '4.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '4.0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -115,9 +129,11 @@ files:
115
129
  - bin/console
116
130
  - bin/setup
117
131
  - codemonitor.gemspec
132
+ - engines/custom/extractor.rb
118
133
  - engines/debug/extractor.rb
119
134
  - engines/eslint/extractor.rb
120
135
  - engines/git/extractor.rb
136
+ - engines/github/extractor.rb
121
137
  - engines/npm/extractor.rb
122
138
  - engines/packwerk/extractor.rb
123
139
  - engines/rubocop/extractor.rb