This document explains how code moves through Rocket.Chat Desktop, from a
feature branch to a published release. It is for anyone who contributes to
the project, not only release managers. For the exact commands that cut a
release, see docs/release-process.md. This document covers the shape of
the model and the reasoning behind it.
The project uses three kinds of branches with distinct roles.
masterholds only released code. Its tip is always the latest stable release, patch releases included. Every commit on it corresponds to something that has shipped or is about to ship.devis where all development converges. Every feature and fix merges there first, and alpha releases are tagged directly from it.release/X.Y.xbranches exist only after a stable version has shipped. They carry patches for that version. They do not pull in unrelated work that has since landed ondev.
This separation keeps master a stable, auditable history of what shipped.
dev stays free to move fast.
| Branch | Purpose | Who merges into it | Merge method |
|---|---|---|---|
dev |
Default branch. Integration point for all feature and fix PRs. Source of alpha tags | Any contributor via PR review | Squash |
master |
Released code only. Its tip is the latest stable release. Gets dev at promotion and release/X.Y.x after each patch |
Release manager, at promotion and after a patch | True merge commit |
release/X.Y.x |
Patch line for a shipped stable version. Receives cherry-picked fixes from dev |
Release manager, when preparing a patch | Squash |
| Feature/fix branches | Short-lived. One change per branch. Opened against dev |
The author, via PR | Squash (into dev) |
A typical change follows this path:
- A contributor branches off
devand opens a PR. After review, the PR is squash-merged intodev. devaccumulates changes between releases. Periodically, a version bump is merged and tagged as an alpha (X.Y.0-alpha.N) directly ondev. QA and early adopters can then test the accumulating changes.- When the release is ready to ship, a last bump on
devdrops the pre-release suffix. Then a release PR mergesdevintomasterwith a true merge commit. The stable tag (X.Y.0) goes on that merge commit. - If someone finds a defect in a shipped stable version, the fix merges
into
devas usual. Then the fix is cherry-picked onto the correspondingrelease/X.Y.xbranch and released as a patch (X.Y.Z). If the branch does not exist, create it from theX.Y.0tag. After the patch is published, the release branch merges intomasterwith a true merge commit, somasteralways holds the latest stable release.
---
config:
gitGraph:
mainBranchName: "master"
---
gitGraph
commit id: "released code"
branch dev
checkout dev
commit id: "feature work 1"
commit id: "feature work 2"
commit id: "bump to 4.16.0-alpha.1" tag: "4.16.0-alpha.1"
commit id: "feature work 3"
commit id: "bump to 4.16.0-alpha.2" tag: "4.16.0-alpha.2"
commit id: "bump to 4.16.0"
checkout master
merge dev id: "release 4.16.0" tag: "4.16.0"
checkout dev
commit id: "next cycle work"
checkout master
branch release/4.16.x
checkout release/4.16.x
commit id: "cherry-pick fix"
commit id: "bump to 4.16.1" tag: "4.16.1"
checkout master
merge release/4.16.x id: "patch 4.16.1"
The diagram omits the individual squash commits that make up "feature work". In practice, each labeled commit above is the product of one or more squash-merged PRs.
| Stage | Trigger | What happens |
|---|---|---|
| PR checks | Any PR opened against dev, master, or release/* |
validate-pr runs lint and the full test suite. A build-artifacts label also builds installers for manual smoke-testing |
| Release build | A semver tag push (X.Y.Z or X.Y.Z-alpha.N, etc.) |
build-release creates a draft GitHub release, then seven parallel jobs (per platform × installer family) build, sign and upload the installers into it. workflow_dispatch runs the same jobs as a dry run with no release |
| Publish | Manual | A human reviews the draft release and its assets, then publishes it |
A branch push never starts a release build. This keeps dev, master, and
release/* free of accidental builds. A tag push creates the only publishable
release, and a human must publish the draft. A manual workflow_dispatch run
builds and signs from a branch as a dry run and publishes nothing.
The app's auto-updater receives published releases through three channels:
| Channel | Who receives it |
|---|---|
latest (stable) |
All users by default |
beta |
Users who opt into beta updates |
alpha |
Users who opt into alpha updates (also receive beta and stable) |
Versions follow semver (MAJOR.MINOR.PATCH, with an optional
-alpha.N/-beta.N pre-release suffix). Two conventions keep the branches
in sync:
- The
devversion invariant:package.jsonondevalways equals the newest tag cut fromdev's own line. Right after a stable promotion,devstays at the version that just shipped. It does not jump ahead until the next cycle starts. - Alpha numbering starts at
.1: the first alpha of a new cycle isX.(Y+1).0-alpha.1. It is never a bareX.(Y+1).0. The release process reserves that plain version number for the eventual stable release of that cycle.
- Never back-merge.
masterandrelease/X.Y.xbranches never merge back intodev. Two practices make sure thatdevalready has every change thatmastergets: bumpdevbefore every promotion, and cherry-pick fixes downward fromdevto patch lines. The patch version bumps are the only expected difference. The next promotion resolves them on a promotion branch, never with a merge intodev. The single exception is a hotfix that someone authors directly on arelease/X.Y.xbranch. Forward-port it todevimmediately with a small cherry-pick PR, so that the next promotion does not lose it. - Never squash the promotion PR. Merge the
dev→masterrelease PR with a true merge commit. A squash forks history permanently and makes every future diff between the branches unreadable. - Always tag through
yarn release:tag. The script enforces that a tag goes on a commit that belongs to the right branch for its channel. A baregit tagpush has no such guard.
docs/release-process.md— the operational runbook. It has the exact commands to cut alpha, stable, and patch releases, and the full reference foryarn release:tag..github/CONTRIBUTING.md— the Branching Model section for contributors opening a PR.