microsoft / beachball

The Sunniest Semantic Version Bumper

Home Page:https://microsoft.github.io/beachball

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Beachball canary isn't documented and doesn't work as would be expected

DanProudfoot opened this issue · comments

This is going to be a relatively wide ranging issue on the topic of the canary command.

  1. There isn't any documentation on the Canary command. I had to figure it out for myself after noticing it mentioned once in the docs.
  2. The bump algorithm on canary works a bit weirdly? My packages were on version 0.1.5 and I created a minor change. Running bump locally increased the version to 0.2.0 as expected. However, if I undo those changes and instead run canary I get 0.2.1-pr30.0 (where I'm using the PR number from bitbucket). This doesn't seem right, why am I bumping an extra patch version above where I should be?
  3. It might be slightly related to the undocumented nature of the command, but as the bump is not committed back to git, how does canary know to go from .0 to .1 the next time a version is pushed?

I'm might be willing to look into this and submit a PR, but before I do I'd like my assumptions cleared up, just in case I'm barking up the wrong tree.

commented

I am also confused about the prerelease workflow, and have noted the various options (prerelease-prefix via Bumping and publishing options, prereleasePrefix via Options and as mentioned in this issue the one reference to canary also via Bumping and publishing options).

I, too, would be very interested in contributing, but do not want to rush in with invalid assumptions. I will try to address one of your questions, add what I understand and then expand on how I think a workflow could work in theory to (hopefully?) move this discussion along.


To try and address your second question first:

Running bump locally increased the version to 0.2.0 as expected. However, if I undo those changes and instead run canary I get 0.2.1-pr30.0 (where I'm using the PR number from bitbucket). This doesn't seem right, why am I bumping an extra patch version above where I should be?

I believe this is explained by the documented behaviour of semver prerelease, which is the only option used by the Canary command:

If called from a non-prerelease version, the prerelease will work the same as prepatch. It increments the patch version, then makes a prerelease.

To summarise:

input (after bump) action output
0.2.0 prerelease preid=pr30 0.2.1-pr30.0
0.2.0 prepatch preid=pr30 0.2.1-pr30.0
0.2.0 preminor preid=pr30 0.3.0-pr30.0
0.2.0 premajor preid=pr30 1.0.0-pr30.0

Understanding so far:

  • Currently prerelease is a change type:
    export type ChangeType = 'prerelease' | 'patch' | 'minor' | 'major' | 'none';
  • semver describes a prerelease as a “label” or “extension“ to a version (i.e. to be used in conjunction with a version)
  • Canary only ever uses prerelease, it never uses preminor or premajor, even if the change type is minor or major):
    newVersion = semver.inc(newVersion, 'prerelease', options.canaryName || 'canary')!;
  • A PR was raised previously to always offer prerelease as a change option, but was closed due to understandable concerns: #571
  • There is no documented workflow for how to manage prerelease versions
  • Currently publish has no understanding of how to handle prerelease versions.
    • Publishing 2.0.0-canary.0 with type major will result in 3.0.0 instead of releasing 2.0.0

How I think a workflow could work:

I think prerelease should be treated as a modifier to a change, rather than a change itself.

In other words, I don’t think it should ever be a valid change type in a change file, it should instead work in conjunction with the change type defined (i.e. patch/minor/major).

To expand:

  1. Running canary creates the appropriate prerelease version based on the type specified on the change file
  2. Running publish converts the prerelease version into the desired release version

So a workflow might be:

  1. beachball change creates a change file for patch / minor / major
  2. beachball canary (or aliased as prerelease) can be run any number of times to publish prerelease versions
  3. beachball publish will convert the pre-release version to the target release version

And then to illustrate:

original change canary x1 canary x2 canary x3 publish
1.0.0 patch 1.0.1-canary.0 1.0.1-canary.1 1.0.1-canary.2 1.0.1
1.0.0 minor 1.1.0-canary.0 1.1.0-canary.1 1.1.0-canary.2 1.1.0
1.0.0 major 2.0.0-canary.0 2.0.0-canary.1 2.0.0-canary.2 2.0.0

Obviously implied in that is that I do not believe publish should also be used as the command to publish prerelease versions, because they require slightly specialist handling (and I would infer this is why canary exists in the first place). Of course there is nothing stopping most of the publish logic from being reused, but I think it is conceptually clearer if publish itself is only used for final release versions.

Without this pivot though I feel you are going to be stuck with manual tasks each time to convert back and forth between versions and prerelease versions (which is liable to mistakes).

For me, when publishing prereleases, I have access to a CI build number I could use. However that would result in an awkward version of 1.0.0-canary.1.0 since the .0 will always be appended at the end still.

I could switch from canary back to publish but I believe that would then muck with the change files that may have been generated. Hope I am not mistaken, is there a workaround to set the versions more directly?