Skip to content

Prereleases & Canary ​

Publish prerelease versions (alpha, beta, rc) that are part of the release history, and canary versions (snapshot, preview) to test a pull request, with their versions, npm dist-tags and graduation to stable.

Prerelease or Canary ​

Prerelease (--prerelease --preid beta)Canary (--canary)
PurposeA milestone of the release history (alpha, beta, rc)A throwaway version to test a branch or a pull request
Version1.3.0-beta.0, then 1.3.0-beta.1...1.3.0-0.canary-a3f4b2c (commit SHA)
npm dist-tagnext (change it with --tag)canary (change it with --tag)
package.jsonBumped and committedBumped for the publish, then restored
ChangelogYesNo
Commit, tag, pushYesNo
Provider releaseYesNo
Social postsSkipped with onlyStable (the default)No
AI rewritesSkipped with ai.onlyStable (the default)No
PR commentYesYes

Prerelease Versions ​

Starting a Prerelease ​

From a stable version, --prerelease computes the bump from the commits, and --preid names the prerelease:

bash
relizy release --prerelease --preid beta
# fix commits:  1.0.0 → 1.0.1-beta.0
# feat commits: 1.0.0 → 1.1.0-beta.0

--premajor, --preminor and --prepatch set the bump instead: relizy release --preminor --preid beta gives 1.1.0-beta.0. The preid can also be set in the config with bump.preid.

--preid needs a prerelease type: relizy release --preid beta alone fails with You cannot use a "release" type with a "preid".

Continuing a Prerelease ​

Keep running --prerelease with the same preid. Relizy compares the commits since the last prerelease with the level of its base version (1.3.0 in 1.3.0-beta.2):

StepCommits since the last prereleaseResultWhy
1fix: resolve bug (from 1.2.1)1.2.2-beta.0First prerelease, a fix is a patch
2fix: another fix1.2.2-beta.1Same level: the counter increments
3feat: new feature1.3.0-beta.0A minor is above the patch base: base bumps
4fix: small fix1.3.0-beta.1Below the minor base: the counter increments
5feat!: breaking2.0.0-beta.0A major is above the minor base: base bumps

The base version only goes up, and the counter restarts at 0 when it does. Without new commits, nothing is released. In 0.x, a breaking change bumps the minor (0.5.2 to 0.6.0-beta.0), see Semver Convention.

Changing the Preid ​

Move to the next stage with another preid, even without new commits:

bash
# 1.2.0-beta.3
relizy release --prerelease --preid rc
# → 1.2.0-rc.0

A preid sorting lower (rc to beta) is refused: the new version would not be greater than the current one.

Graduating to Stable ​

Run a release without prerelease type:

bash
relizy release

The stable version is the base version of the prerelease, unless the commits since the prerelease imply a bigger bump than this base:

PrereleaseCommits since the prereleaseStable version
1.13.1-beta.0fix: resolve bug1.13.1
1.13.1-beta.0feat: new feature1.14.0
1.3.0-beta.2feat: another feature1.3.0
1.3.0-beta.2feat!: breaking2.0.0
1.13.1-beta.0none, or chore: tooling1.13.1

An explicit type applies as is: --patch on 1.3.0-beta.5 gives 1.3.0. In a monorepo, a package on a prerelease version is released when it graduates (to stable or to a new preid), even without new commits. The changelog of a stable release starts at the previous stable release, see Range of Commits.

Dist-Tag, Suffix and Dependents ​

  • Dist-tag: a prerelease is published with the next dist-tag, unless --tag (or publish.tag) sets another one: relizy release --prerelease --preid beta --tag beta. Publishing a prerelease with --tag latest warns.
  • Suffix: --suffix replaces the counter of the prerelease: --prerelease --preid beta --suffix pr-42 gives 1.3.0-beta.pr-42 instead of 1.3.0-beta.0. The version must still be greater than the current one.
  • Dependents: a dependent without commits of its own gets a prepatch (1.4.0 to 1.4.1-beta.0), or the next prerelease when it already is a prerelease. In selective mode, it gets the root version, as always (see Dependency Management).

Canary Releases ​

A canary is a version published from the current commit, to install and test a branch before it is merged:

bash
relizy release --canary --yes

What --canary Does ​

--canary forces these settings of relizy release, whatever the other flags and the config:

  • the type is prerelease and the preid canary (unless --preid);
  • the dist-tag is canary (unless --tag), whatever --preid;
  • no changelog, commit, git tag, push, provider release nor social post.

The other steps run as usual: the safety checks, the check of uncommitted changes (--no-clean skips it), the bump confirmation (--yes in CI), the publish (--no-publish skips it) and the PR comment (--no-pr-comment skips it).

The canary versions are written to the package.json files for the publish, then restored once the packages are published, when the publish fails, or right away with --no-publish. With relizy bump --canary, the canary versions stay in the files.

Version Format ​

text
{next version}-0.{preid}-{short sha}
1.3.0-0.canary-a3f4b2c

The next version is computed from the commits (patch when no commit sets a bump), the short SHA is the one of the current commit. The leading 0 sorts the canary below every other prerelease of the same version: 1.3.0-0.canary-a3f4b2c < 1.3.0-alpha.0 < 1.3.0-beta.0 < 1.3.0. A semver range (^1.3.0-beta.0) never matches it, and update tools never suggest it: a canary is only installed on purpose.

Current versionCommitsCanary version
1.2.3feat: ...1.3.0-0.canary-a3f4b2c
1.2.3fix: ...1.2.4-0.canary-a3f4b2c
1.2.3feat!: ...2.0.0-0.canary-a3f4b2c
2.0.0-beta.1feat: ...2.0.0-0.canary-a3f4b2c
0.5.2feat!: ...0.6.0-0.canary-a3f4b2c

As for a release, a breaking change of a 0.x version bumps the minor with bump.capZeroMajor (the default).

--preid snapshot gives 1.3.0-0.snapshot-a3f4b2c, still published with the canary dist-tag.

Packages Released ​

  • Standalone and unified: every package gets the canary version, a patch canary when no commit sets a bump.
  • selective: the packages with commits and their dependents get the canary version of the root; without commits, nothing is released.
  • independent: each package with commits, and each dependent, gets a canary of its own version.

With version groups, the canary versions of every group are written before anything is published, and restored once, after the last package is published: the workspace: dependencies between groups resolve to the canary versions of the same run.

Installing a Canary ​

bash
npm install my-package@canary
npm install [email protected]

The latest dist-tag is never changed by a canary.

Canary in CI ​

A canary job on each pull request publishes the version and comments it on the pull request:

yaml
- name: Canary release
  run: pnpm exec relizy release --canary --yes --skip-existing-versions
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

The canary version comes from the commit SHA: a rerun on the same commit regenerates the same version, which the registry refuses to publish again. --skip-existing-versions skips the packages already published, so a rerun passes.

For the complete workflows (permissions, tokens, PR number), see GitHub Actions and GitLab CI; for the comment, see PR Comment.