Skip to content

Branches, releases and version numbers

Muppy ships from a production branch, gathers the next release on a second branch, and numbers every build so the number alone says what you are running and how far it has matured.

Three kinds of branches

18.0 — production. What customers run. It receives a release candidate when a release is cut, and hotfixes, nothing else.

next — the next release. Permanent. Every change waiting for the next release pours into it — features, fixes, improvements — and it never stops moving. Candidates are cut on it, and they are the only way it reaches a customer before production does: the customers who opted into vNext.

Feature branches. One branch, one feature. A feature is what Muppy's development process calls a chantier: a bounded piece of work cut into lots, each developed, tested and accepted on its own. The branch is born from 18.0, receives the lots one after the other, is merged into next when the chantier is done, then archived and deleted. Two chantiers may share one branch: they are then merged together, and neither reaches next before the other is done.

A small, self-contained change — no chantier, a commit or two — may be committed on next directly when the product owner decides so. It has no merge commit to revert: once on next, it leaves with the next candidate.

A branch that ends is archived before it is deleted, whether it was merged or abandoned unmerged: a tag archive/<branch> is set on its tip, in every repository that carries it, and pushed. Once the branch is gone, the merge commit names it only in its message; the tag keeps the chantier's commits reachable under its name — for an abandoned branch, it is what keeps them at all — and its prefix says that nothing builds from it any more.

A hotfix is committed on 18.0, released as a patch, and merged into next straight away, so the next candidate carries it. A critical or high security fix to a released version is always a hotfix: the fix and its description reach production together, and vNext with its next candidate. A medium or low one may wait for the next minor: its candidates announce security fixes without detail, and the release publishes the details — see Security fixes.

A feature is born from production

A feature branch starts from what customers run, not from other work in progress. It therefore carries nothing that is not released yet, and a feature that is not ready is simply not merged: a candidate is always production plus the features merged into it and the changes committed on next directly, and nothing else.

A feature that depends on another one not released yet is born from that feature instead, and is merged after it.

Four levels of maturation

A change climbs four levels on its way to customers. The level is where the code was cut, and the tag says which.

Level Tag Cut on Who runs it Release notes
alpha 18.97.0-alpha.mkeyd-k8s.3 a feature branch wherever a person deploys it none
beta 18.97.0-beta.mkeyd-k8s.1 a feature branch wherever a person deploys it, to be tested none
release candidate 18.98.0-rc.1 next the customers in vNext the page of 18.98.0, marked preview
release 18.98.0 18.0 everyone the page of 18.98.0
%%{init: { 'gitGraph': { 'mainBranchName': '18.0', 'showCommitLabel': false }, 'themeVariables': { 'fontSize': '20px', 'tagLabelFontSize': '18px' } } }%%
gitGraph LR:
    commit tag: "18.97.0"
    branch next order: 1
    checkout "18.0"
    branch feature-a order: 2
    commit
    commit
    checkout next
    merge feature-a
    checkout "18.0"
    commit type: REVERSE tag: "18.97.1"
    checkout next
    merge "18.0"
    checkout "18.0"
    branch feature-b order: 3
    commit
    checkout next
    commit type: HIGHLIGHT
    commit tag: "18.98.0-rc.1"
    commit
    merge feature-b
    commit tag: "18.98.0-rc.2"
    checkout "18.0"
    merge next tag: "18.98.0"
    checkout next
    commit

A cross on 18.0 is a hotfix, merged into next at once. The square on next is a small change the product owner allowed on next directly. A feature branch is usually deployed at its head, untagged.

An alpha and a beta are optional, and only ever tagged on a feature branch — most features are deployed at their head and never get one. They are builds of a feature, one step of maturity apart: an alpha is a build of the lots done so far, run somewhere to try them; a beta is the whole feature, complete enough to be tested. Nothing deploys them on its own — a person chooses where each one goes, which keeps a feature that is not accepted off every shared server.

A release candidate is cut on next. It carries the number of the release it precedes and that release's notes, published early and marked as a preview, and the customers in vNext receive it. Each candidate is a snapshot of next: 18.98.0-rc.2 carries the fixes to rc.1 and whatever merged since. 18.98.0-rc.1, 18.98.0-rc.2 and 18.98.0 are three states of one release, in that order.

A release moves 18.0 to the last candidate — a fast-forward, not a merge — and the release tag goes on that very commit: production receives, commit for commit, what the customers in vNext ran. What reached next after that candidate waits for the next release. The page loses its preview mark.

The release candidate

Three rules.

  • It is cut on next once next contains all of 18.0. A hotfix not yet merged into next would be missing from the candidate, and then from the release.
  • It is a snapshot, and next never waits for it. A candidate is cut when next holds what is to be tested. Features keep merging while it is out, so the next candidate carries the fixes to the previous one together with whatever merged since.
  • Production receives only what ran as a candidate. A release is the commit of the last candidate, however far next has moved since. It is refused when 18.0 carries a hotfix that candidate lacks: that means one more candidate first.

Version numbers

A number is MAJOR.MINOR.PATCH, tagged in git.

  • MAJOR is the Odoo series Muppy runs on: 18.
  • MINOR bumps with each release, when 18.0 receives the release candidate.
  • PATCH bumps for a hotfix on 18.0.

One rule governs every number, and it has no exception: a release number is greater than every tag the release contains, alphas and betas included. A candidate sits below its release, as the ordering of version numbers has it — 18.98.0-rc.2 comes before 18.98.0 — so the rule holds without a special case. No parity, no reserved number, and no number announced before it is cut, except by the candidates of the release it names.

You see What it is
18.98.0 a release — it has a page here
18.98.1 a patch on 18.98.0 — documented on the page of 18.98.0
18.98.0-rc.2 the second candidate for 18.98.0 — before the release, on its page
18.97.0-beta.mkeyd-k8s.1 the first beta of the feature mkeyd_k8s, after 18.97.0 — no page
18.97.0-alpha.mkeyd-k8s.3 the third alpha of the same feature — no page
18.97.0-1-gdf5cd050 a checkout one commit past the release 18.97.0
df5cd050 a build from a branch that carries no tag at all

Reading a suffix

The number before the suffix does not mean the same thing on every level, and the two readings are opposites:

  • On an alpha or a beta it is the last release the build contains. It is a fact git computes — what is in the build — not a promise about the number the feature will be released under. So 18.97.0-beta.mkeyd-k8s.1 is after 18.97.0: that release, plus a feature.
  • On a candidate it is the release the build precedes. 18.98.0-rc.2 is before 18.98.0: if it is the last candidate, it is the very commit later released as 18.98.0.

The word after the hyphen — alpha, beta, rc — is what the deployment pipeline reads. Only a candidate or a release reaches a customer: a server qualified vNext receives the candidates, every customer the releases. An alpha or a beta is deployed by hand. The feature name in an alpha or a beta (mkeyd-k8s, underscores written as hyphens) says where it comes from; the final number counts the builds of that level, on that feature, on that base.

Sub-repositories

Muppy is assembled from sub-repositories, each with its own git history, and they evolve compatibly: a change in one of them is written so that nothing depending on it breaks. A feature that needs such a change works on a twin branch there, pinned in the build file (.muppy/buildit.jsonc), for exactly as long as the feature lives. Merging the feature into next merges its twins into their own main branch in the same gesture — so a dependency may reach production before the feature that asked for it, which is why it is written to be compatible — and the twins end as the feature does, archived then deleted. No pin names a dead branch, in any repository: a surviving pin is a server still building from a branch nobody maintains.

What you see as a user

  • One page per MINOR under Release Notes. It says what the release changes for you.
  • A candidate opens that page early, marked as a preview, so that a customer in vNext running 18.98.0-rc.1 reads what 18.98.0 will change. The mark goes when the release is cut; nothing else on the page needs to.
  • A patch adds a section to the page of its minor. It never gets a page of its own. A security fix is described in that section, or on the page of the minor that carries it.
  • An alpha or a beta has no page. Read the page of the release its number names, and treat everything since as work in progress.

The version in the user menu links to its release page — for a candidate, to the page of the release it precedes. For an alpha, a beta or anything else that is not a release, it links to how to read a version number.

Where to read your version

The version of the instance you are using is in the user menu, top right. The instance also serves it at /inouk_health_check — the form to use from a script, or to check a server you are not logged into.