quality_report 1.5.0 → 1.7.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: 23d2fbfb3f81887e40858181c9822346e770e8f242d96cfb39b8239b5288cb37
4
- data.tar.gz: f39b9f3ae08503660b79bcc0d286ae622d5e0aa5c06b056ef635a8af8def8576
3
+ metadata.gz: 51abac0022982e8c18d66396b580a4acadcbc14f86fd698f6e551e0d95cd304a
4
+ data.tar.gz: 8f4c5b26c6dd55268206ebe402642a88a287e5339d93a7dcd2532b11093e5564
5
5
  SHA512:
6
- metadata.gz: de5bfd72e7ea4b31e0bf57785ea38d5503624f0861adc660c1844848d32d839a90ecfb0ed6f5de1eabe13293846fd1771be45bb8f373725eabf6aed092fb50bf
7
- data.tar.gz: bd38063b3c625ac4296dacff7ca0499192bcbb140f744ea7a063a8fe4e3f98c5f1a1ee93831242592e0f744fecef512081f5fc5c9f134751dba6ea91d14e0285
6
+ metadata.gz: 701288fc0a288adba125cb2299810b79067ef86486ae1c94cdf87f86b0ebdf030226cb4c925c10a43455ee606a2a70f3396b5d538feb5b07200cbeedb22acde2
7
+ data.tar.gz: cfca2cab37975eed90e80b6c018f35c7a193f4977c7c6d62b21057f6d8513d0a3b3fd1bc33e4f1f9f826bbd5887bfd81bd7a69134b793cec5a22c6beb9c3138d
data/.rubocop.yml CHANGED
@@ -1,2 +1,2 @@
1
1
  AllCops:
2
- TargetRubyVersion: 3.1
2
+ TargetRubyVersion: 3.1
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  ## Installation
4
4
 
5
5
  ```sh
6
- gem install quality-report
6
+ gem install quality_report
7
7
  ```
8
8
 
9
9
  ## Usage
@@ -73,6 +73,8 @@ Complex code introduces bugs in a second, more subtle way. This is because code
73
73
 
74
74
  - [x] Colorize the output to separate high, medium, and low warning percentages.
75
75
  - [x] Fix the numerical alignment.
76
+ - [ ] --add-column option.
77
+ - [ ] --skip option.
76
78
  - [ ] Add a progress bar.
77
79
  - [ ] Speed up the scan.
78
80
  - [ ] Refactor from script-style coding to a more standard Ruby project.
data/Rakefile CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "bundler/gem_tasks"
4
- require "rspec/core/rake_task"
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
5
 
6
6
  RSpec::Core::RakeTask.new(:spec)
7
7
 
@@ -1,6 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
+ require 'json'
5
+ require 'tty-option'
4
6
  require 'tty-table'
5
7
  require 'pastel'
6
8
 
@@ -19,46 +21,60 @@ def create_combined_stats(part_stats, whole_stats)
19
21
  part_data = make_data_set(part_stats)
20
22
  whole_data = make_data_set(whole_stats)
21
23
 
22
- whole_data.map do |label, whole_count|
23
- part_count = part_data[label] || 0
24
+ whole_data.map do |author, whole_count|
25
+ part_count = part_data[author] || 0
24
26
  percent = float_to_percent(part_count.to_f / whole_count)
25
27
 
26
- { label:, part_count:, whole_count:, percent: }
28
+ { author:, part_count:, whole_count:, percent: }
27
29
  end
28
30
  end
29
31
 
30
32
  def make_data_set(two_column_data)
31
33
  hash = {}
32
34
  two_column_data.each_line do |line|
33
- count, label = line.split(' ')
34
- hash[label] = count.to_i
35
+ count, author = line.split(' ')
36
+ hash[author] = count.to_i
35
37
  end
36
38
  hash
37
39
  end
38
40
 
39
41
  def generate_csv(combined_stats)
40
42
  generate_data(combined_stats)
41
- .map { |stats| [stats[:label], stats[:percent], stats[:part_count], stats[:whole_count]].join(',') }
43
+ .map { |stats| [stats[:author], stats[:percent], stats[:part_count], stats[:whole_count]].join(',') }
42
44
  .tap { |x| x.prepend(['Author,Percent Flagged,Flagged Lines,All Lines']) }
43
45
  .join("\n")
44
46
  end
45
47
 
46
- def generate_table(combined_stats)
47
- table = TTY::Table.new(header: %W[Author Percent\nFlagged Flagged\nLines All\nLines])
48
- table_data = generate_data(combined_stats).reject { should_skip?(_1) }
48
+ def generate_table(combined_stats, colspec: {}, skip: '')
49
+ author_heading = ['Author']
50
+ static_heading = [colspec.keys&.first].compact
51
+ default_headings = ['Percent Flagged', 'Flagged Lines', 'All lines']
52
+ all_headings = author_heading + static_heading + default_headings
53
+
54
+ table = TTY::Table.new(header: all_headings)
55
+ table_data = generate_data(combined_stats).reject { should_skip?(_1) }
56
+ static_values = colspec[static_heading.first] || {}
49
57
 
50
58
  table_data.each do |stats|
51
- table << [
52
- { value: stats[:label], alignment: :left },
59
+ next if skip.include?(stats[:author])
60
+
61
+ author_column = [{ value: stats[:author], alignment: :left }]
62
+ static_column = [static_heading.any? ? { value: static_values[stats[:author]], alignment: :left } : nil]
63
+ dynamic_columns = [
53
64
  { value: "#{stats[:percent]}%", alignment: :right },
54
65
  { value: int_to_accounting(stats[:part_count]), alignment: :right },
55
66
  { value: int_to_accounting(stats[:whole_count]), alignment: :right }
56
67
  ]
68
+
69
+ table << (author_column + static_column + dynamic_columns).compact
57
70
  end
58
71
 
59
72
  render_table(table, table_data)
60
73
  end
61
74
 
75
+ ##
76
+ # Renders the table with color coding based on the percentage of flagged lines.
77
+ #
62
78
  def render_table(table, table_data)
63
79
  pastel = Pastel.new
64
80
 
@@ -96,7 +112,7 @@ def less_than_200_lines_total?(stats)
96
112
  end
97
113
 
98
114
  def no_commits_in_last_60_days?(stats)
99
- author = stats[:label]
115
+ author = stats[:author]
100
116
 
101
117
  # Get the last commit timestamp in Unix epoch format
102
118
  last_commit = `git log -1 --format="%at" --author="#{author}"`.chomp
@@ -126,11 +142,82 @@ def int_to_accounting(an_int)
126
142
  an_int.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse
127
143
  end
128
144
 
145
+ #
146
+ # CLI Argument Parser
147
+ #
148
+ class Command
149
+ include TTY::Option
150
+
151
+ usage do
152
+ program 'ruby-quality-report'
153
+ no_command
154
+ header 'Ruby Quality Report'
155
+ desc <<~DESC
156
+ Generates a report of the percentage of flagged lines of code written by each author. For improved relevance, it excludes:
157
+
158
+ - authors with fewer than 200 lines of code
159
+ - authors with no commits in the previous 60 days
160
+
161
+ It runs a suite of Rubocop metrics on *.rb files recursively starting in the current directory. Then, using git, it calculates the percentage of warnings per line written, per author. Each failing check is another warning.
162
+ DESC
163
+
164
+ example <<~EXAMPLE1
165
+ Append a column showing office location. The order of the keys in the JSON does not matter:
166
+ $ ruby-quality-report -c '{"Location": {"Amy": "NYC", "Bob": "Remote"}}'
167
+ EXAMPLE1
168
+
169
+ example <<~EXAMPLE2
170
+ Skip one author:
171
+ $ ruby-quality-report --skip Cathy
172
+ EXAMPLE2
173
+ end
174
+
175
+ option :add_column do
176
+ long '--add-column JSON'
177
+ short '-c JSON'
178
+ desc 'Add a static column to the report. This is a simple way to add known information. See the examples.'
179
+ end
180
+
181
+ flag :skip do
182
+ long '--skip AUTHOR'
183
+ short '-s AUTHOR'
184
+ desc 'Filter out a git author'
185
+ end
186
+
187
+ flag :help do
188
+ short '-h'
189
+ long '--help'
190
+ desc 'Print this help'
191
+ end
192
+
193
+ def run
194
+ if params[:help]
195
+ print help
196
+ exit 1
197
+ elsif params.errors.any?
198
+ puts params.errors.summary
199
+ exit 1
200
+ end
201
+ end
202
+ end
203
+
129
204
  #
130
205
  # Execution begins here
131
206
  #
207
+
208
+ command = Command.new
209
+ command.parse
210
+ command.run
211
+
212
+ add_column_param = command.params[:add_column]
213
+ colspec = add_column_param ? JSON.parse(add_column_param) : {}
214
+ puts "Adding column: #{colspec.keys.first}" unless colspec.empty?
215
+
216
+ skip = command.params[:skip] || ''
217
+ puts "Skipping author: #{skip}" if skip != ''
218
+
132
219
  PART_STATS = `ruby-author-warnings | frequency-list`.freeze
133
- WHOLE_STATS = `ruby-line-authors | frequency-list`.freeze
220
+ WHOLE_STATS = `ruby-line-authors | frequency-list`.freeze
134
221
  COMBINED_STATS = create_combined_stats(PART_STATS, WHOLE_STATS)
135
222
 
136
- puts generate_table(COMBINED_STATS)
223
+ puts generate_table(COMBINED_STATS, colspec:, skip:)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module QualityReport
4
- VERSION = '1.5.0'
4
+ VERSION = '1.7.0'
5
5
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "quality_report/version"
3
+ require_relative 'quality_report/version'
4
4
 
5
5
  module QualityReport
6
6
  class Error < StandardError; end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quality_report
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robb Shecter
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-11-10 00:00:00.000000000 Z
11
+ date: 2024-11-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubocop
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.68'
27
+ - !ruby/object:Gem::Dependency
28
+ name: tty-option
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.3.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.3.0
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: tty-table
29
43
  requirement: !ruby/object:Gem::Requirement