skunk 0.5.4 → 0.6.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 +4 -4
- data/.github/workflows/main.yml +8 -2
- data/.gitignore +2 -0
- data/.reek.yml +29 -0
- data/.rubocop_todo.yml +22 -19
- data/CHANGELOG.md +15 -1
- data/CONTRIBUTING.md +7 -1
- data/Gemfile +8 -3
- data/README.md +53 -2
- data/Rakefile +11 -4
- data/lib/skunk/cli/application.rb +5 -13
- data/lib/skunk/cli/options/argv.rb +17 -9
- data/lib/skunk/commands/compare.rb +12 -2
- data/lib/skunk/commands/default.rb +0 -3
- data/lib/skunk/commands/shareable.rb +7 -0
- data/lib/skunk/commands/status_reporter.rb +5 -82
- data/lib/skunk/commands/status_sharer.rb +25 -10
- data/lib/skunk/config.rb +128 -0
- data/lib/skunk/generators/console/simple.rb +92 -0
- data/lib/skunk/generators/console_report.rb +48 -0
- data/lib/skunk/generators/html/file_data.rb +21 -0
- data/lib/skunk/generators/html/overview.rb +61 -0
- data/lib/skunk/generators/html/path_truncator.rb +49 -0
- data/lib/skunk/generators/html/templates/skunk_overview.html.erb +366 -0
- data/lib/skunk/generators/html_report.rb +52 -0
- data/lib/skunk/generators/json/simple.rb +16 -37
- data/lib/skunk/generators/json_report.rb +18 -4
- data/lib/skunk/reporter.rb +4 -4
- data/lib/skunk/rubycritic/analysed_modules_collection.rb +91 -6
- data/lib/skunk/version.rb +1 -1
- data/skunk.gemspec +4 -4
- metadata +48 -37
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9ae89820e2645a8356092c358e5f5e2c6e89a61aa6420ba77dc60e79c64fdd8a
|
|
4
|
+
data.tar.gz: 47762e6f7666c98cfd41c1a104c62c0aa3041acf4ac64db7f6f32040aebb1390
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d7d8759277c1bc4b150cb31d9e7b5d6a04e63d79ec57ee455f0c6f3011dc96ba6448a62e9108c7169aa6320aebc12c2f706d1f2f3226438d67cc58ae8e320489
|
|
7
|
+
data.tar.gz: 47bd94df98ac6e5170eb8030f86c88a7d72d28d74621e8296f5372d788d28a0360593302e339392dba4915d7446af1d2091156838e52fa79709bfe69d9b070e7
|
data/.github/workflows/main.yml
CHANGED
|
@@ -6,10 +6,16 @@ on: [push, pull_request]
|
|
|
6
6
|
jobs:
|
|
7
7
|
test-ruby:
|
|
8
8
|
runs-on: ${{ matrix.os }}-latest
|
|
9
|
+
continue-on-error: ${{ matrix.experimental || false }}
|
|
9
10
|
strategy:
|
|
11
|
+
fail-fast: false
|
|
10
12
|
matrix:
|
|
11
13
|
os: [ubuntu]
|
|
12
|
-
ruby-version: ["2.6", "2.7", "3.0", "3.1", "3.2", "3.3"]
|
|
14
|
+
ruby-version: ["2.6", "2.7", "3.0", "3.1", "3.2", "3.3", "3.4", "4.0"]
|
|
15
|
+
include:
|
|
16
|
+
- os: ubuntu
|
|
17
|
+
ruby-version: "head"
|
|
18
|
+
experimental: true
|
|
13
19
|
steps:
|
|
14
20
|
- uses: actions/checkout@v2
|
|
15
21
|
- name: Setup Ruby ${{ matrix.ruby-version }}
|
|
@@ -19,6 +25,6 @@ jobs:
|
|
|
19
25
|
bundler-cache: true
|
|
20
26
|
- name: Build and run tests
|
|
21
27
|
run: |
|
|
22
|
-
gem install bundler -v 2.4.
|
|
28
|
+
gem install bundler -v 2.4.22
|
|
23
29
|
bundle install --jobs 4 --retry 3
|
|
24
30
|
bundle exec rake
|
data/.gitignore
CHANGED
data/.reek.yml
CHANGED
|
@@ -7,6 +7,7 @@ detectors:
|
|
|
7
7
|
FeatureEnvy:
|
|
8
8
|
exclude:
|
|
9
9
|
- Skunk::Command::StatusReporter#table
|
|
10
|
+
- Skunk::Generator::HtmlReport#create_directories_and_files
|
|
10
11
|
InstanceVariableAssumption:
|
|
11
12
|
exclude:
|
|
12
13
|
- Skunk::Cli::Options::Argv
|
|
@@ -22,9 +23,37 @@ detectors:
|
|
|
22
23
|
- initialize
|
|
23
24
|
- Skunk::Cli::Application#execute
|
|
24
25
|
- Skunk::Cli::Options::Argv#parse
|
|
26
|
+
- Skunk::Analysis#test_module?
|
|
27
|
+
- add_mock_methods_to_module
|
|
28
|
+
TooManyInstanceVariables:
|
|
29
|
+
exclude:
|
|
30
|
+
- Skunk::Generator::Html::FileData
|
|
31
|
+
- Skunk::Generator::Html::SkunkData
|
|
25
32
|
UtilityFunction:
|
|
26
33
|
exclude:
|
|
27
34
|
- capture_output_streams
|
|
28
35
|
- Skunk::Command::Compare#analyse_modified_files
|
|
29
36
|
- Skunk::Command::Compare#build_details_path
|
|
30
37
|
- Skunk::Command::Shareable#sharing?
|
|
38
|
+
- Skunk::Command::Shareable#share_enabled?
|
|
39
|
+
- Skunk::Command::StatusSharer#share_enabled?
|
|
40
|
+
- Skunk::Command::StatusSharer#share_url_empty?
|
|
41
|
+
- Skunk::Configuration#supported_format?
|
|
42
|
+
- Skunk::Configuration#supported_formats
|
|
43
|
+
- Skunk::Analysis#test_module?
|
|
44
|
+
- Skunk::ConfigTest#setup
|
|
45
|
+
ManualDispatch:
|
|
46
|
+
exclude:
|
|
47
|
+
- Skunk::Config#self.method_missing
|
|
48
|
+
- Skunk::Config#self.respond_to_missing?
|
|
49
|
+
BooleanParameter:
|
|
50
|
+
exclude:
|
|
51
|
+
- Skunk::Config#self.respond_to_missing?
|
|
52
|
+
DuplicateMethodCall:
|
|
53
|
+
exclude:
|
|
54
|
+
- Skunk::ConfigTest#test_add_format_ignores_duplicates
|
|
55
|
+
FeatureEnvy:
|
|
56
|
+
exclude:
|
|
57
|
+
- Skunk::Command::StatusReporter#table
|
|
58
|
+
- Skunk::Generator::HtmlReport#create_directories_and_files
|
|
59
|
+
- add_mock_methods_to_module
|
data/.rubocop_todo.yml
CHANGED
|
@@ -1,51 +1,44 @@
|
|
|
1
1
|
# This configuration was generated by
|
|
2
2
|
# `rubocop --auto-gen-config`
|
|
3
|
-
# on 2025-
|
|
3
|
+
# on 2025-11-14 17:50:37 UTC using RuboCop version 1.81.1.
|
|
4
4
|
# The point is for the user to remove these configuration records
|
|
5
5
|
# one by one as the offenses are removed from the code base.
|
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
|
7
7
|
# versions of RuboCop, may require this file to be generated again.
|
|
8
8
|
|
|
9
9
|
# Offense count: 1
|
|
10
|
-
# Configuration parameters: Severity
|
|
11
|
-
# Include: **/*.gemspec
|
|
10
|
+
# Configuration parameters: Severity.
|
|
12
11
|
Gemspec/RequiredRubyVersion:
|
|
13
12
|
Exclude:
|
|
14
13
|
- 'skunk.gemspec'
|
|
15
14
|
|
|
16
15
|
# Offense count: 1
|
|
17
|
-
|
|
18
|
-
Layout/ClosingHeredocIndentation:
|
|
16
|
+
Lint/IneffectiveAccessModifier:
|
|
19
17
|
Exclude:
|
|
20
|
-
- 'lib/skunk/
|
|
18
|
+
- 'lib/skunk/generators/console/simple.rb'
|
|
21
19
|
|
|
22
|
-
# Offense count:
|
|
23
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
24
|
-
Layout/HeredocIndentation:
|
|
25
|
-
Exclude:
|
|
26
|
-
- 'lib/skunk/commands/status_reporter.rb'
|
|
27
|
-
|
|
28
|
-
# Offense count: 1
|
|
20
|
+
# Offense count: 2
|
|
29
21
|
# Configuration parameters: AllowedParentClasses.
|
|
30
22
|
Lint/MissingSuper:
|
|
31
23
|
Exclude:
|
|
32
24
|
- 'lib/skunk/cli/application.rb'
|
|
25
|
+
- 'lib/skunk/generators/html/overview.rb'
|
|
33
26
|
|
|
34
|
-
# Offense count:
|
|
27
|
+
# Offense count: 5
|
|
35
28
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
|
|
36
29
|
Metrics/AbcSize:
|
|
37
|
-
Max:
|
|
30
|
+
Max: 24
|
|
38
31
|
|
|
39
|
-
# Offense count:
|
|
32
|
+
# Offense count: 13
|
|
40
33
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
|
41
34
|
# AllowedMethods: refine
|
|
42
35
|
Metrics/BlockLength:
|
|
43
|
-
Max:
|
|
36
|
+
Max: 208
|
|
44
37
|
|
|
45
|
-
# Offense count:
|
|
38
|
+
# Offense count: 7
|
|
46
39
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
|
47
40
|
Metrics/MethodLength:
|
|
48
|
-
Max:
|
|
41
|
+
Max: 20
|
|
49
42
|
|
|
50
43
|
# Offense count: 1
|
|
51
44
|
# Configuration parameters: EnforcedStyle, CheckMethodNames, CheckSymbols, AllowedIdentifiers, AllowedPatterns.
|
|
@@ -55,6 +48,16 @@ Naming/VariableNumber:
|
|
|
55
48
|
Exclude:
|
|
56
49
|
- 'lib/skunk/commands/status_sharer.rb'
|
|
57
50
|
|
|
51
|
+
# Offense count: 1
|
|
52
|
+
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
53
|
+
# Configuration parameters: EnforcedStyle, EnforcedStyleForClasses, EnforcedStyleForModules.
|
|
54
|
+
# SupportedStyles: nested, compact
|
|
55
|
+
# SupportedStylesForClasses: ~, nested, compact
|
|
56
|
+
# SupportedStylesForModules: ~, nested, compact
|
|
57
|
+
Style/ClassAndModuleChildren:
|
|
58
|
+
Exclude:
|
|
59
|
+
- 'test/test_helper.rb'
|
|
60
|
+
|
|
58
61
|
# Offense count: 1
|
|
59
62
|
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
60
63
|
# Configuration parameters: EnforcedStyle.
|
data/CHANGELOG.md
CHANGED
|
@@ -5,10 +5,24 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## main [(unreleased)](https://github.com/fastruby/skunk/compare/v0.
|
|
8
|
+
## main [(unreleased)](https://github.com/fastruby/skunk/compare/v0.6.0...HEAD)
|
|
9
9
|
|
|
10
10
|
* <INSERT YOUR FEATURE OR BUGFIX HERE>
|
|
11
11
|
|
|
12
|
+
## v0.6.0 / 2026-10-12 [(commits)](https://github.com/fastruby/skunk/compare/v0.5.4...v0.6.0)
|
|
13
|
+
|
|
14
|
+
* [BREAKING: `-o/--out` now takes an output directory instead of a file. Reports, and `skunk_report.txt` with the console output, are written there. The HTML report is renamed from `skunk_overview.html` to `skunk_report.html`](https://github.com/fastruby/skunk/pull/131)
|
|
15
|
+
* [FEATURE: Add sortable columns to the Skunk HTML report](https://github.com/fastruby/skunk/pull/142)
|
|
16
|
+
* [ENHANCEMENT: Support SimpleCov 1.0](https://github.com/fastruby/skunk/pull/140)
|
|
17
|
+
* BUGFIX: Pin path_expander < 2.0 for Ruby 2.7 compatibility
|
|
18
|
+
* [FEATURE: Add `--formats` CLI flag to select report formats (json, html, console)](https://github.com/fastruby/skunk/pull/130)
|
|
19
|
+
* [REFACTOR: Move Console Report](https://github.com/fastruby/skunk/pull/128)
|
|
20
|
+
* [BUGFIX: Set the right content type in the share HTTP request](https://github.com/fastruby/skunk/pull/129)
|
|
21
|
+
* [REFACTOR: Centralize Skunk analysis into RubyCritic module](https://github.com/fastruby/skunk/pull/127)
|
|
22
|
+
* [FEATURE: Add Skunk HTML Report](https://github.com/fastruby/skunk/pull/123)
|
|
23
|
+
* [FEATURE: Add Skunk::Config class](https://github.com/fastruby/skunk/pull/123)
|
|
24
|
+
* [FEATURE: Add Ruby 3.4 compatibility](https://github.com/fastruby/skunk/pull/124)
|
|
25
|
+
|
|
12
26
|
## v0.5.4 / 2025-05-05 [(commits)](https://github.com/fastruby/skunk/compare/v0.5.3...v0.5.4)
|
|
13
27
|
|
|
14
28
|
* [FEATURE: Generate JSON report in background](https://github.com/fastruby/skunk/pull/119)
|
data/CONTRIBUTING.md
CHANGED
|
@@ -14,6 +14,12 @@ Here's what you need to do:
|
|
|
14
14
|
- [Make sure the test suite passes on GitHub Actions and make any necessary changes to your branch to bring it to green.](#continuous-integration).
|
|
15
15
|
- Check out the [Help Wanted](#help-wanted) section for suggestions on how to support Skunk.
|
|
16
16
|
|
|
17
|
+
## Requirements
|
|
18
|
+
For a Linux distro called Pop!_OS, running Ruby 3.0 and up might require installing the following packages:
|
|
19
|
+
```bash
|
|
20
|
+
sudo apt install libyaml-dev
|
|
21
|
+
```
|
|
22
|
+
|
|
17
23
|
## Setting up your environment
|
|
18
24
|
To install the dependencies, run:
|
|
19
25
|
|
|
@@ -81,4 +87,4 @@ The SkunkScore of a module should be the average of the SkunkScores of all of it
|
|
|
81
87
|
|
|
82
88
|
Feel free to review and submit your suggestions to improve the method [RubyCritic::AnalysedModule#skunk_score](https://github.com/fastruby/skunk/blob/main/lib/skunk/rubycritic/analysed_module.rb#L33).
|
|
83
89
|
|
|
84
|
-
📘 Read [Escaping The Tar Pit: Introducing Skunk v0.3.2 at RubyConf 2019](https://www.fastruby.io/blog/code-quality/escaping-the-tar-pit-at-rubyconf.html) and [Churn vs. Complexity vs. Code Coverage](https://www.fastruby.io/blog/code-quality/churn-vs-complexity-vs-coverage.html) for more details about the `skunk_score` method.
|
|
90
|
+
📘 Read [Escaping The Tar Pit: Introducing Skunk v0.3.2 at RubyConf 2019](https://www.fastruby.io/blog/code-quality/escaping-the-tar-pit-at-rubyconf.html) and [Churn vs. Complexity vs. Code Coverage](https://www.fastruby.io/blog/code-quality/churn-vs-complexity-vs-coverage.html) for more details about the `skunk_score` method.
|
data/Gemfile
CHANGED
|
@@ -7,6 +7,11 @@ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
|
|
7
7
|
# Specify your gem's dependencies in skunk.gemspec
|
|
8
8
|
gemspec
|
|
9
9
|
|
|
10
|
-
gem "reek"
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
gem "reek"
|
|
11
|
+
|
|
12
|
+
# Pinned so the CI matrix lints against one RuboCop instead of each Ruby
|
|
13
|
+
# resolving whatever version it happens to support. Rubies older than 3.1 cannot
|
|
14
|
+
# install it: reek and rubycritic hold parser below 3.3 there, while RuboCop
|
|
15
|
+
# 1.60 and up require it, so those rubies get no RuboCop and the Rakefile drops
|
|
16
|
+
# the lint task for them. They still run the tests and reek.
|
|
17
|
+
gem "rubocop", "~> 1.81.0" if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.1")
|
data/README.md
CHANGED
|
@@ -14,6 +14,8 @@ Skunk is a RubyCritic extension to calculate a SkunkScore for a file or project.
|
|
|
14
14
|
* [Help commands](#help-commands)
|
|
15
15
|
* [Generate the SkunkCore for your project](#generate-the-skunkcore-for-your-project)
|
|
16
16
|
* [Comparing Feature Branches](#comparing-feature-branches)
|
|
17
|
+
* [Configuration](#configuration)
|
|
18
|
+
* [Setting Output Formats](#setting-output-formats)
|
|
17
19
|
* [Sharing your SkunkScore](#sharing-your-skunkscore)
|
|
18
20
|
* [Contributing](#contributing)
|
|
19
21
|
* [Sponsorship](#sponsorship)
|
|
@@ -63,7 +65,7 @@ Run `skunk -h` to check out the help options:
|
|
|
63
65
|
```
|
|
64
66
|
Usage: skunk [options] [paths]
|
|
65
67
|
-b, --branch BRANCH Set branch to compare
|
|
66
|
-
-o, --out
|
|
68
|
+
-o, --out PATH Output directory for reports
|
|
67
69
|
-v, --version Show gem's version
|
|
68
70
|
-h, --help Show this message
|
|
69
71
|
```
|
|
@@ -125,7 +127,9 @@ To only run skunk on specific folders, pass a list of directories in the command
|
|
|
125
127
|
|
|
126
128
|
### Generate JSON report in background
|
|
127
129
|
|
|
128
|
-
When the Skunk command is run, it will generate a JSON report file in the
|
|
130
|
+
When the Skunk command is run, it will generate a JSON report file in the configured output path.
|
|
131
|
+
|
|
132
|
+
When `--out PATH` is given, Skunk also writes the console report to `skunk_report.txt` in that directory.
|
|
129
133
|
|
|
130
134
|
### Comparing feature branches
|
|
131
135
|
|
|
@@ -152,6 +156,53 @@ Score: 340.3
|
|
|
152
156
|
|
|
153
157
|
This should give you an idea if you're moving in the direction of maintaining the code quality or not. In this case, the feature branch is decreasing the code quality because it has a higher SkunkScore than the main branch.
|
|
154
158
|
|
|
159
|
+
## Configuration
|
|
160
|
+
|
|
161
|
+
### Setting Output Formats
|
|
162
|
+
|
|
163
|
+
Skunk supports multiple output formats and you can select them via CLI or programmatically.
|
|
164
|
+
|
|
165
|
+
**Supported formats:**
|
|
166
|
+
- `:json` - JSON report
|
|
167
|
+
- `:html` - HTML report with visual charts and tables
|
|
168
|
+
- `:console` - Console output (default)
|
|
169
|
+
|
|
170
|
+
#### CLI flag
|
|
171
|
+
|
|
172
|
+
You can choose one or more formats from the command line:
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
skunk --formats=json
|
|
176
|
+
skunk -f json,html
|
|
177
|
+
skunk --formats console,json
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
If omitted, Skunk defaults to `console`.
|
|
181
|
+
|
|
182
|
+
#### Programmatic configuration
|
|
183
|
+
|
|
184
|
+
You can also configure formats in code using `Skunk::Config`:
|
|
185
|
+
|
|
186
|
+
```ruby
|
|
187
|
+
require 'skunk/config'
|
|
188
|
+
|
|
189
|
+
# Set multiple formats (equivalent to `--formats=json,html`)
|
|
190
|
+
Skunk::Config.formats = [:json, :html]
|
|
191
|
+
|
|
192
|
+
# Add a format to the existing list
|
|
193
|
+
Skunk::Config.add_format(:html)
|
|
194
|
+
|
|
195
|
+
# Remove a format
|
|
196
|
+
Skunk::Config.remove_format(:json)
|
|
197
|
+
|
|
198
|
+
# Check supported formats
|
|
199
|
+
Skunk::Config.supported_formats # => [:json, :html, :console]
|
|
200
|
+
Skunk::Config.supported_format?(:json) # => true
|
|
201
|
+
|
|
202
|
+
# Reset to defaults
|
|
203
|
+
Skunk::Config.reset
|
|
204
|
+
```
|
|
205
|
+
|
|
155
206
|
## Sharing your SkunkScore
|
|
156
207
|
|
|
157
208
|
If you want to share the results of your Skunk report with the Ruby community, run:
|
data/Rakefile
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
require "bundler/gem_tasks"
|
|
4
4
|
require "rake/testtask"
|
|
5
|
-
require "rubocop/rake_task"
|
|
6
5
|
require "reek/rake/task"
|
|
7
6
|
require "rubycritic/rake_task"
|
|
8
7
|
|
|
@@ -12,12 +11,20 @@ Rake::TestTask.new do |task|
|
|
|
12
11
|
task.pattern = "test/**/*_test.rb"
|
|
13
12
|
end
|
|
14
13
|
|
|
15
|
-
RuboCop::RakeTask.new
|
|
16
|
-
|
|
17
14
|
Reek::Rake::Task.new
|
|
18
15
|
|
|
19
16
|
RubyCritic::RakeTask.new do |task|
|
|
20
17
|
task.paths = FileList["lib/**/*.rb"]
|
|
21
18
|
end
|
|
22
19
|
|
|
23
|
-
|
|
20
|
+
lint_tasks = []
|
|
21
|
+
|
|
22
|
+
begin
|
|
23
|
+
require "rubocop/rake_task"
|
|
24
|
+
RuboCop::RakeTask.new
|
|
25
|
+
lint_tasks << :rubocop
|
|
26
|
+
rescue LoadError
|
|
27
|
+
# RuboCop is not installed on the rubies the Gemfile skips the pin for.
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
task default: %i[test reek] + lint_tasks
|
|
@@ -5,6 +5,7 @@ require "rubycritic/cli/application"
|
|
|
5
5
|
|
|
6
6
|
require "skunk"
|
|
7
7
|
require "skunk/rubycritic/analysed_module"
|
|
8
|
+
require "skunk/rubycritic/analysed_modules_collection"
|
|
8
9
|
require "skunk/cli/options"
|
|
9
10
|
require "skunk/command_factory"
|
|
10
11
|
require "skunk/commands/status_sharer"
|
|
@@ -24,19 +25,20 @@ module Skunk
|
|
|
24
25
|
def execute
|
|
25
26
|
warn_coverage_info unless File.exist?(COVERAGE_FILE)
|
|
26
27
|
|
|
28
|
+
Skunk::Config.reset
|
|
27
29
|
# :reek:NilCheck
|
|
28
30
|
@parsed_options = @options.parse.to_h
|
|
29
31
|
command = Skunk::CommandFactory.create(@parsed_options)
|
|
30
32
|
reporter = command.execute
|
|
31
33
|
|
|
32
|
-
|
|
34
|
+
$stdout.puts(reporter.status_message)
|
|
33
35
|
if command.sharing?
|
|
34
36
|
share_status_message = command.share(reporter)
|
|
35
|
-
|
|
37
|
+
$stdout.puts(share_status_message)
|
|
36
38
|
end
|
|
37
39
|
|
|
38
40
|
reporter.status
|
|
39
|
-
rescue OptionParser::
|
|
41
|
+
rescue OptionParser::ParseError => e
|
|
40
42
|
warn "Error: #{e}"
|
|
41
43
|
STATUS_ERROR
|
|
42
44
|
end
|
|
@@ -47,16 +49,6 @@ module Skunk
|
|
|
47
49
|
warn "warning: Couldn't find coverage info at #{COVERAGE_FILE}."
|
|
48
50
|
warn "warning: Having no coverage metrics will make your SkunkScore worse."
|
|
49
51
|
end
|
|
50
|
-
|
|
51
|
-
# :reek:NilCheck
|
|
52
|
-
def print(message)
|
|
53
|
-
filename = @parsed_options[:output_filename]
|
|
54
|
-
if filename.nil?
|
|
55
|
-
$stdout.puts(message)
|
|
56
|
-
else
|
|
57
|
-
File.open(filename, "a") { |file| file << message }
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
52
|
end
|
|
61
53
|
end
|
|
62
54
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "rubycritic/cli/options/argv"
|
|
4
|
+
require "skunk/config"
|
|
4
5
|
|
|
5
6
|
module Skunk
|
|
6
7
|
module Cli
|
|
@@ -9,21 +10,21 @@ module Skunk
|
|
|
9
10
|
# Extends RubyCritic::Cli::Options::Argv to parse a subset of the
|
|
10
11
|
# parameters accepted by RubyCritic
|
|
11
12
|
class Argv < RubyCritic::Cli::Options::Argv
|
|
12
|
-
|
|
13
|
-
attr_accessor :output_filename
|
|
14
|
-
|
|
15
|
-
def parse # rubocop:disable Metrics/MethodLength
|
|
13
|
+
def parse
|
|
16
14
|
parser.new do |opts|
|
|
17
15
|
opts.banner = "Usage: skunk [options] [paths]\n"
|
|
18
|
-
|
|
19
16
|
opts.on("-b", "--branch BRANCH", "Set branch to compare") do |branch|
|
|
20
17
|
self.base_branch = String(branch)
|
|
21
18
|
set_current_branch
|
|
22
19
|
self.mode = :compare_branches
|
|
23
20
|
end
|
|
24
21
|
|
|
25
|
-
opts.on("-o", "--out
|
|
26
|
-
self.
|
|
22
|
+
opts.on("-o", "--out PATH", "Output directory for reports") do |path|
|
|
23
|
+
self.output_path = path
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
opts.on("-f", "--formats json,html,console", Array, "Output formats: json,html,console") do |list|
|
|
27
|
+
Skunk::Config.formats = Array(list).map(&:to_sym)
|
|
27
28
|
end
|
|
28
29
|
|
|
29
30
|
opts.on_tail("-v", "--version", "Show gem's version") do
|
|
@@ -36,8 +37,15 @@ module Skunk
|
|
|
36
37
|
end.parse!(@argv)
|
|
37
38
|
end
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
# Moves only Skunk's reports. RubyCritic::Config.root stays under
|
|
43
|
+
# RubyCritic's control, and Skunk::Config.root falls back to it
|
|
44
|
+
def output_path=(path)
|
|
45
|
+
raise OptionParser::InvalidArgument, "expects a directory" if path.to_s.strip.empty?
|
|
46
|
+
raise OptionParser::InvalidArgument, "expects a directory, but #{path} is a file" if File.file?(path)
|
|
47
|
+
|
|
48
|
+
Skunk::Config.root = path
|
|
41
49
|
end
|
|
42
50
|
end
|
|
43
51
|
end
|
|
@@ -5,6 +5,7 @@ require "skunk/rubycritic/analysed_modules_collection"
|
|
|
5
5
|
require "skunk/commands/output"
|
|
6
6
|
require "skunk/commands/shareable"
|
|
7
7
|
require "skunk/commands/compare_score"
|
|
8
|
+
require "skunk/config"
|
|
8
9
|
|
|
9
10
|
# nodoc #
|
|
10
11
|
module Skunk
|
|
@@ -51,13 +52,22 @@ module Skunk
|
|
|
51
52
|
::RubyCritic::Config.feature_branch_score.to_f.round(2)
|
|
52
53
|
).message
|
|
53
54
|
|
|
54
|
-
Skunk::Command::Output.create_directory(
|
|
55
|
+
Skunk::Command::Output.create_directory(compare_directory)
|
|
55
56
|
File.open(build_details_path, "w") { |file| file.write(details) }
|
|
56
57
|
puts details
|
|
57
58
|
end
|
|
58
59
|
|
|
59
60
|
def build_details_path
|
|
60
|
-
"#{
|
|
61
|
+
"#{compare_directory}/build_details.txt"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Uses --out (Skunk::Config.root) when given, otherwise RubyCritic's
|
|
65
|
+
# compare directory
|
|
66
|
+
# :reek:UtilityFunction
|
|
67
|
+
def compare_directory
|
|
68
|
+
return ::RubyCritic::Config.compare_root_directory unless Skunk::Config.root_set?
|
|
69
|
+
|
|
70
|
+
File.join(Skunk::Config.root, "compare")
|
|
61
71
|
end
|
|
62
72
|
end
|
|
63
73
|
end
|
|
@@ -26,8 +26,6 @@ module Skunk
|
|
|
26
26
|
#
|
|
27
27
|
# @return [Skunk::Command::StatusReporter]
|
|
28
28
|
def execute
|
|
29
|
-
RubyCritic::Config.formats = [:json]
|
|
30
|
-
|
|
31
29
|
report(critique)
|
|
32
30
|
|
|
33
31
|
status_reporter
|
|
@@ -41,7 +39,6 @@ module Skunk
|
|
|
41
39
|
Reporter.generate_report(analysed_modules)
|
|
42
40
|
|
|
43
41
|
status_reporter.analysed_modules = analysed_modules
|
|
44
|
-
status_reporter.score = analysed_modules.score
|
|
45
42
|
end
|
|
46
43
|
end
|
|
47
44
|
end
|
|
@@ -18,6 +18,13 @@ module Skunk
|
|
|
18
18
|
# @return [Boolean] If the environment is set to share to an external
|
|
19
19
|
# service
|
|
20
20
|
def sharing?
|
|
21
|
+
share_enabled?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
# @return [Boolean] Check if sharing is enabled via environment variable
|
|
27
|
+
def share_enabled?
|
|
21
28
|
ENV["SHARE"] == "true"
|
|
22
29
|
end
|
|
23
30
|
end
|
|
@@ -1,96 +1,19 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "erb"
|
|
4
3
|
require "rubycritic/commands/status_reporter"
|
|
5
|
-
require "terminal-table"
|
|
6
4
|
|
|
7
5
|
module Skunk
|
|
8
6
|
module Command
|
|
9
|
-
#
|
|
7
|
+
# Extends RubyCritic::Command::StatusReporter to silence the status message
|
|
10
8
|
class StatusReporter < RubyCritic::Command::StatusReporter
|
|
11
9
|
attr_accessor :analysed_modules
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
HEADINGS_WITHOUT_FILE_WIDTH = HEADINGS_WITHOUT_FILE.size * 17 # padding
|
|
16
|
-
|
|
17
|
-
TEMPLATE = ERB.new(<<-TEMPL
|
|
18
|
-
<%= _ttable %>\n
|
|
19
|
-
SkunkScore Total: <%= total_skunk_score %>
|
|
20
|
-
Modules Analysed: <%= analysed_modules_count %>
|
|
21
|
-
SkunkScore Average: <%= skunk_score_average %>
|
|
22
|
-
<% if worst %>Worst SkunkScore: <%= worst.skunk_score %> (<%= worst.pathname %>)<% end %>
|
|
23
|
-
|
|
24
|
-
Generated with Skunk v<%= Skunk::VERSION %>
|
|
25
|
-
TEMPL
|
|
26
|
-
)
|
|
27
|
-
|
|
28
|
-
# Returns a status message with a table of all analysed_modules and
|
|
29
|
-
# a skunk score average
|
|
30
|
-
def update_status_message
|
|
31
|
-
opts = table_options.merge(headings: HEADINGS, rows: table)
|
|
32
|
-
|
|
33
|
-
_ttable = Terminal::Table.new(opts)
|
|
34
|
-
|
|
35
|
-
@status_message = TEMPLATE.result(binding)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
private
|
|
39
|
-
|
|
40
|
-
def analysed_modules_count
|
|
41
|
-
@analysed_modules_count ||= non_test_modules.count
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def non_test_modules
|
|
45
|
-
@non_test_modules ||= analysed_modules.reject do |a_module|
|
|
46
|
-
module_path = a_module.pathname.dirname.to_s
|
|
47
|
-
module_path.start_with?("test", "spec") || module_path.end_with?("test", "spec")
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def worst
|
|
52
|
-
@worst ||= sorted_modules.first
|
|
11
|
+
def initialize(options = {})
|
|
12
|
+
super(options)
|
|
53
13
|
end
|
|
54
14
|
|
|
55
|
-
def
|
|
56
|
-
@
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def total_skunk_score
|
|
60
|
-
@total_skunk_score ||= non_test_modules.sum(&:skunk_score)
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def total_churn_times_cost
|
|
64
|
-
non_test_modules.sum(&:churn_times_cost)
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def skunk_score_average
|
|
68
|
-
return 0 if analysed_modules_count.zero?
|
|
69
|
-
|
|
70
|
-
(total_skunk_score.to_d / analysed_modules_count).to_f.round(2)
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
def table_options
|
|
74
|
-
max = sorted_modules.max_by { |a_mod| a_mod.pathname.to_s.length }
|
|
75
|
-
width = max.pathname.to_s.length + HEADINGS_WITHOUT_FILE_WIDTH
|
|
76
|
-
{
|
|
77
|
-
style: {
|
|
78
|
-
width: width
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
def table
|
|
84
|
-
sorted_modules.map do |a_mod|
|
|
85
|
-
[
|
|
86
|
-
a_mod.pathname,
|
|
87
|
-
a_mod.skunk_score,
|
|
88
|
-
a_mod.churn_times_cost,
|
|
89
|
-
a_mod.churn,
|
|
90
|
-
a_mod.cost.round(2),
|
|
91
|
-
a_mod.coverage.round(2)
|
|
92
|
-
]
|
|
93
|
-
end
|
|
15
|
+
def update_status_message
|
|
16
|
+
@status_message = ""
|
|
94
17
|
end
|
|
95
18
|
end
|
|
96
19
|
end
|