Skip to content

Conversation

@djberube
Copy link
Contributor

@djberube djberube commented Aug 27, 2024

What was the end-user or developer problem that led to this PR?

Suppose a project has a requirement like this:

gem 'something', '~> 3.0'

So far, so good. Now, version 3.0.2 comes out with some critical security fix, and the project admins want to make sure everyone has it. They update the requirement to look like this:

gem 'something', '~> 3.0.2'

This seemingly works as intended - but there is a non-obvious difference in how the requirements operate. The first version matches anything between 3.0 and 4.0 - but the second only matches between 3.0.2 and 3.1.0.

This isn't a bug: the ~> operator works exactly as documented - but for many usecases, a caret operator would be helpful. This patch includes a ^> operator - basically, unlike ~>, which has a variable scope, ^> always matches from the specified version until the next major version.

This means that '^> 3.0.2' will match > 3.0.2 but < 4.0.0.

There is a similarly functioning ^ operator in npm, PHP's Composer, and Rust's Cargo - though that their equivalent of the ~> operator doesn't function exactly like RubyGems.

What is your fix for the problem, implemented in this PR?

Added a ^> operator.

Also added a bump_major method to Gem::Version, which makes the code in Gem::Requirement a bit cleaner, and is conceivably useful in other circumstances.

Several notes:

  1. I don't know if ^> is the community preferred name; if people prefer ^ to more closely follow npm and friends, I'll gladly change.

  2. I am not sure if bump_major is the best name for the method in Gem::Version; I had considered "next_major_version", but bump_major seemed to fit closer with current method names.

I will gladly submit an update to change either of those decisions.

Make sure the following tasks are checked

@welcome
Copy link

welcome bot commented Aug 27, 2024

Thanks for opening a pull request and helping make RubyGems and Bundler better! Someone from the RubyGems team will take a look at your pull request shortly and leave any feedback. Please make sure that your pull request has tests for any changes or added functionality.

We use GitHub Actions to test and make sure your change works functionally and uses acceptable conventions, you can review the current progress of GitHub Actions in the PR status window below.

If you have any questions or concerns that you wish to ask, feel free to leave a comment in this PR or join our #rubygems or #bundler channel on Slack.

For more information about contributing to the RubyGems project feel free to review our CONTRIBUTING guide

@simi
Copy link
Contributor

simi commented Aug 27, 2024

🤔 Any reason to not call it just ^?

@djberube
Copy link
Contributor Author

djberube commented Aug 27, 2024

🤔 Any reason to not call it just ^?

The scheme followed by npm and composer seems to be not including the >, with ~ and ^ operators; RubyGems has ~>, and it seemed like ^> should follow that convention.

Either operator name, or some third option, is fine with me.

@deivid-rodriguez
Copy link
Contributor

See #3574 or #1919. Probably we can unify both of those in a single place.

I think the main thing that'd be needed here (even before deciding on how the operator will look like) is a good compatibility story.

@jeromedalbert
Copy link
Contributor

jeromedalbert commented Aug 28, 2024

gem 'something', '~> 3.0'

[...] version 3.0.2 comes out with some critical security fix, and the project admins want to make sure everyone has it

For this use case I think what most people do is bundle update something and push the updated Gemfile.lock to version control. This ensures that everyone in the project (existing developers and newcomers) has the version with the critical security fix the next time they pull.

For gem maintainers, this hasn't been an issue either. If their .gemspec contains spec.add_dependency 'something', '~> 3.0', and a 3.0.2 version comes out with a critical security fix, anyone installing that gem from then on will install the latest version that includes the critical security fix.

So, for RubyGems, I am wondering if there really is a need for a ^ semver operator like the one in this PR or the one mentioned in #1919 / #3574. Especially since the security fix use case can already easily be handled by updating the Gemfile.lock as explained above. Or I would be curious to know what other use cases I am missing.

@deivid-rodriguez
Copy link
Contributor

I could imagine some situation where one of your dependencies has a bug that makes your library quite useless, so you want to force a working version of the dependency. Maybe to avoid user reports coming your way.

If the minimum working version is not explicitly forced, users can of course still get the proper version of the subdependency through bundle update but, for example, bundle update --conservative won't update it. Also some other dependency may be blocking the upgrade of the subdependency, and the dependency author may want to choose that her library is also blocked in that case.

Overall, this would be a shortcut to things like >= 3.0.2, ~> 3.0. I think this operator would have limited usage, but some people would find it useful under certain situations.

@jeromedalbert
Copy link
Contributor

jeromedalbert commented Sep 5, 2024

Yeah ^3.0.2 could be a shortcut for >= 3.0.2, ~> 3.0. I am just wondering about the usefulness of such a shortcut for a use case with limited usage. On the other hand if some people would find it useful under certain situations then I guess it's a judgment call.

I am also wondering if ^, which could make sense for limited use cases, wouldn't get overused in Gemfiles by people coming from the JavaScript world since most libraries in a package.json file use that syntax (e.g. "bootstrap": "^5.3.3"). On the other hand if an operator is to be added at all I think ^ looks the most familiar.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants