-
-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Required ruby version fixes #9515
Required ruby version fixes #9515
Conversation
38e6f2c
to
bb076a8
Compare
Add cases that include - numeric version - approximate version - not equal version - array of many version types
…equired_ruby_version` - Create `Gem::Requirement` from required_ruby_version - Return first `KNOWN_RUBY` that satisfies the requirement when one exists - Support more types of version entries
bb076a8
to
4e15000
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Much better!
I think it can be improved, simplified, and avoid parsing the requirement ourselves
lib/rubocop/target_ruby.rb
Outdated
|
||
# Helper to check if the requirement is satisfied by a given known ruby version | ||
# @api private | ||
class Matcher |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be best to do without this class and use the Gem::Requirement
as a matcher. Note that matchers typically better constructed without the value to match; that value is passed to the matching method (like satisfied_by?
).
lib/rubocop/target_ruby.rb
Outdated
def version_from_str(str) | ||
str.match(/^(?:>=|<=)?\s*(?<version>\d+(?:\.\d+)*)/) do |md| | ||
md[:version].to_f | ||
def remove_patch_from_version(str) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see that you went through the trouble of parsing the requirement nevertheless... How about instead mapping our versions like 2.7 => '2.7.999'? This would have the desired effect, except in the case of exact Ruby version requirements (which are a mistake), simplify the code and avoid redoing the parsing that we shouldn't be doing.
s.licenses = ['MIT'] | ||
end | ||
HEREDOC | ||
|
||
create_file(gemspec_file_path, content) | ||
expect(target_ruby.version).to eq default_version | ||
end | ||
|
||
it 'sets target_ruby from inclusive range' do | ||
content = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No obligation, but consider using let
or before_each
to avoid duplicating all these lines so many times.
spec/rubocop/target_ruby_spec.rb
Outdated
content = | ||
<<-HEREDOC | ||
Gem::Specification.new do |s| | ||
s.name = 'test' | ||
s.required_ruby_version = '>= 3.0.0' | ||
s.required_ruby_version = '2.7.4' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't even test this. There's is no reason I can think of to specify such a requirement. We could even consider raising an offense in one of our cops for this, but I doubt it happens in practice.
spec/rubocop/target_ruby_spec.rb
Outdated
content = | ||
<<-HEREDOC | ||
Gem::Specification.new do |s| | ||
s.name = 'test' | ||
s.required_ruby_version = '< 3.0.0' | ||
s.required_ruby_version = '2.3.0' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, testing for < 2.3.0
is fine, but not = 2.3.0
@marcandre Thanks for the review. Updated the PR and I think its ready now 🤞 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it is almost ready 😅
lib/rubocop/target_ruby.rb
Outdated
gem_version = ->(ruby_version) { Gem::Version.new(ruby_version) } | ||
|
||
match = KNOWN_RUBIES.each.lazy.map(&gem_version).detect { |v| requirement.satisfied_by?(v) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't these lines be replaced by:
match = KNOWN_RUBIES.detect { |v| requirement.satisfied_by?(Gem::Version.new(v) }
I'd actually use Gem::Version.new("#{v}.99")
so that it works ok for >= '2.6.1'
In general, storing a lambda in a local variable is an anti-pattern. Also, it's typically best to use lazy
only when actually needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems to me it is an error to use !=
. In any case, if someone did specify != 2.4.0
, that doesn't exclude 2.4.1
etc which are in the 2.4
series, so it seems like an ok target.
The main scenario we have to get right is >
, >=
and potentially ~>
even though that seems a bit strange.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok 1 more thing if we had '> 2.4.1'
then it would match to 2.4
due to the .99
, that seems wrong?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that's the best behavior. Imagine that there is a bug in 2.4.1 that is fixed in Ruby 2.4.2+; the gem author wants to make sure we don't try to run the gem in 2.4.1 or below as the bug can be triggered by code in the gem. The gem still uses the "2.4.x" features and syntax, so target of 2.4 is best.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok pushed the updates 😃
spec/rubocop/target_ruby_spec.rb
Outdated
content = | ||
<<-HEREDOC | ||
Gem::Specification.new do |s| | ||
s.name = 'test' | ||
s.required_ruby_version = '2.7.4' | ||
s.required_ruby_version = '>= 2.6.0' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should also work for >= 2.6.1
d80cfc5
to
b3093ba
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good stuff! 💪
Thanks 😄
Closes #9482 and #9329
The class to match
required_ruby_version
from.gemspec
files could return invalid ruby versions.KNOWN_RUBIES
array. Specifically the minimal known ruby will be returned.Gem
library.Before submitting the PR make sure the following are checked:
[Fix #issue-number]
(if the related issue exists).master
(if not - rebase it).bundle exec rake default
. It executes all tests and runs RuboCop on its own code.{change_type}_{change_description}.md
if the new code introduces user-observable changes. See changelog entry format for details.