Skip to content
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

Bundler release channels #12

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
70 changes: 70 additions & 0 deletions text/0000-release-channels.md
@@ -0,0 +1,70 @@
# Bundler release channels

- Feature Name: release\_channels
- Start Date: 2018-06-30
- RFC PR:
- Bundler Issue:

# Summary

Bundler release channels allow users to opt in to the level of release stability that they want. The “canary” channel has a release from every commit that builds green. The default channel has regular releases when features and bugfixes are ready. The “stable” channel only has releases that have fixes for any issues found by the default channel. When possible, bugfixes are backported from the default channel to the stable channel.

# Motivation

As the developers of Bundler, we want to be able to continue to develop and revise Bundler into a better version of itself. As users of Bundler, we want the safest, most stable, least problematic version of Bundler at any given time.

Release channels are a way for the Bundler team to officially bless and support versions that have proven themselves to be stable. It also adds an easy and straightforward way to try the latest upcoming changes to Bundler at any time, increasing the chances that bugs can be found and fixed.

With the stable channel, this RFC aims to actively support the usecases of users deploying Ruby code to important production servers. With the canary channel, this RFC aims to actively support power users, Bundler contributors, early adopters, and anyone who wants to participate in the future of Bundler.

Hopefully, release channels will allow Bundler to change and move forward more easily, while at the same time providing even more stability as an option for users who care most about that.

# Guide-level explanation

To use the default release channel, install the Bundler gem and use it as usual. For example, you install Bundler by running `gem install bundler`, and you install gems by running `bundle install`. The default release of Bundler will let you know anytime there is a newer default release available, but will not install it for you.

To use the stable release channel, instead install with `gem install bundler-stable`. Install gems as usually, by running `bundle install`. The stable version of Bundler will let you know anytime there is a newer stable version available, but will not install it for you. You can identify stable releases of Bundler by running `bundle install --version` and looking for `(stable)` in the output.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont understand how this will work, technically speaking

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think one option is shipping a bundler-stable gem that overwrites the bundle binstub to point to the bundler-stable gem instead of bundler. (Release channels are global 😛). Maybe another option is to double down on our RubyGems Bundler-loading hackery and prefer the latest stable if it is installed at all?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm tempted to ask this question: would we be better off adding some support for this into rubygems


To use the canary release channel, instead install with `gem install bundler-canary`. Install gems as usually, by running `bundle install`. The canary version of Bundler will continuously keep itself up to date, installing the latest canary version (if you don’t already have it) during any `bundle install`. You can identify canary versions of Bundler by running `bundle --version`, and checking the output for `(canary)`.

# Reference-level explanation

Default releases are created using today’s release process, running `rake release`. Maybe default releases could be the same as canary releases, but with different feature flags?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not clear to me why gem install bundler don't install what you are calling the stable channel and gem install bundler-canary install what you are calling the default channel, care to expand the reasoning why the we have the tree channels instead of only two (canary and stable)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I can take another stab at it. Most users want a "pretty stable" version, with "pretty recent" bugfixes. The current releases try to do that, striking a midpoint between release frequency and release stability.

If we made gem install bundler install the stable channel, nothing would change from how things are today... most users would not run into bugs until the wide release, many users would run into bugs on each release, and Heroku would continue to not upgrade for months or years in an effort to stay away from new issues.

This RFC is an attempt to offer a different option, where opting in to the canary channel can either be a way to get the latest build from the master branch or be a way to always use the most recent version of Bundler that has passed all the tests in order to provide feedback.

The regular release channel then becomes the second tier of frequency/stability. We'll continue to fix known bugs before releasing, and hopefully more bugs will be caught thanks to the help of canary users.

Finally, the stable release channel is a way for most or all edge cases to be caught before we ship a release suitable for Heroku or other PaaSes to use—after a huge number of regular users have tried the release and we have ironed out any additional bugs.

In practice, this three-tier system is what we already have. Cutting edge users install Bundler from git, regular users run the latest regular release, and Heroku only installs a single carefully selected bugfix release once every 2-3 years. This RFC is about making it easier for all of those groups to participate, give us feedback, and install new releases with less stress.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense and I like the plan. How would the BUNDLED_WITH option works for cases were users have the regular channel and their machine but deploy to an infra that uses the stable channel. Would it show a warning? I believe that warning will not be actionable for the developer, so maybe it will be perceived as noise and ignored most of the time?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'm not sure what would be best. We can either leave the warning the way it is today, and it will be noise/ignored, or we can change the warning to check for newer versions only on the specific channel that is installed. I think either one of those would probably be fine?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checking new versions of the specific channel would be ideal, but if that requires a lot more code we can leave the warning in the way it is today.


Stable releases are created by running a new rake task, `rake release:stable`. Rather than creating a new version from the latest commit, `rake release:stable` takes an existing version of Bundler as an argument, and releases that version to the stable channel. The rake task needs to check out the tag, edit the gemspec to change the name of the gem, and then build and push to RubyGems.org. Minor versions probably should not be promoted to stable until they have had at least one bugfix release or two weeks in the default channel with no significant issues.

Canary releases are created automatically from Travis CI anytime the build passes with the latest released Ruby and RubyGems versions. The canary release task edits the gemspec to change the gem name and append the first 6 characters of the commit sha to the end of the version.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could that lead to non-monotonic version numbers ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we would need a timestamp-derived section of the version number as well, to ensure it would be monotonic.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or something like git describe: v1.16.2-490-g34f909fc3

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That version example is not user friendly. Try to keep it a simple 3-4 digit number. 🙂

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect, we'll append the three-digit swatch beat number (😂) at the time of the release, and then add the git sha to the end of that so we can trace to a specific commit if needed.


We’ll likely need to update `bundle env` to include channel information.

# Drawbacks

We might not want to do this if we think it would be more development effort than is worth the benefits of having multiple release channels.

This change increases the possible number of Bundler versions in the wild, so it will likely increase the workload for maintainers by at least a small amount.

Adding a stable channel means supporting one older version of Bundler for longer than our current support plans, which is likely small but still some more additional work.

# Rationale

The Bundler team deals with the tension between stability and change on a daily basis. With the tens or hundreds of thousands of users that Bundler has, it feels impossible to satisfy everyone with every release.

Release channels tries to make it possible to satisfy everyone, by dividing users into groups based on risk tolerance, and deliberately aiming for that level of risk. Adding stable releases might make it possible to support default releases for less time overall, to try to balance out the overall support load.

The strategy proposed in this RFC (or something very similar) is currently in active use by the Rust language, the NPM package manager, and the Ember.js framework, among many others. It seems to strike the best balance, allowing ongoing development work while protecting production systems from changes and accidents as much as possible.

If we don’t do this, we will continue to struggle with the existing problem of strongly conflicting expectations and tensions within the user base for each version of Bundler that is released.

# Alternatives

Instead of releasing to canary with every commit, we could release to canary on an automated cadence, like every 24 hours.

Other possible solutions to this class of problem include: the Unix and early Ruby strategy of alternating stable and unstable releases, declaring all releases unstable except one blessed release per year or quarter, or any other option to classify some versions as stable and some as unstable.

# Unresolved questions

The details of how to release, when to release, how feature flags interact with release channels, and how to distinguish channel releases all likely need to be worked out before implementation.

It would be a wonderful next step (albeit out of scope for this RFC) to ship and support one Heroku buildpack for each Bundler release channel, so that Ruby developers on Heroku can easily test each channel, give feedback, and provide bug reports _before_ Bundler releases are rolled out to all Heroku users.

Questions about breaking changes, how long to support versions, support for versions of Ruby or RubyGems, and integration with RubyGems all seem out of scope for this specific RFC.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might want to say about the subject of an LTS version, then?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I'm not sure what you mean by this. Can you elaborate or rephrase?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the subject of a Bundler long term support version on the table for the RFC, or is another topic

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A true LTS version would be another RFC. This RFC is purely about providing opt-in release candences, and inherits the existing support policy, which is iirc “majors get features and bugfixes for one year, and might get bugfixes for a second year but backports are not guaranteed”.