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

doc: add releases document detail release cycle #630

Closed
wants to merge 1 commit into from
Closed

doc: add releases document detail release cycle #630

wants to merge 1 commit into from

Conversation

chrisdickinson
Copy link
Contributor

Add a release cycle document covering use of semver, LTS releases, support releases, train system, and git branching model.


Topics I am seeking feedback on: Everything generally, but in particular:

  • Until async-listener is released, a weekly release cycle is going to create epic amounts of work for anyone instrumenting io.js. Do we want to downsample the "stable" releases? Or do we want to wait to implement this until we have a proof of concept for async-listener?
  • Distribution linking. These are essentially human branch names as proposed, but I'm not sure in what form they should be best made available to downstream packagers.
  • Semver: I'm still on the fence about the "major bumps except for NAN" bit, but I'm happy to adopt that and see how it fares.
  • Git branching: this puts us back on master, and makes the vN.x branches a pre-release phenomenon – that is, as v2.0.0 gets released, a v1.x branch is cut and master becomes the work on the v2 major version.
  • Is this too complicated?

cc @iojs/tc @iojs/build @iojs/collaborators @domenic @wraithan

Add a release cycle document covering use of semver, LTS
releases, support releases, train system, and git branching
model.
@Qard
Copy link
Member

Qard commented Jan 28, 2015

I'm curious what makes you think instrumentation work would be made more difficult by the frequent releases.

AppNeta uses async-listener indirectly via continuation-local-storage. New Relic does pretty much the same thing, as far as I'm aware. As long as CLS has something to hack itself onto, everything should work as-normal.

@chrisdickinson
Copy link
Contributor Author

@Qard the maintainer of async-listener/continuation-local-storage will have to evaluate every minor and patch version to make sure it works across all extant versions of io.js so long as those libraries rely on monkeypatching – not just what's supported by us, but also the releases in-between. @wraithan can make a better argument for this position, though.

@wraithan
Copy link

@Qard I think @chrisdickinson is referring to the async-listener that used to be in core and was pulled when he says until async-listener is released. And I stand by what I said about every single version having to be vetted for various new or different ways to invoke asynchronous things. If you depend on those libraries then you know how important it is to wrap every single async boundary and how lossy the data gets when you don't.

Instead of attacking this the same way I have been, I'm going to try a new approach. Instead of having to defend 1 week being too fast. I'd like to put 1 week to maintain momentum on trial.

We have to consider who's momentum that we are concerned with losing. The people are the things that can gain or lose momentum really so we'll start there. Those with commit bit are working on various problems, almost always when I talk with anyone in that area, they are talking bout various large projects they are working on. I'd like to see how often patches are being proposed by core and how long they sit in PR status before being merged. My gut instinct would be a few a month and at least a week on average in PR status. That considered, what is another week or two before it goes live? You wont be losing core over making the release cycle slightly slower, at least not for 'momentum reasons' though maybe for pride reasons.

Next we'll go into the mind of a contributor, someone who has an idea, found an issue, etc and is presenting a patch for it. Now I know those take a while to review as I've been that person on a lot of open source projects. I know that often having the fix released sooner rather than later is preferable. But I know that io.js is a platform, and if io.js had a predictable release cycle of 2 or 4 weeks instead of weekly, I can't see myself being any more discouraged. Maybe I'm speaking for too many people here but, it is known that the PR -> release process for any project is often longer than a week.

Say I submit a patch.

  • 2 years to release and I've given up, moved on and am probably done ever contributing.
  • 6 months to release and I might still be around, but discouraged from submitting more.
  • 3 months to release and I probably still care about the bug and want it fix, it is taking too long but I've not yet given up hope.
  • 1 month to release and I'm a little frustrated but overall pretty happy, especially if it is just part of the regularly scheduled release.
  • 2 weeks to release and I'm stoked, couldn't ask for more. Life is 100% great and I'll of course submit again.

We are talking at most 2 week and as little as 1 week from merge to release. And that would exceed any expectation that I'd ever have for project. Assume that people average landing in the middle of a release cycle and every 2-4 week cycle. Average would still be well within the "I'm motivated to contribute more" range I think. Especially if the PR was promptly commented on and such.

Taking all that, and my typical argument against 1 week due to the treadmill you put every single library author on, I can't see why 1 week is required or even desirable.

@Fishrock123 Fishrock123 added the doc Issues and PRs related to the documentations. label Jan 28, 2015
@chrisdickinson
Copy link
Contributor Author

The sample rate from dev to next can be tweaked (per @wraithan's request). Here's the result of increasing it, for those interested:

sample rate = 1 week sample rate = 2 weeks sample rate = 3 weeks
weeks from merge till release on stable 1-2 2-4 3-6
number of releases for which a given version of v8 will be in use 6 3 2

@rvagg
Copy link
Member

rvagg commented Jan 28, 2015

@chrisdickinson I'm having trouble seeing how this plays out in practice in terms of how release and how we version those releases. Can you give some examples of what the version strings would look like and in what sequence and for what release line? Also interesting would be how you imagine people access these releases, perhaps some download URLs and how we promote them on iojs.org? The complexity of this leaves me scratching my head and just thinking how impossible the messaging will be since we're so strongly dedicated to following semver. It's already hard enough telling people not to expect too much support for their particular problem because they are using Node 0.11 and "should be using stable". It's surprising how poorly even the odd/even messaging for Node.js releases are understood with people just picking the highest number and rolling with that. What you're proposing, when coupled with semver, sounds exponentially more difficult to message.

@Qard
Copy link
Member

Qard commented Jan 28, 2015

I worry this might be premature optimization. When a new version lands, I just run my test suite on it and make any necessary changes. It's never taken more than a couple hours to fix--typically I don't have to change anything. I get a new release out before our customers even realize there's a new version of node/iojs.

I can't imagine it being much more complicated for New Relic, considering we all do pretty much the same thing and they have a much larger team.

Personally, I just want to see io.js progressing at a pace where people can contribute and feel like they are actually making a difference. If you think that'll be challenging to keep up with, well, challenge accepted!

@chrisdickinson
Copy link
Contributor Author

Putting aside LTS and support branches for now, the release lines I've proposed – "dev", "next", "next+v8", and "stable" are essentially tagged releases.

During the course of the week, on master, we can say that we'd like to roll a release (v2.0.2). That bumps the semver version appropriately based on the changes the release contains. We choose to do another release that week (v2.1.0). At the end of the week, v2.1.0 is promoted to "next." Now, an aside to examine the state of the world thus far:

At this point, we have three tagged releases:

  • v2.0.2-dev
  • v2.1.0-dev
  • v2.1.0-next

The previous release on "next" was v2.0.0. It is promoted from v2.0.0-next to v2.0.0-stable. Whenever a release is promoted to "next," the work necessary to update to the current unstable V8 is applied, and the result of applying unstable V8 to next is released, in this case, as v2.1.0-next+v8[*]. The state of the world is now as follows:

  • v2.0.2-dev
  • v2.1.0-dev
  • v2.1.0-next
  • v2.0.0-stable
  • v2.1.0-next+v8

The tags I've suggested – "dev", "next", "stable", "next+v8" could be subbed out for other tags ("alpha", "beta", "rc", for example). Users would access these versions, as @domenic suggested, through the website using something like ember's icons for "canary", "beta", and "stable" icons. Users would not need to examine the version number to make decisions about what they need to download.

This serves folks who need a train release cycle to have adequate time to test their packages against upcoming versions, as well as those who can afford to be "close to" the cutting edge. But for those that can't afford to track that close to edge, or update that often...

For that audience, there are support and LTS branches (coming back to these). These releases are meant for package maintainers and other folks who can't upgrade more than once or twice a year. The intent here is to backport security and bug fixes only to these branches, and to base them off an existing known stable version of io.js. These releases would be downplayed on the main website, but available for those that need them. While we could deal with this as we come to it, it would be good to at least have this as a statement of intent for the audience these releases serve.

Re: the merging model – I think we're going to need to switch to master sooner rather than later, as we run into major-version changes. Cutting the major version branches after the fact lets us maintain those versions after release, supporting with backported patches.

@chrisdickinson
Copy link
Contributor Author

@Qard:

I worry this might be premature optimization.

I probably should have linked to the release versioning issue. This also came up in the state of ES6 issue, and another version of the same was proposed by @wraithan in another issue. This is part of the work of aligning with the V8 release cycle – it's a starting point for discussion on how we go about implementing what we said we were going to do.

Personally, I just want to see io.js progressing at a pace where people can contribute and feel like they are actually making a difference. If you think that'll be challenging to keep up with, well, challenge accepted!

The reason for the release cycle is explicitly to avoid slowing us down – it's there to keep momentum going, while giving downstream folks enough time to vet our changes. We can release every day of the week and get feedback about last weeks work before it becomes the "blessed" release. The promotion of "next" to "stable" (and "dev" to "next") is there to prevent a v0.12 branch situation, where code is being written frequently but not run by our users.

@Qard
Copy link
Member

Qard commented Jan 28, 2015

I was just referring to worries about instrumentation writers keeping up while there's no official async-listener. Personally, I'm not worried.

@bnoordhuis
Copy link
Member

I agree with @Qard. I work on a similar product and I'm not worried. We've got good enough test coverage that issues are tracked down quickly, it even finds regressions in io.js occasionally (e.g. #628).

@chrisdickinson The versioning you propose here seems very complicated and difficult to communicate to users. Ideally, we would have -stable and -next and that's it. -next rolls over to -stable every six weeks, after which the new -next upgrades V8 and lands any pending semver-minor patches.

I do see the value of having more branches - we can try out upcoming V8 releases earlier, and we'll be able to do code freezes without bringing all development to a halt - but it's almost inevitable that some branches will end up getting more attention than others.

(Also, if -beta is a snapshot of the -next branch, then it's useless for testing; bug reports would have to be checked against -next because it might have been fixed already.)

Last but not least, the messaging gets more complicated - but I already said that. :-)

@domenic
Copy link
Contributor

domenic commented Jan 28, 2015

FWIW on Chrome the expectation is that each additional branch takes 10% of the users from the previous branch. (So, stable gets 90%, beta gets 10%, dev gets 1%, canary gets 0.1%.) Four branches might make sense for a product with user numbers like Chrome's; not so sure it makes sense for something with the audience of io.js.

@chrisdickinson
Copy link
Contributor Author

This kind of feedback is what I was looking for :) To recap where we're currently at: we have two release channels, "nightly" and "release." There is no "canary" or "next" channel. The proposed version has 5 channels (4 plus an implicit "nightly" channel.)

Dev releases are there so that we can 1) ad-hoc release, and 2) have a dedicated channel on which we make semver updates. Nightly and dev might be able to be combined. If we update the semver as things get merged, nightly can fulfill dev's purpose, and "next" can sample nightly at the one or two week rate proposed. Alternatively, we release into "next", and have "stable" sample "next", though this means that there are no guarantees for the amount of time a given "next" release will be available before being promoted to stable.

"next+v8" is there specifically for tracking changes to the next version of v8, and making those available to users who are interested. The other function it provides is decoupling the act of releasing io.js from updating V8 immediately, which makes it possible to work on the current version of io.js on master.

We're left with the three desired channels: "nightly", "next", and "stable," and a small "v8next" side-channel for tracking v8 changes. These release channels are not git branches, they represent distributions on the website.

The vN.x support and LTS branches are git branches, and exist so that we can support recent major version releases for a bit longer, without them becoming the primary branch of development / having to go through the "merge to v0.10, merge up to v0.12" process. These exist specifically for users that can't track the latest stable.

@domenic
Copy link
Contributor

domenic commented Jan 28, 2015

Here is an alternative proposal.

  • master branch => nightly builds. Version numbers x.y.z-nightlyaaaaa
  • master+v8 branch => nightly builds with next V8. Version numbers x.y.z-nightlyv8nextaaaa
  • cut releases from master at will. Version numbers x.y.z

That's it. Optionally add LTS branches if we decide to do that at some point.

People can test nightly or nightly+v8next if they want things ahead of time. Otherwise we maintain the rapid release cycle and single codebase without parallel trains.

This was referenced Jan 30, 2015
@mgol
Copy link
Contributor

mgol commented Feb 7, 2015

Semver: I'm still on the fence about the "major bumps except for NAN" bit, but I'm happy to adopt that and see how it fares.

Doesn't it mean, though, that every time the v8 C++ API introduces a breaking change, all modules that depended on an explicit nan version (as opposed to using semver ranges with the ^ or ~ operator) may be broken until they update their internal nan copies? That makes me a little uneasy. That would also mean packages that specify a semver range for nan but use shrinkwrap will suffer the same.

If I understood it correctly then what is the solution? One possibility would be to include nan directly in io.js and change the nan package to check for the built-in module first and only then fallback to the package implementation.

@sam-github
Copy link
Contributor

@mzgol no module should depend on an explicit nan version. nan itself will (edit: I mean does follow semver) follow semver, depending on an explicit nan version is the equivalent of saying "I explicitly do not want my code to work with newer versions of iojs, even though an API compatible update of nan would be released that would allow me to do that with zero changes to my code". So, if you do that... you get what you asked for.

@mgol
Copy link
Contributor

mgol commented Feb 9, 2015

But that also means that if you shrinkwrap your dependencies, you're saying
"I don't want my package to work with newer io.js versions". And some
projects do shrinkwrap their deps (for good reasons), no one has said so
far that it'd block further io.js compat.

cc @othiym23

Michał Gołębiowski

@othiym23
Copy link
Contributor

othiym23 commented Feb 9, 2015

@mzgol

all modules that depended on an explicit nan version (as opposed to using semver ranges with the ^ or ~ operator) may be broken until they update their internal nan copies

Those packages are already playing with fire, though. Since the whole point of nan is to provide a compatibility layer, pinning to a specific version of nan is going to interfere with its ability to act as a stable abstraction layer.

And some projects do shrinkwrap their deps (for good reasons), no one has said so far that it'd block further io.js compat.

I don't think this problem is specific to io.js. We've got many versions here:

  1. the platform version (io.js 1.2.0, node 0.12.0)
  2. the engine version (V8 4.1, 3.28)
  3. the nan version (1.6.2)
  4. the dependency version
    (also maybe 5. the node-gyp / pangyp / npm version)

npm shrinkwrap is really only meant to deal with 3-5, not 1 or 2. The implicit contract, which hasn't been much of an issue until now, is that a given shrinkwrap file version should be assumed to be for a given version of the platform. But if you've got a package that depends on, say, --harmony providing generators support, there's an implicit dependency on 1 or 2 regardless that npm shrinkwrap can't abstract away.

This is why I recommend npm shrinkwrap be used as a last step when preparing to deploy an application. Yes, people do shrinkwrap libraries, but that is somewhat fraught when you start looking at these larger issues. It's possible we could address some of this by extending shrinkwrap's semantics, but we've muddled along without that until now. I don't think this proposal really adds anything new to the discussion.

@mgol
Copy link
Contributor

mgol commented Feb 12, 2015

I think a reasonable requirement for business apps running on io.js in
production is that if at the moment of deployment the project depends on
latest io.js, at least for the next 6 months it'll be enough to just apply
io.js updates required for security reasons. This is hard to achieve when
io.js gets an update from, let's say, 1.4.2 to 1.5.0 that fixes a security
update but also applies an update of v8 to the next version. If then this
next v8 breaks some C++ API a sub-sub-sub-dependency relies on, the
developer can either try to make the package (often 3rd party) work with
newest io.js or skip the update at all, making users vulnerable.

IOW, with Node.js it's possible to create a package depending on a specific
set of versions you outlined in points 1-5 and still be able to apply only
security updates for some time. Since io.js plans to keep up with latest
stable v8 (point 2/5), this starts to be impossible.

While it seems completely impossible to achieve the goal fully, if io.js
had a built-in copy of nan and the external, published to npm nan package would change its export logic to:

  1. If current Node/io.js doesn't have a built-in nan, use our own;
    otherwise proceed to the next point.
  2. If the built-in nan is older than our own, use our own.
  3. If the built-in nan has a higher major than our own, use our own.
  4. Otherwise, use the built-in one.

then a lot of these problems would go away, no? This would mean that if nan
1.8.0 adds compat with v8 from io.js 1.9.0 a project depending on nan 1.7.0
would still work as it'd detect the nan built into io.js is newer but
compatible and it'd export it instead.

@sam-github
Copy link
Contributor

I basically like this proposal: #630 (comment)

In terms of use cases rather than "what could we do", what I see uses for are:

  • nightly installable builds: useful for testing the installer, for example, or people who want to try bleading edge but for some reason don't build iojs by themselves. These can cut from master/v1.x and just have a tag, as @domenic suggested, and have a newest v8 and current v8 version.

For actual production, its more complex.

We have customers in production who don't ever update node unless they find a problem, or there is a security update. But in the v0.10 world, we felt comfortable suggesting that they should always install the latest 0.10.x a week after its released: it should always improve. In the case of iojs... we "might" be able to say always do the latest 1.x release, but some of the minors are pretty big changes, I'm not sure how confident I would be that they wouldn't introduce problems. We (strongloop) might eventually need to commit to maintaining a 1.2.x series, where we bring in patches from >= 1.3.x. But I hope not.

I don't think we should slow dev down to 0.10 levels, but I do think its useful to slow releases down to some predictable rate. I'm OK with my semver-minor or semver-major PRs don't release right away, I'm not OK with them taking 2 years. Its too unpredictable, why should I PR code if there is no way to know when it can hit my customer's sites?

As a strawman, I'd suggest something like this:

  • bugfixes get merged right away, and released either immediately (critical) or weekly if not, as new patch releases
  • minor changes get tagged semver-minor (as they do), and then tagged "LGTM" when accepted. CI could auto-merge all LGTM changes into a branch for test purposes, but they wouldn't be merged to master and released except for, say, once a month, so slow down the rate of minor bumping. minor changes could even be gathered into a vx.y branch and released nightly, so people have a preview of what the next minor vx.y release will contain, and can complain if they consider some of the supposedly minor changes to be breaking/major.
  • major changes would get tagged semver-major but otherwise be like minor, except they would be slowed down to every 3 months or so. I'm not so familiar with v8 release cycles, but I'd suggest that releasing a major (assuming there are major changes that have been accepted) in sync with v8 being promoted to stable might be a reasonable pace.

If stables are going to happen at a fairly predictable case, PRs like #325 or #774 that have arguable semver status could be queued up at some kind of predictable rate, and still be available for testing for confirmation by users. A very small number of users is likely to use them... but they could.

If this sounds vaguely like the old even/odd system, I'm sorry! But I'd like to point out that its critical difference is predictability, and also that there is no "release" of unstable... just nightly builds of the next major branch... use at your own risk until released, if you so desire.

Also the old regime didn't allow major changes at all, and even uncontroversial minors that were PURE API additions were rejected from stable for years. That's a scenario we don't want to repeat.

/cc @piscisaureus This is what we were talking about a couple nights ago (not to imply you agree or disagree... feel free to weigh in!).

@domenic
Copy link
Contributor

domenic commented Feb 13, 2015

I'd really prefer not to hold up minors for a month waiting to batch changes. If I want a new feature, and I PR it in, and it gets accepted, waiting a month is going to discourage me.

For example, look at the new features in 1.2.0. All of them were pretty darn useful and the people who added them (among other consumers) would be pretty bummed if we were waiting a month to release them.

@domenic
Copy link
Contributor

domenic commented Feb 13, 2015

I guess the key conflict here is that some people see adding features as more of a big deal than making bugfixes. I don't think this is the correct mindframe. io.js 1.0.0 to 1.2.0 is a similar amount of changes from Node 0.10.x to 0.10.(x + 1). You should be equally happy to recommend an upgrade to your customers. And, we shouldn't be having to maintain a 1.2.x branch even after 1.3.0 is released. There's no actual value in avoiding new features by staying on 1.2.x.

In the end I think such concerns are solving the wrong problem. If the worry is that the jump from 1.2.x to 1.3.0 might "introduce problems" at a greater rate than the jump to 1.2.(x + 1), then I'd argue we shouldn't have merged those things into 1.3.0 until they were problem-free.

@vkurchatkin
Copy link
Contributor

@sam-github +1

I would prefer if patch releases were bugfixes only (no refactoring, perf improvements or anything else)

@mikeal
Copy link
Contributor

mikeal commented Feb 13, 2015

Thought I'd chime in with a idea that is seeding in the roadmap. Basically, the idea is that there are 3 channels, which is just a fancy way of messaging current builds for 3 concurrent lines of development.

  • Release: Stable, Production Ready. Anything with a semver is in this channel. Most of what is being discussed here falls in to that channel.
  • Canary: Nightly builds with next v8.
  • NG (Next Generation): Nightly builds of experimental next generation API using ES6 modules.

As far as LTS goes, patch releases can be published of any prior minor release provided someone cares enough to port fixes to it. We shouldn't block any new work happening in a current line of development with the work of backporting it to a prior line. There are a lot of companies that care strongly about LTS, enough that they can easily chip in some resources each and handle the work of back porting fixes provided we give them an easy way to do it and a clean and automated way to produce patch releases. There's a big industry out there supporting customers who are running their applications on older lines and won't take a big upgrade, let that industry provide the resources necessary to drive this support and allow LTS support to find its own natural cutoff point.

@sam-github
Copy link
Contributor

@domenic I'm not caught up on whether its a month, or 2 weeks. But I want to point out that some new features are breaking changes to someone. Not all, of course, but even "purely additive" features can break code.

I'm about to PR the emit of the 'message' event on cluster, for consistency with the other 4 cluster events. But, somewhere, there is someone who is already emitting the 'message' event on cluster... and they will now get two events. Sucks to be them, we can say, because you should never extend a built-in, and you should never emit your own events on any builtin EE... but folks do that all the time. And if its express that does it, and we break express with a hopefully "purely additive change", shaking our fingers at the express developers isn't going to change the fact that half the node apps in the world don't work.

@mikeal I'm suggesting that so-called "minor" changes be available in some kind of non-semvered "canary" channel, so folks have some way of giving feedback about whether those changes are in fact as "semver-minor" as we think they are. I didn't say anything about LTS, just about "canary" channels for next releases, that distinguish between patch, minor, and major - so we can see if the classification is correct. @chrisdickinson mentions he likes to run the old tests against the new code to see if it really is api compatible, but I suggest iojs test coverage is not sufficient for that to be any more than a smoke test.

Also, @domenic, you didn't address _major_ changes. There are going to be some of those. There arguably already have been. How often do we want to release them? How are we going to give people a chance of to get a "canary" of them?

Anyhow, I'm just kicking the idea into the air. We'll see how bumping minor and major based on whenever someone happens to PR something goes, how hard people find iojs to follow, and if as certain recent video put it "semver will drive them insane".

@chrisdickinson
Copy link
Contributor Author

Closing this because the conversation has since moved on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
doc Issues and PRs related to the documentations.
Projects
None yet
Development

Successfully merging this pull request may close these issues.