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) | |
|---|---|---|
| Purpose | A milestone of the release history (alpha, beta, rc) | A throwaway version to test a branch or a pull request |
| Version | 1.3.0-beta.0, then 1.3.0-beta.1... | 1.3.0-0.canary-a3f4b2c (commit SHA) |
| npm dist-tag | next (change it with --tag) | canary (change it with --tag) |
package.json | Bumped and committed | Bumped for the publish, then restored |
| Changelog | Yes | No |
| Commit, tag, push | Yes | No |
| Provider release | Yes | No |
| Social posts | Skipped with onlyStable (the default) | No |
| AI rewrites | Skipped with ai.onlyStable (the default) | No |
| PR comment | Yes | Yes |
Prerelease Versions
Starting a Prerelease
From a stable version, --prerelease computes the bump from the commits, and --preid names the prerelease:
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):
| Step | Commits since the last prerelease | Result | Why |
|---|---|---|---|
| 1 | fix: resolve bug (from 1.2.1) | 1.2.2-beta.0 | First prerelease, a fix is a patch |
| 2 | fix: another fix | 1.2.2-beta.1 | Same level: the counter increments |
| 3 | feat: new feature | 1.3.0-beta.0 | A minor is above the patch base: base bumps |
| 4 | fix: small fix | 1.3.0-beta.1 | Below the minor base: the counter increments |
| 5 | feat!: breaking | 2.0.0-beta.0 | A 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:
# 1.2.0-beta.3
relizy release --prerelease --preid rc
# → 1.2.0-rc.0A 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:
relizy releaseThe stable version is the base version of the prerelease, unless the commits since the prerelease imply a bigger bump than this base:
| Prerelease | Commits since the prerelease | Stable version |
|---|---|---|
1.13.1-beta.0 | fix: resolve bug | 1.13.1 |
1.13.1-beta.0 | feat: new feature | 1.14.0 |
1.3.0-beta.2 | feat: another feature | 1.3.0 |
1.3.0-beta.2 | feat!: breaking | 2.0.0 |
1.13.1-beta.0 | none, or chore: tooling | 1.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
nextdist-tag, unless--tag(orpublish.tag) sets another one:relizy release --prerelease --preid beta --tag beta. Publishing a prerelease with--tag latestwarns. - Suffix:
--suffixreplaces the counter of the prerelease:--prerelease --preid beta --suffix pr-42gives1.3.0-beta.pr-42instead of1.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.0to1.4.1-beta.0), or the nextprereleasewhen it already is a prerelease. Inselectivemode, 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:
relizy release --canary --yesWhat --canary Does
--canary forces these settings of relizy release, whatever the other flags and the config:
- the type is
prereleaseand the preidcanary(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
{next version}-0.{preid}-{short sha}
1.3.0-0.canary-a3f4b2cThe 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 version | Commits | Canary version |
|---|---|---|
1.2.3 | feat: ... | 1.3.0-0.canary-a3f4b2c |
1.2.3 | fix: ... | 1.2.4-0.canary-a3f4b2c |
1.2.3 | feat!: ... | 2.0.0-0.canary-a3f4b2c |
2.0.0-beta.1 | feat: ... | 2.0.0-0.canary-a3f4b2c |
0.5.2 | feat!: ... | 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, apatchcanary 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
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:
- 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.