quality_report 1.3.0 → 1.5.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: f18d81f9fa7d9dca4e114657e18e06fed11bed99df6746c0438bf2bf9b625441
4
- data.tar.gz: 19578513e16b8457a2e388e326834f31f1dd17876c822cf6f509349a2ae261e3
3
+ metadata.gz: 23d2fbfb3f81887e40858181c9822346e770e8f242d96cfb39b8239b5288cb37
4
+ data.tar.gz: f39b9f3ae08503660b79bcc0d286ae622d5e0aa5c06b056ef635a8af8def8576
5
5
  SHA512:
6
- metadata.gz: '03793a5b452e7f3ecc1b3c805eb273ff60f5619dceb902d0f19fc7c1272da7b60751ee737602671b364c00f2a2894568b8cf9c09b6e707feed5029b195c00952'
7
- data.tar.gz: 0da7cd9be8337214421ee9ed709dc5a6119fdc48611c4648c70b211e8df0aee85b39c65d24c30dc77be690237f205c34c788176d22e49db38467368c6a9fe9f5
6
+ metadata.gz: de5bfd72e7ea4b31e0bf57785ea38d5503624f0861adc660c1844848d32d839a90ecfb0ed6f5de1eabe13293846fd1771be45bb8f373725eabf6aed092fb50bf
7
+ data.tar.gz: bd38063b3c625ac4296dacff7ca0499192bcbb140f744ea7a063a8fe4e3f98c5f1a1ee93831242592e0f744fecef512081f5fc5c9f134751dba6ea91d14e0285
data/README.md CHANGED
@@ -8,6 +8,8 @@ gem install quality-report
8
8
 
9
9
  ## Usage
10
10
 
11
+ Change to a project directory that contains `*.rb` files. Then:
12
+
11
13
  ```sh
12
14
  ruby-quality-report
13
15
  ```
@@ -16,7 +18,7 @@ After a bit of a wait, it outputs a report in table form:
16
18
 
17
19
  ![Screenshot](screenshot-1@2x.webp)
18
20
 
19
- This is showing, for each author, the percentage of problematic lines of code. Lower is better.
21
+ This is showing, for each author, the percentage of problematic lines of code in the repo. Lower is better.
20
22
 
21
23
 
22
24
  ### For improved relevance, it has two filters.
@@ -44,7 +46,7 @@ It runs a subset of [Rubocop Metrics cops](https://docs.rubocop.org/rubocop/cops
44
46
  - [Method Length](https://docs.rubocop.org/rubocop/cops_metrics.html#metricsmethodlength)
45
47
  - [Perceived Complexity](https://docs.rubocop.org/rubocop/cops_metrics.html#metricsperceivedcomplexity)
46
48
 
47
- It then calculates the percentage of warnings per line written, per author. Each failing check is another warning.
49
+ Then, using git, it calculates the percentage of warnings per line written, per author. Each failing check is another warning.
48
50
 
49
51
 
50
52
  ## Intent
@@ -56,7 +58,7 @@ This is a team management tool to:
56
58
 
57
59
  ## Foundational Research
58
60
 
59
- Diving a little deeper, I've seen the phenomenon of micro-economies of bug-creation and bug-fixing develop within teams. Some developers appear to be extremely productive. They write a lot of code. But they also introduce a lot of bugs. The productivity is illusory.
61
+ Diving a little deeper, I've seen the phenomenon of "micro-economies" of bug-creation and bug-fixing develop within teams. Some developers appear to be extremely productive. They create a lot of commits. But they also create a lot of bugs. Their productivity is illusory.
60
62
 
61
63
  This code quality report doesn't track **bugs** per se. But it does report **quality and complexity**. Researchers have found a strong correlation between complexity and bug rate [1]. This link is reflected, _e.g.,_ in international safety standards that mandate low software complexity to reduce failures [2].
62
64
 
@@ -69,13 +71,13 @@ Complex code introduces bugs in a second, more subtle way. This is because code
69
71
 
70
72
  ## Roadmap
71
73
 
72
- - [ ] Colorize the output to separate high, medium, and low warning percentages.
73
- - [ ] Fix the numerical alignment.
74
- - [ ] Add a `--csv` option.
75
- - [ ] Make the filters configurable.
76
- - [ ] Speed up the scan.
74
+ - [x] Colorize the output to separate high, medium, and low warning percentages.
75
+ - [x] Fix the numerical alignment.
77
76
  - [ ] Add a progress bar.
77
+ - [ ] Speed up the scan.
78
78
  - [ ] Refactor from script-style coding to a more standard Ruby project.
79
+ - [ ] Make the filters configurable.
80
+ - [ ] Add a `--csv` option.
79
81
 
80
82
 
81
83
  ## Contributing
@@ -2,6 +2,7 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'tty-table'
5
+ require 'pastel'
5
6
 
6
7
  #
7
8
  # ruby-quality-report
@@ -10,6 +11,9 @@ require 'tty-table'
10
11
  # of lines of code written by each author that have been flagged as
11
12
  # having too high of a complexity.
12
13
  #
14
+ #
15
+
16
+ SIXTY_DAYS_IN_SECONDS = 60 * 24 * 60 * 60
13
17
 
14
18
  def create_combined_stats(part_stats, whole_stats)
15
19
  part_data = make_data_set(part_stats)
@@ -40,15 +44,42 @@ def generate_csv(combined_stats)
40
44
  end
41
45
 
42
46
  def generate_table(combined_stats)
43
- table = TTY::Table.new(header: ['Author', 'Percent Flagged', 'Flagged Lines', 'All Lines'])
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) }
49
+
50
+ table_data.each do |stats|
51
+ table << [
52
+ { value: stats[:label], alignment: :left },
53
+ { value: "#{stats[:percent]}%", alignment: :right },
54
+ { value: int_to_accounting(stats[:part_count]), alignment: :right },
55
+ { value: int_to_accounting(stats[:whole_count]), alignment: :right }
56
+ ]
57
+ end
44
58
 
45
- generate_data(combined_stats).each do |stats|
46
- next if should_skip?(stats)
59
+ render_table(table, table_data)
60
+ end
47
61
 
48
- table << [stats[:label], "#{stats[:percent]}%", stats[:part_count], stats[:whole_count]]
62
+ def render_table(table, table_data)
63
+ pastel = Pastel.new
64
+
65
+ table.render(:unicode, alignment: :center, padding: [0, 1], multiline: true) do |renderer|
66
+ renderer.border.style = :dim
67
+ renderer.filter = lambda { |val, row_index, _col_index|
68
+ if row_index <= 0
69
+ # Header row
70
+ val
71
+ else
72
+ case table_data[row_index - 1][:percent]
73
+ when 0...40
74
+ val
75
+ when 40...50
76
+ pastel.bold.yellow(val)
77
+ else
78
+ pastel.bold.red(val)
79
+ end
80
+ end
81
+ }
49
82
  end
50
-
51
- table.render(:unicode, alignments: %i[left right right right])
52
83
  end
53
84
 
54
85
  def generate_data(combined_stats)
@@ -73,13 +104,26 @@ def no_commits_in_last_60_days?(stats)
73
104
 
74
105
  # Convert Unix timestamp to Time object
75
106
  last_commit_time = Time.at(last_commit.to_i)
76
- sixty_days_ago = Time.now - (60 * 24 * 60 * 60) # 60 days in seconds
107
+ sixty_days_ago = Time.now - SIXTY_DAYS_IN_SECONDS
77
108
 
78
109
  last_commit_time < sixty_days_ago
79
110
  end
80
111
 
112
+ ###
113
+ # Converts a float to an integer percentage
114
+ #
81
115
  def float_to_percent(a_float)
82
- (Float(a_float) * 100).round(1)
116
+ (Float(a_float) * 100).round
117
+ end
118
+
119
+ ##
120
+ # Converts an integer to a string with commas separating thousands.
121
+ #
122
+ # An alternative implementation is:
123
+ # an_int.to_s.gsub(/(\d)(?=(\d{3})+(?!\d))/, '\\1,')
124
+ #
125
+ def int_to_accounting(an_int)
126
+ an_int.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse
83
127
  end
84
128
 
85
129
  #
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module QualityReport
4
- VERSION = '1.3.0'
4
+ VERSION = '1.5.0'
5
5
  end
data/screenshot-1@2x.webp CHANGED
Binary file
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.3.0
4
+ version: 1.5.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-08 00:00:00.000000000 Z
11
+ date: 2024-11-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubocop