Loopback-next: Switch to 0.x.y versions instead of 4.0.0-alpha.X

Created on 2 Feb 2018  路  9Comments  路  Source: strongloop/loopback-next

Our current versioning scheme based on pre-release 4.0.0-alpha.X version numbers (where X is an increasing integer) has several shortcomings. Most importantly, there is no way how to signal consumers of our modules which releases are backwards-compatible and which contain breaking changes.

Originally, when we (foolishly?) believed LoopBack4 will be released in 6 months, it probably made sense to use pre-release versions. However, now that we are looking for another ~12 months until stable Beta/GA releases, I think we should revisit this decision.

I am opening this issue as a follow-up for our discussion with @raymondfeng in https://github.com/strongloop/loopback-next/pull/913#discussion_r164051703, where we did not want to remove no-longer-used-script to preserve backwards compatibility with external projects depending on our build system:

If we were versioning non-core modules as 0.x.y, then we could treat semver-patch release as backwards compatible and semver-minor releases as breaking. This works great with the carrot operator as implemented by npm's semver (https://www.npmjs.com/package/semver#caret-ranges-123-025-004):

this allows patch and minor updates for versions 1.0.0 and above, patch updates for versions 0.X >=0.1.0, and no updates for versions 0.0.X.

Let's see if there are any downsides of moving from 4.0.0-alpha.X down to 0.x.y and how much effort such change would require.

developer-experience needs discussion tech-debt

Most helpful comment

Don't we want users to pick up the changes automatically unless there's a breaking change? (In which case I think it should be patch releases and minor for breaking changes).

I am +1 for using semver-minor 0.x.0 releases for breaking changes only, and publishing backwards-compatible changes as patch releases. OTOH, I don't know how our release tooling works when it comes to 0.x releases, I think we should simply follow whatever they have implemented.

I still think it might be a good idea to a certain extent to lock version numbers for simplicity even though it might make it harder to upgrade versions without certainty as a major release in one package that might not be used by everyone will cause all packages to be bumped by a major version -- but once we've hit stability, how often are we going to introduce breaking changes? ... LoopBack 3 is still 3.x.

Regarding independent release numbers or not, I think both @virkt25 and me have wrote enough arguments for and against this proposal (see above). Let's hear from others what do they think.

cc @strongloop/sq-lb-apex @strongloop/loopback-next

All 9 comments

@kjdelisle @dhmlau I have labelled this issue as MVP because I think it's sort of a tech debt that is slowing us down a bit, please let me know if you disagree.

@bajtos, I agree to go with the 0.x.y versioning in general. From the user point of view, it is also a more convenient way to get the latest instead of changing the package.json manually in the app.

I'm not sure the effort involved (it doesn't seem to be too much??). If it's small effort, I think we should consider to get it into MVP. Otherwise, at least before beta. :)

Here is my main concern about this change: how will npm install handle the situation when we have let's say 0.1.0 that's newer than 4.0.0-alpha.10. Typically, versions are ordered by their numbers, i.e. 0.1.0 is a predecessor of 4.0.0-alpha.10. When we make the switch, we will end up with 4.0.0-alpha.10 being a predecessor of 0.1.0.

I think it should not be a problem, because alpha pre-releases are ignored by ^ and ~ unless the specific pre-release suffix is specified. I.e. when people depend on ^0.1.0 or even ^3.9.9, then npm install is never going to consider 4.0.0-alpha.X version as a candidate to install.

The second possible issue that comes to my mind is that when we eventually decide to switch back to 4.0.0 pre-releases, then we won't be able to reuse existing 4.0.0-alpha.X numbers. OTOH, I think this should not be a problem because if we decide to switch back to 4.0.0 preleases, then it should be for beta or even rc (release candidate) version, which are different from the current -alpha suffix. (To be honest, I personally think we should not be switching to 4.0.0 pre-releases at all. Use 0.x until we have a release candidate, then publish the first release candidate as 4.0.0.)

As far as the effort involved, I think all we need is to edit version field in all packages/*/package.json files (set it to something like 0.1.0) and update the release script in monorepo's package.json to stop publishing pre-release versions.

@bajtos I agree with your assessment. Let's fix it ASAP.

For each release, I think we should default the increment to minor, which means 0.1.0 will become 0.2.0. NPM won't resolve ^0.1.0 with 0.2.0 and that ensures isolation for existing apps.

Don't we want users to pick up the changes automatically unless there's a breaking change? (In which case I think it should be patch releases and minor for breaking changes).


Now one thing I noticed with our current releases is that packages that don't have any change in them are still having their version bumped up (Can be seen in the CHANGELOG). This is fine ... but bring me to a question that's been discussed before but I think should be re-considered, should we sync all the versions (if all are getting bumped) ... and this will ensure certainty for users that a given version across the board for @loopback/* will always work together. (So all packages are 0.1.0 and the 0.1.1 -> 0.2.0 , etc.)

I still think it might be a good idea to a certain extent to lock version numbers for simplicity even though it might make it harder to upgrade versions without certainty as a major release in one package that might not be used by everyone will cause all packages to be bumped by a major version -- but once we've hit stability, how often are we going to introduce breaking changes? ... LoopBack 3 is still 3.x.

Prior discussion links:
https://github.com/strongloop/loopback-next/pull/858#issuecomment-360377839
(@virkt25)

Sort of relevant to this discussion but also possibly irrelevant so perhaps it's best I open an issue, but I'm not sure why we are versioning our releases independently. Seeing @commitlint monorepo use the same version number for all packages make me wonder if we should do the same. So if we have a breaking change, we don't have issues like is v4.1.1 of @loopback/boot compatible with @loopback/core v5.0.1. If everything is the same, then users will have certainty over compatible versions.

https://github.com/strongloop/loopback-next/pull/858#issuecomment-360492344
(@bajtos)

I see your point.

On the other hand, we will make it more difficult for our users to update their dependencies and keep using the latest version. Whenever we make a breaking change in any of our packages, even those that are optional and may not be used by all users, we have to bump the major version of @loopback/core, even though there was not breaking change made in that module! Since most people are using the caret operator in their dependency version specifiers (e.g. ^4.0.0), they'll stop receiving bug fixes until they explicitly/manually upgrade to a newer semver-major version.

It also makes upgrade process more difficult, because users have to upgrade all packages at once. For example, consider the situation when we change our bootstrapper in a backwards-incompatible way, and also make some backwards-incompatible changes in our runtime (core, rest, etc.) at the same time. With independent versioning, people can keep using the olde bootstrapper because they don't have time to reorganize their project files, but still upgrade the runtime parts to stay on the latest runtime version.

Also when all versions are locked to the same value, then what's the point of having so many small packages, when their versions cannot be picked independently?

Don't we want users to pick up the changes automatically unless there's a breaking change? (In which case I think it should be patch releases and minor for breaking changes).

I am +1 for using semver-minor 0.x.0 releases for breaking changes only, and publishing backwards-compatible changes as patch releases. OTOH, I don't know how our release tooling works when it comes to 0.x releases, I think we should simply follow whatever they have implemented.

I still think it might be a good idea to a certain extent to lock version numbers for simplicity even though it might make it harder to upgrade versions without certainty as a major release in one package that might not be used by everyone will cause all packages to be bumped by a major version -- but once we've hit stability, how often are we going to introduce breaking changes? ... LoopBack 3 is still 3.x.

Regarding independent release numbers or not, I think both @virkt25 and me have wrote enough arguments for and against this proposal (see above). Let's hear from others what do they think.

cc @strongloop/sq-lb-apex @strongloop/loopback-next

IMO, I think changing it to 0.x.y doesn't really give us anything in terms of ease of versioning, and would require us to answer the next question, which is "Will loopback-next be on a separate version count from the original loopback?"

If so, then our version history would look something like this
4.0.0-alpha.* --> 0.x.y --> 1.x.y

If _not_, would it then look like this?
4.0.0-alpha.* --> 0.x.y --> 4.x.y

Personally, the least confusing of the three to me is to remain with the current approach
4.0.0-alpha.* --> 4.0.0-beta.* --> 4.x.y

Let's ask the community!
@strongloop/loopback-next
What do you think about switching the prerelease version to 0.x instead of 4.0.0-xxx?

@kjdelisle makes a really good point when looking that the history... However, I'm with @bajtos on this one. Having the ability to increment major and minor versions is really helpful when it comes to pin pointing breaking changes. 0.x.y -> 4.0.0 is still very clearly a pre-release version to a fully released version even though it looks a little silly.

Once you have >= 4.0.0 the history is going to be less of a concern.

From the discussion with @strongloop/sq-lb-apex and @raymondfeng , we'll go for:
4.0.0-alpha.* --> 0.x.y --> 4.x.y

@kjdelisle @bajtos , in this case, what should be the next step for this ticket?

Was this page helpful?
0 / 5 - 0 ratings