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

Add new channels for long term support (LTS) releases #2483

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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 164 additions & 0 deletions text/0000-lts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
- Feature Name: lts
- Start Date: 2018-06-21
- RFC PR: (leave this empty)
- Rust Issue: (leave this empty)

# Summary
[summary]: #summary

Add an additional release channel for long term releases.

# Motivation
[motivation]: #motivation

Rust's current release model has, overall, worked very well for us. We maintain
a strong degree of backwards compatibility despite producing a new stable
release very frequently. Relative to many other languages, it is very easy to
upgrade between Rust stable releases.

However, for various institutional reasons, many users do not find it
convenient and desirable to upgrade with the frequency that Rust releases. So
Copy link
Contributor

Choose a reason for hiding this comment

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

IMO, this should be substantiated by at least some examples of the institutional reasons and the users, and that are specific to Rust.

far, they have been left on their own to figure out when to actually upgrade,
creating a situation of uncertainty and disparity. Moreover, because there are
no norms around when an older stable stops being "supported," libraries authors
experience a similar level of uncertainty around which versions of the compiler
their library should be compatible with.

We solve this problem by adding long-term support ("LTS") release channels,
providing explicit support for releases beyond the latest stable.

# Guide-level explanation
[guide-level-explanation]: #guide-level-explanation

## Two new channels: lts and lts-prior
Copy link
Member

Choose a reason for hiding this comment

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

It's unclear to me why two new channels are needed. Could you elaborate on that in the RFC?


In addition to `stable`, `beta`, and `nightly`, we will add two additional
release tracs:

* `lts`: The most recent LTS release.
* `lts-prior`: The second most recent LTS release.

Every fourth stable/beta release, we will perform a release on both the `lts`
and `lts-prior` channels. The **previous** stable release will be the basis for
the new `lts` release, and the previous `lts` release will move to the
`lts-prior` release. This is analogous to the way that the previous beta
becomes the new stable.

To keep it as easy as possible to remember which releases are lts release, we
will begin the lts schedule so that the point version of the LTS release is
always divisible by four. Depending on implementation schedule, that means that
Copy link
Member

Choose a reason for hiding this comment

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

I like the divisible-by-release-period. Nice touch 👍

the first LTS release will probably be 1.28 or 1.32, release concurrently with
either 1.29 or 1.33.

## Level of support from the Rust project

All three of the stable release channels - stable, lts, and lts-prior - will
receive the same level of support. We will host documentation for all three
channels and provide equivalent levels of patch release support - that is, if a
bug justifying a patch exists in any of these channels, we will release a patch
for that channel, just as we do today for stable. However, lts releases are
Copy link
Member

Choose a reason for hiding this comment

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

I think this is a good formulation of our current support, but I might like to see it laid out a bit better for LTSes, that is, can we refine this policy too? It's basically 100% subjective at the moment.

less likely to receive patch releases in practice, since these bugs are most
often found in the first six weeks after a stable release.

As a result of this, a stable release which is a candidate for the lts channel
(that is, its minor version is a multiple of four) will be supported across all
three channels for the following nine release cycles, a period of 54 weeks or
just over a year.

## Recommendations for library authors

Today, library authors fall into three general camps:

1. Their library compiles on the nightly channel.
2. Their library compiles on the stable channel.
3. Their library compiles on any release more recent than an arbitrary old
release, which is different for each library (for example, `failure` compiles
on 1.18.0, whereas `serde` compiles on 1.13.0).
Copy link
Contributor

Choose a reason for hiding this comment

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

Mostly unrelated, but worth mentioning -- Serde only supports 1.13 with default features turned off. With them enabled, it only supports 1.24 and later -- Diesel supports specifically that version since one of our dependencies requires serde and didn't set default-features = false. While not specifically related to this RFC, it's a larger problem that is tangentially related to the one this seems to be trying to solve.


Frequently, whichever level of support they offer, they guarantee it by testing
their code on that channel or release using CI.

The Rust project recommends that library authors interested in providing
support for users on versions older than the latest stable, instead of focusing
on supporting particular *versions*, focus on supporting particular *release
channels*. That is, a library may guarantee that it will compile on any of the
Copy link
Contributor

Choose a reason for hiding this comment

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

I think that doesn't work well and will lead to surprises for users.

Say that you start with adding lts to your Travis CI matrix... After half a year, lts will suddenly become a different version, and so you are testing a different version, instead of the one you were testing when you added lts into your matrix. Therefore, instead should become in addition to. Otherwise, a crate like serde will actually support fewer versions (provided --no-default-features per @sgrif's note).

Another way to solve this is to always increment the X in lts-X such that you can pin to a particular lts version. lts and lts-prior itself will refer to the highest X and X - 1. Backports will still only be provided for lts and lts-prior.

stable release channels, determining how old the version of Rust their users
can be on with a guarantee of compatibility.

We recommend that libraries consider dropping support for a release channel to
be a breaking change, but that dropping support for any particular version of
Rust to be a non-breaking change.
Copy link
Contributor

Choose a reason for hiding this comment

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

AFAIK, libraries have until now considered bumping the minimum stable release requirement to be a breaking change. This seems to weaken that guarantee considerably?

Copy link
Member

Choose a reason for hiding this comment

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

@Centril the question is contentious. This suggestion is somewhat of a middle ground.

Copy link
Contributor

Choose a reason for hiding this comment

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

@est31 Thanks for the link -- I haven't read the thread in depth, but think I agree with @KodrAus.

Copy link
Member

Choose a reason for hiding this comment

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

@Centril To summarize, I don't think there is actually any strong consensus on this point. Some libraries do as you say. Others adopt a different policy as a compromise where they are allowed to bump the minimum Rust version in minor version releases. Some libraries even bump the minimum Rust version in patch releases, although it is sometimes for good reason. This happened, in recent memory, with the log and rand crates, where they used the semver trick to make a patch release depend on a new minor release, which in turn required a newer rustc.

In my view, we're kind of all over the place right now. The best I've come to hope for is that library authors pin a Rust release in their CI so that it's at least easy to observe a possibly non-minimal lower bound.

I welcome a recommendation (such as the one in this RFC) that we can all unite around.

Copy link
Contributor

Choose a reason for hiding this comment

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

@BurntSushi Alright; Thank you for the summary. The policy mess sounds like a bad place to be in, I agree. I agree that there should be a recommendation to unite around, but I don't think it should be the one in this RFC.


If a library does not support a particular release channel, effectively all of
the libraries that depend on *it* also do not support that channel. For this
reason, we strongly recommend that so-called "core libraries" - those on which
many other libraries depend - adopt a practice of supporting all three stable
release channels. Examples of core libraries include libc and serde.

For libraries that do not believe they are "core libraries," we make no
particular recommendation about which channels to support. There is always a
trade off between providing the best API for users on stable as soon as
Copy link
Contributor

@Centril Centril Jun 22, 2018

Choose a reason for hiding this comment

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

In principle, I have no objection to providing LTS release channels if the bandwidth exists..

However, I believe the timing is not right and that this should be done in 2021. Why? Because the existence of LTS and the marketing thereof incentivizes supporting LTS releases and users will request that of libraries. I think that for the time being, there are important language features, such as:

  • Generic Associated Types (GATs),
  • const generics,
  • support for impl Trait in traits,
  • specialization

that would improve many APIs considerably, but which will not make it into Rust 2018.

I also think that the mechanisms to detect if a library path exists, or similar methods for ergonomic conditional compilation does not exist yet.

Therefore, I think we should wait until some important language features are in place.

Copy link
Member

Choose a reason for hiding this comment

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

@Centril But LTS releases, as proposed, are to supported only for about a year, so should not intefer with marketing of these language features. That is, the conservative people would have needed to upgrade 2-3 times anyways to get to 2021.

Copy link
Contributor

Choose a reason for hiding this comment

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

It is not the marketing of the features I'm concerned about, but how LTS releases and marketing thereof incentivizes libraries, to become, in my view, prematurely more conservative, and thus miss out on these specific features that are important for the public API of libraries. 2021 was just an example; it doesn't have to be that long. But I still think the time is not right, yet.

Copy link
Member

@tshepang tshepang Jun 22, 2018

Choose a reason for hiding this comment

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

@Centril I think the important libraries are already conservative anyways, meaning they don't bump minimum versions unless they "have to". What you are also asking is for someone to decide what future feature is worth waiting for, meanwhile we were able to get by without such features.

Copy link
Contributor

@Centril Centril Jun 22, 2018

Choose a reason for hiding this comment

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

@tshepang I don't think that is true. Some important libraries are conservative (serde). Others don't compile on stable yet (rocket). Other important libraries have breaking changes more frequently (syn). A library like diesel supports 1.24.1, which was released 2018-03-01, in its .travis.yml. Some libraries will/should be important but can't be made 1.0 yet due to lack of the specific features I've cited, in particular GATs.

What you are also asking is for someone to decide what future feature is worth waiting for, meanwhile we were able to get by without such features.

I think those features in particular, and especially GATs affect very much the fundamental nature of some library APIs (see StreamingIterator vs. Iterator). One can always "get by" with a very minimal mostly featureless language without parametric polymorphism and such things. But if you want more than "getting by", then good APIs depend on the abstractive power of the language.

I am not asking that everyone should wait for these features. They can always pin to some version of Rust like 1.13 as they've done so far. But if we're going to provide LTS releases, then our story around conditional compilation should first be improved, and these features, in particular GATs, important for the APIs of libraries, should be there first, in my opinion.

Copy link
Member

Choose a reason for hiding this comment

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

rocket and syn are special cases, the former explicitly target nightly, and the latter depends on recent compiler changes (I think), and I besides didn't consider it important, not in a sense that serde is important. The diesel one falls under "have to", as explained here #2483 (review).

Copy link
Contributor

Choose a reason for hiding this comment

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

rocket targets nightly because it has no choice but to (until proc macros land), which is precisely my point. There are fundamental language features which have not landed yet that important crates need. diesel, a central crate in the ecosystem, having to support 1.24.1 means that it wouldn't otherwise. This means that it would be even less conservative.

possible vs supporting users who choose to stay on older versions of Rust, and
each library should make a judgment call regarding the trade off in their
particular circumstances.

# Reference-level explanation
[reference-level-explanation]: #reference-level-explanation

Current policy is that the core team decides if a bugfix justifies a patch
release to the stable channel. This policy will remain the same for patches to
the lts and lts-prior channels.

# Drawbacks
[drawbacks]: #drawbacks

This increases the maintenance burden on the release and infrastructure teams
by adding two additional release channels.
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm currently skeptical that the bandwidth to do this release work and that the funding to support those doing the work exists. But I would be happy to be proven wrong.


This also muddies our recommendation that users upgrade to the latest stable,
which we have worked hard to make very easy to do. In particular, we should not
allow the existence of lts releases to justify reducing our effort to identify
and resolve stable-to-stable regressions.

Ultimately, users will continue not to upgrade to the latest stable, and
libraries will continue to want to support users on some older versions of
Rust. Providing a policy allows a better consensus to be formed around what is
supported and what isn't.

# Rationale and alternatives
[alternatives]: #alternatives

There are many ways to decide how to provide LTS support. We have chosen to
extend our existing channels mechanism by adding more channels, rather than
constructing a parallel LTS mechanism.

The main knobs within that context are in regard to when we choose to make lts
releases and how many lts channels we support. Our choice to support two lts
channels, released every 4 stable releases, is inspired by the ember project's
LTS system.

# Prior art
[prior-art]: #prior-art

Many different projects offer an LTS release. Our most direct inspiration was
the ember project. The ember project's LTS support is described well by both
Copy link
Contributor

Choose a reason for hiding this comment

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

This does surprise me. I would think that some of the users most interested in LTS releases are more industrial applications including embedded devices. I concur with others that something called "LTS" is surprising to only provide support for 6 months / 1 years.

Copy link
Member

Choose a reason for hiding this comment

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

@Centril Would you prefer it be longer than 1 year, or would you prefer it being called something else?

Copy link
Contributor

@Centril Centril Jun 22, 2018

Choose a reason for hiding this comment

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

I have no preference. But if we are going to call it "LTS", then I think it should be longer than 1 year. On the other hand, if it is longer than 1 year, then even more bandwidth will be required of the people doing the back-porting of bugfixes.

Copy link

Choose a reason for hiding this comment

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

Time to invent "MTS" (Medium Term Support) releases.

Copy link
Member

Choose a reason for hiding this comment

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

"long" is a relative term, and in this case, 1 year vs 6 weeks

an ember RFC and an ember blog post:

* [RFC 56: Refining the Release Process][ember-rfc-56]
* [Announcing Ember's first LTS][embers-first-lts]

The main deviation from ember's system is that, instead of providing multiple
levels of support for different lengths of time for each lts *release* (ember
provides "critical bugfixes" for 6 release cycles and "security patches" for 10
release cycles), we simplify the system by providing equivalent support among
all three stable release channels, having the effect of providing all critical
bugfixes and security patches we provide to stable today for 9 release cycles
for LTS releases.

# Unresolved questions
[unresolved]: #unresolved-questions

None known yet.

[embers-first-lts]: https://emberjs.com/blog/2016/02/25/announcing-embers-first-lts.html
[ember-rfc-56]: https://github.com/emberjs/rfcs/blob/97a92311646624996feba45226f82059858c14f3/text/0056-improved-release-cycle.md