Skip to content

Commit

Permalink
Add "Bundler version locking" RFC.
Browse files Browse the repository at this point in the history
  • Loading branch information
duckinator committed Sep 1, 2020
1 parent aa031d3 commit 6459b08
Showing 1 changed file with 142 additions and 0 deletions.
142 changes: 142 additions & 0 deletions text/0000-bundler-version-locking.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
- Feature Name: bundler_version_locking
- Start Date: 2020-09-01
- RFC PR: (leave this empty)
- Bundler Issue: (leave this empty)

# Summary

If a user specifies a required Bundler version in the Gemfile/gemspec, it should be installed and used during the normal `bundle install`/`bundle exec` workflow.

# Motivation

There are many times where locking your Bundler version is useful. The existence of `BundlerVersionFinder` shows that, but that approach clearly has not worked. **This RFC assumes that `BundlerVersionFinder` is removed first. The discussion on whether or not to do that should be had elsewhere.**

# Guide-level explanation

## Example 1

For this example, assume Bundler 2.1.4 is installed but Bundler 2.0.2 is not.

Gemfile:

```
source "https://rubygems.org"
gem "bundler", "= 2.0.2"
```

Output:

```
$ bundle install
Bundler 2.1.4 is being run, but "Gemfile" requires version 2.0.2.
Installing Bundler 2.0.2...
(... output of installing Bundler 2.0.2 ...)
Switching to Bundler 2.0.2...
(... rest of output, as normal ...)
$ bundle install
(... normal output ...)
```

## Example 2

For this example, assume both Bundler 2.0.2 and Bundler 2.1.4 are installed.

Gemfile:

```
source "https://rubygems.org"
gem "bundler", "~> 2.0"
```

Output:

```
$ bundle install
Bundler 2.1.4 is being run, but "Gemfile" requires version 2.0.2.
Switching to Bundler 2.0.2...
(... normal output ...)
```

## Example 3

For this example, assume both Bundler 2.0.2 and Bundler 2.1.4 are installed.

Gemfile:

```
source "https://rubygems.org"
gemspec
```

blah.gemspec:

```
<...>
spec.add_development_dependency "bundler", "~> 2.0"
<...>
```

Output:

```
$ bundle install
Bundler 2.1.4 is being run, but "blah.gemspec" requires version 2.0.2.
Switching to Bundler 2.0.2...
(... normal output ...)
```

## Example 4

For this example, assume both Bundler 2.0.2 and Bundler 2.1.4 are installed.
Note that since the default behavior is to run the newest version installed, and that matches the requirement, it never needs to switch versions.

Gemfile:

```
source "https://rubygems.org"
gem "bundler", "~> 2.1"
```

Output:

```
$ bundle install
(... normal output ...)
```

# Reference-level explanation

First, the `BundlerVersionFinder` would be removed, as mentioned in "Motivation."

Then, Bundler would do the following when `bundle` is executed:

1. If the first argument isn't `_<bundler version>_` _and_ the Gemfile/gemspec specify a required version of Bundler _and_ the requirement isn't met by the currently-running version:
a. Install the required version of Bundler, if needed.
b. Replace the current process with `bundle _<required version>_ <args...>` (e.g. something along the lines of `Kernel.exec("bundle", "_#{required_version}_", *args)`)
2. Run as normal.

# Drawbacks

TBD. (I'm sure there are some.)

# Rationale and Alternatives

The main alternative is a refinement of the BundlerVersionFinder, but I think the approach in this RFC better follows the [principle of least surprise](https://en.wikipedia.org/wiki/Principle_of_least_astonishment) by relying on existing knowledge and assumptions.

The approach in this RFC tries to ensure:

1. It is inherently opt-in: it won't do anything if you don't explicitly list Bundler as a dependency.
2. The user has more control:
- It's opt-in, so it won't get in the way if it's not actively wanted.
- By implementing it in terms of the `_<some version>_` feature, we provide a way for users to override the behavior if needed.
3. It builds on existing conventions:
- Locking the Bundler version is done in the same place and way as any other dependency.
- Changing the locked Bundler version is done the same way as any other dependency.

# Unresolved questions

There are many quality-of-life things that could be added, like telling users if they're relying on an outdated Bundler version, but I feel this can be added after the fact.

0 comments on commit 6459b08

Please sign in to comment.