quality_report 1.5.0 → 1.7.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: 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