Release process
How a change on a feature branch becomes a versioned Cloud release with images, CLI, website, PWA, and npm packages.
Cloud releases from main. Nobody edits version numbers or the changelog by
hand; release-please derives them from squash-commit titles.
Branch and merge
main is protected. Work on a feature branch, open a pull request, and let the
gate check pass. Pull requests are squash-merged, so the PR title becomes the
commit on main.
The title is a Conventional Commit of
the form type(scope): outcome:
| Title | Next release |
|---|---|
fix(mail): keep list subscriptions after provider restart |
patch |
feat(grids): add column formulas |
minor |
feat(core)!: require the identity KEK at startup |
major |
docs: …, chore: …, refactor: …, test: …, ci: … |
no release on its own |
A BREAKING CHANGE: footer in the PR body has the same effect as !. Use
either only with explicit maintainer approval, because it moves every
application image to a new major version.
A change to a runtime contract (configuration, routes, permissions, data
format, deployment) needs a feat or feat! title and a note on the matching
Operations page. It lands in the next cloud-vX.Y.Z
automatically.
Let release-please cut the release
release-please runs on every push to main:
- It opens or updates one release pull request per component. The PR bumps
versionfields, updatesCHANGELOG.md, and records the new version in.release-please-manifest.json. - Merging the release PR creates the tag. The Cloud component tags
cloud-vX.Y.Z; the npm packages tagnpm-cloud-vX.Y.Zandnpm-ui-vX.Y.Zas separate components with their own version lines. - The
cloud-vX.Y.Ztag triggers the release workflow. It builds the 26 images of the release set (every application fromscripts/workspace.tspluscloud-websiteandcloud-pwa-auth) forlinux/amd64andlinux/arm64, the CLI binaries, and publishes a GitHub release withrelease.jsonand build attestations. - The
npm-cloud-v*andnpm-ui-v*tags publish@k2b/cloudand@k2b/uiwith npm provenance. A prerelease version such as0.8.0-rc.1publishes under thenextdist-tag; a stable version publishes underlatest.
release.json lists every image with its tag and digest. Deployments pin the
vX.Y.Z tag or the digest from that file; see
Build and deploy.
Every push to main also builds sha-<12> images for staging. Those tags are
not releases: they carry no changelog entry and no support commitment.
Ship a hotfix
Branch from the release tag, not from main:
git switch -c fix/mail-subscriptions cloud-v0.7.0Open the pull request against main as usual. release-please includes the fix
in the next patch release. If main already contains unreleased minor changes,
the fix ships with them; a separate patch line for an old minor is not
maintained.
Roll back
Pin the previous vX.Y.Z or its digests from that release's release.json,
then run the fleet preflight against the running installation:
CLOUD_IMAGE_TAG=v0.7.0 bun run release:preflightThe preflight needs CLOUD_IMAGE_TAG, SYNC_NAMESPACE, CLOUD_CORE_URL, and
CLOUD_ADMIN_TOKEN in the process environment. Check migration compatibility
before rolling back across a release that changed the database; the changelog
marks such releases.
Do not
- edit
versionfields,CHANGELOG.md, or.release-please-manifest.json; - create, move, or delete tags;
- push to
maindirectly; - re-run a release for a tag that already exists. Fix forward with a new patch release.