Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
* [CHANGE] Replace Aruba with direct API calls in specs (by [@faisal][])
* [CHANGE] Replace all Cucumber features with Minitest/Spec specs (by [@faisal][])
* [BUGFIX] Add `lang="en"` to the report's `<html>` element, give the menu-toggle anchor an `aria-label`, and make the per-rating summary IDs unique. Fixes 17 WCAG 2.1 AA structural errors on `overview.html`. (by [@MarcusAl][])
* [FEATURE] `--maximum-decrease` / `maximum_decrease` now accepts float values (e.g. `0.5`), mirroring how `minimum_score` is handled (by [@siklodi-mariusz][])
* [CHANGE] Rename the `threshold_score` YAML key to `maximum_decrease` to match the `--maximum-decrease` CLI flag. The old `threshold_score` key still works but emits a deprecation warning; when both are present, `maximum_decrease` wins (by [@siklodi-mariusz][])

# v5.0.0 / 2026-01-26 [(commits)](https://github.com/whitesmith/rubycritic/compare/v4.12.0...v5.0.0)

Expand Down Expand Up @@ -507,3 +509,4 @@
[@exoego]: https://github.com/exoego
[@raff-s]: https://github.com/raff-s
[@MarcusAl]: https://github.com/MarcusAl
[@siklodi-mariusz]: https://github.com/siklodi-mariusz
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ $ rubycritic --help
- `lint`
2. See [custom formatters docs](/docs/formatters.md)
3. Faster, analyses diffs w.r.t base_branch (default: main), see `-b`
4. Works only with `-b`, default: 0
4. Works only with `-b`. Accepts a FLOAT (ex: 0.5), default: 0

You also can use a config file. Just create a `.rubycritic.yml` on your project root path.

Expand All @@ -144,7 +144,7 @@ mode_ci:
branch: 'production' # default is main
path: '/tmp/mycustompath' # Set path where report will be saved (tmp/rubycritic by default)
coverage_path: '/tmp/coverage' # Set path where SimpleCov coverage will be saved (./coverage by default)
threshold_score: 10 # default is 0
maximum_decrease: 0.5 # FLOAT, default is 0.0
deduplicate_symlinks: true # default is false
suppress_ratings: true # default is false
no_browser: true # default is false
Expand Down
2 changes: 1 addition & 1 deletion lib/rubycritic/cli/options/argv.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def parse
'--maximum-decrease [MAX_DECREASE]',
'Set a threshold for score difference between two branches (works only with -b)'
) do |threshold_score|
self.threshold_score = Integer(threshold_score)
self.threshold_score = Float(threshold_score)
end

formats = []
Expand Down
15 changes: 14 additions & 1 deletion lib/rubycritic/cli/options/file.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,21 @@ def coverage_path
options['coverage_path']
end

# The YAML key is `maximum_decrease` (matching the `--maximum-decrease`
# CLI flag). The legacy `threshold_score` key is still honoured for
# backward compatibility but is deprecated. When both are present, the
# new `maximum_decrease` key takes precedence.
def threshold_score
options['threshold_score']
warn_threshold_score_deprecation if options.key?('threshold_score')

options.fetch('maximum_decrease') { options['threshold_score'] }
end

def warn_threshold_score_deprecation
warn(
'[DEPRECATION] The `threshold_score` key in .rubycritic.yml is deprecated ' \
'and will be removed in a future release. Please use `maximum_decrease` instead.'
)
end

def deduplicate_symlinks?
Expand Down
2 changes: 1 addition & 1 deletion lib/rubycritic/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def set(options)
self.open_with = options[:open_with]
self.no_browser = options[:no_browser]
self.coverage_path = options[:coverage_path]
self.threshold_score = options[:threshold_score].to_i
self.threshold_score = options[:threshold_score].to_f
setup_paths_for_targets(options) if options[:paths]
setup_analysis_targets(options)
setup_version_control(options)
Expand Down
90 changes: 90 additions & 0 deletions test/lib/rubycritic/cli/options/file_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# frozen_string_literal: true

require 'test_helper'
require 'tmpdir'
require 'fileutils'
require 'yaml'
require 'rubycritic/cli/options/file'

describe RubyCritic::Cli::Options::File do
before do
@dir = Dir.mktmpdir('rubycritic-file-options-')
end

after do
FileUtils.remove_entry(@dir) if @dir && File.directory?(@dir)
end

def options_for(config)
path = File.join(@dir, '.rubycritic.yml')
File.write(path, YAML.dump(config))
options = RubyCritic::Cli::Options::File.new(path)
options.parse
options
end

def capture_stderr
original = $stderr
$stderr = StringIO.new
yield
$stderr.string
ensure
$stderr = original
end

describe 'maximum_decrease YAML key' do
it 'reads a float maximum_decrease value' do
options = options_for('maximum_decrease' => 0.5)

_(options.to_h[:threshold_score]).must_equal 0.5
end

it 'does not emit a deprecation warning for the canonical key' do
options = options_for('maximum_decrease' => 0.5)

warning = capture_stderr { options.to_h }

_(warning).must_equal ''
end
end

describe 'legacy threshold_score YAML key' do
it 'is still honoured for backward compatibility' do
options = options_for('threshold_score' => 0.5)

result = nil
capture_stderr { result = options.to_h }

_(result[:threshold_score]).must_equal 0.5
end

it 'emits a deprecation warning pointing to maximum_decrease' do
options = options_for('threshold_score' => 10)

warning = capture_stderr { options.to_h }

_(warning).must_include 'DEPRECATION'
_(warning).must_include 'threshold_score'
_(warning).must_include 'maximum_decrease'
end
end

describe 'when both keys are present' do
it 'prefers the canonical maximum_decrease key' do
options = options_for('maximum_decrease' => 0.5, 'threshold_score' => 10)

result = nil
capture_stderr { result = options.to_h }

_(result[:threshold_score]).must_equal 0.5
end

it 'still warns about the deprecated threshold_score key' do
options = options_for('maximum_decrease' => 0.5, 'threshold_score' => 10)

warning = capture_stderr { options.to_h }

_(warning).must_include 'DEPRECATION'
end
end
end
25 changes: 25 additions & 0 deletions test/lib/rubycritic/commands/compare_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,31 @@ def abort(str); end
end
end

describe 'float threshold (maximum_decrease)' do
it 'parses a fractional -t value as a float instead of coercing to an integer' do
options = ['-b', 'base_branch', '-t', '0.5', 'test/samples/compare_file.rb']
options = RubyCritic::Cli::Options.new(options).parse.to_h

_(options[:threshold_score]).must_equal 0.5
end

it 'respects a fractional threshold when comparing branch scores' do
options = ['-b', 'base_branch', '-t', '0.5', 'test/samples/compare_file.rb']
options = RubyCritic::Cli::Options.new(options).parse.to_h
RubyCritic::Config.set(options)
comparison = RubyCritic::Command::Compare.new(options)

RubyCritic::Config.base_branch_score = 92.31
RubyCritic::Config.feature_branch_score = 92.0
# difference is 0.31, below the 0.5 threshold -> build must not fail
_(comparison.send(:threshold_reached?)).must_equal false

RubyCritic::Config.feature_branch_score = 91.5
# difference is 0.81, above the 0.5 threshold -> build must fail
_(comparison.send(:threshold_reached?)).must_equal true
end
end

describe 'with default options passing two branches' do
before do
options = ['-b', 'base_branch', '-t', '10', 'test/samples/compare_file.rb']
Expand Down
Loading