Replies: 11 comments 48 replies
-
I like the idea of clearly specifying this file and bundler may be a good central place to do it. As far as I know, this is the original specification/proposal to which modifications have been made by various ruby version managers. Supporting I also like adding support for engines as well as relaxed version matching (something bundler is very good at, ironically). |
Beta Was this translation helpful? Give feedback.
-
@martinemde A starting point for a See this README and its history for the living first draft of such a spec based on this discussion. After brainstorming such a minimal ruleset here, we could open a new discussion and then contact the maintainers of all common version managers to ask for feedback. If we reach a consensus, the ruleset could be published as a guide on rubygems.org (maybe with a heads-up to some very common PaaS such as Heroku, Render etc) I guess, relaxed versions could be controversial since they depend on context and therefore might break the principle of least surprise. However, there are situations where they come in incredibly handy. And along with a word of warning in the specification, it shouldn't be a problem. After all, nobody is forced to use this notation. At least some Ruby version managers support this already. What do you think? So, time to wrap it and get ready for the party! Happy new year!! 🍾 |
Beta Was this translation helpful? Give feedback.
-
Suggestion: Clarify that the final newline is optional. (I remember an issue with one tool because it wasn't handling both cases). |
Beta Was this translation helpful? Give feedback.
-
Thanks for starting this thread and initial ideas of what the spec can be! I think the specification can be more simple in what we want to allow for.
Can we just allow for only one dash? I guess asdf allows for whitespaces but I'm assuming they do support
I see that comments may be helpful, I don't think it's worth the added complexity. I would want |
Beta Was this translation helpful? Give feedback.
-
Per my understanding Ruby version specified in Gemfile must be unique, otherwise it makes no sense to lock it with. Currently Bundler locks Ruby (when present in Gemfile) using following logic to find out the version (if I remember well). rubygems/bundler/lib/bundler/ruby_version.rb Lines 104 to 111 in 457c3be 🤔 If you need reusable piece of code, you're most likely looking for |
Beta Was this translation helpful? Give feedback.
-
What does .ruby-version represent?While I commend the effort to standardize the .ruby-version file, I'd like to also codify what it actually is. I don't mean to derail the discussion, but I think it's important to clarify since the syntax of the file should be influenced by its use case(s). I think the various threads about fuzzy versions hits upon this. As a loose specification, I've always understood it to mean "this is the version the devs are working with" and not "this is the only version this application works with". Indeed, if you don't have the version declared in .ruby-version installed, Ruby version managers will happily activate your default Ruby and most of the time that works fine. Moreover, Ruby goes to fairly extensive lengths to ensure backwards-compatibility. In that light, I can also see the .ruby-version file to mean "this is the minimum version we anticipate working." I'm not a fan of making the .ruby-version file a variant of a lock. Its integration into Gemfile complicates the picture. From my perspective, that move shifted .ruby-version went from being a convenience in activating Ruby versions as you switched between projects to a declarative configuration of the project. I don't believe there's consensus on that transformation. Maybe there is, but we should be deliberate about it. There are a few situations that come to mind that a restrictive lock complicates:
I'm quite in favor of making .ruby-version a convenience, not a lock. Regardless of whether we want to support fuzzy versions, I don't think Bundler's integration of .ruby-version should influence that. If Bundler wants to lock down to a specific version, then it can opt to only accept a subset of the .ruby-version syntax. Fortunately, since we're defining what that syntax is, that should make things easier for Bundler. Depending on what we determine a .ruby-version file is, it could make sense for it allow for multiple values. If we want to say the file indicates the supported Ruby versions, then having a list would help convey that information better. For compatibility, I'd suggest the first line is the "default". I suppose at that point it might make more sense to call it .ruby-versions. |
Beta Was this translation helpful? Give feedback.
-
Optional Ruby EngineWith regards to Ruby engines, I haven't seen anything other than CRuby mentioned yet. For my part, requiring the engine as part of the version simplifies things. While "3.3.0" is more convenient to type, using "ruby-3.3.0" normalizes the syntax with what we do for JRuby ("jruby-9.3.4.0"), TruffleRuby ("truffleruby-23.1.2"), mruby ("mruby-3.2.0"), and others. Beyond consistency, it would allow us to cut out some extra complexity in allowing "3.3.0" to be an alias for "ruby-3.3.0". With that said, I think it's impractical to move away from the simplified version specifier. Grammatical normalization aside, the simplified version has been inserted into many repositories and Rubyists are conditioned to treat the .ruby-version specifier the same as whatever a Ruby version manager or installer supports. Since that coupling isn't a requirement, independently of whatever .ruby-version uses, there's plenty of code out there that drives ruby-build, rbenv, rvm, etc. with the simplified version and breaking those isn't ideal. |
Beta Was this translation helpful? Give feedback.
-
Alternative Ruby EnginesWith regards to alternative Ruby engines, we need to define what's permissible. With the ad hoc system we have now, new Ruby implementations largely get to choose what the engine identifier is and that gets propagated through the various Ruby version managers and installers. While it would simplify parsing, I think it would be too restrictive to hard-code the list of valid engine identifiers. But, if we leave it open-ended, then the question shifts to how consumers agree on what those identifiers should be. E.g., it wouldn't be terribly helpful if two different consumers parsed .ruby-version and one expected an "rbx-" prefix and another expected "rubinius-" when specifying the Rubinius version. Ruby has had a rich history of alternative Ruby implementations and I think we should put up as few hurdles as possible to rapidly adopt them into standard tooling. We could maintain a list of identifiers in a community repository. It wouldn't be terribly different from what we have now with the various Ruby version managers and installers defining those engine identifiers. A central repository, however, is another thing to maintain and risks becoming bureaucratic. |
Beta Was this translation helpful? Give feedback.
-
Different Build ConfigurationsAnother piece of syntax to consider is different build configurations. I could see a case where Rubies ship with both libc and musl builds or maybe with different malloc implementations. We run into something like this already with TruffleRuby. Each release of TruffleRuby ships as a standalone native binary or as a distribution based on the JVM. Currently, we use something like "truffleruby-23.1.2" to indicate the native build configuration and "truffleruby+graalvm-23.1.2" to indicate the JVM (GraalVM) build. Packing all of that info into one string has made it easy to integrate with the Ruby version managers and installers, but using a structured file (e.g., with |
Beta Was this translation helpful? Give feedback.
-
Here's a weird, probably too complicated idea for which I will start a new thread. Rubygems and Bundler target Ruby 3.0, 3.1, 3.2, 3.3, and 3.4. What would the various version managers do if I put each of those in
I only have What could you do with this?This specifies all valid rubies for a project. Any of them are allowed but the top one is selected automatically if you're not already using another compatible version. I think this solves an issue where a gem can't have a .ruby-version file. This also solves for cases where something targets multiple engines and they are equally important. Version managers could also become smarter about switching, maybe making it easier to swap between usable versions or test against multiple. This says nothing about how Bundler will handle it. Probably Bundler locks to the top one in this crazy alternate world. If the other version managers ignore this too it could be an interesting way to solve a few of the problems that keep coming up with this file. |
Beta Was this translation helpful? Give feedback.
-
In case this discussion and the feedback from the Ruby version manager maintainers reaches some consensus, where would you like to see the There are not too many places which come to mind, at least not to mine: What do you think, are there any other, better places maybe? |
Beta Was this translation helpful? Give feedback.
-
The
.ruby-version
file emerged somewhere between different Ruby version manager ecosystems, however, it's never been formally documented to my knowledge. I'm interested in your thoughts on this.UPDATE: See this README and its history for the living first draft of such a spec based on this discussion.
Now that the latest versions of Bundler support
ruby file: ".ruby-version"
, maybe Rubygems (and Bundler as a part thereof) would be the right place to give this omnipresent file a home. (Btw, there's no mention offile:
on https://bundler.io/guides/gemfile_ruby.html as of yet.)The trouble I have with an undocumented
.ruby-version
are edge cases as the ones mentioned below. A single point of truth to clarify these cases (and maybe more) would help adopters anywhere to be compatible – Ruby version managers, hosting services like Heroku or Render, custom code and of course Bundler itself.Relaxed Ruby Version
Say you want your project to always be on the latest PATCH version of Ruby 3.2 (at the time of writing that's Ruby 3.2.2), you could set the following in
.ruby-version
:This does work with some Ruby version managers, certainly does for my homebrew solution based on direnv. However try the following in the corresponding
Gemfile
:Installing the bundle will fail with:
For it to work, you'd have to work around this with something along the lines of:
Engine or Not?
Some Ruby version managers allow the selection of the engine in
.ruby-version
as well. The following two are therefore equivalent and both choose CRuby:Beta Was this translation helpful? Give feedback.
All reactions