3
Versioning
Justin Klein edited this page 2026-10-13 18:48:54 +00:00

Versioning

The scheme

version: 1.4.0+up1.9.2
appVersion: 1.9.2

version: <chart-semver>+up<appVersion>. The +up suffix always matches appVersion, with dashes normalized to dots:

appVersion suffix
1.9.2 +up1.9.2
v1.159.0 +upv1.159.0
0.0.36-beta +up0.0.36.beta
2026.8.2-java25 +up2026.8.2.java25

appVersion is the exact image tag of the main app image. That is what makes the suffix mechanical rather than a judgement call.

Bump levels for the chart part

The chart jump is the greater of the chart's own classification and the jump of what it ships — a maximum, never a replacement. So a value that becomes required is a chart major even when the app moved by a patch, and the chart version never stops reporting the chart's own breaks.

Level When — chart's own change When — app/dependency jump
Patch bug fixes without a behaviour or values-schema change app patch, digest or pin
Minor additive, backward-compatible changes — a new optional value whose default leaves the render unchanged; a new or reworked NOTES.txt (it renders no Kubernetes object) app minor
Major runtime behaviour changes or breaking values changes: probes, security hardening, computed limits, resource renames, a value that becomes required, adding checksum/config to an existing chart app major

The major cases share one property: after the upgrade the cluster does something it did not do before. Adding a checksum/config annotation is the least obvious of them — from then on a config change costs a restart, and some workloads take minutes to come back. Name that cost in the PR.

The right-hand column is not a reviewer's judgement: ci/renovate-bump-chart.sh writes it from Renovate's update type, which is why the two columns can be compared at all. Details, including the seven charts whose non-semver app versions stay at a patch and what the rule deliberately does not oblige anyone to read: Renovate → the version-bump hook.

Every chart change must bump the version

A push to main touching a chart directory publishes that chart. The build-chart job compares version: against the base branch and fails the PR if it is unchanged. template-chart is exempt — it is never published.

The registry accepts a re-upload of an existing version and replaces the artifact, so the version check is the only thing standing between a forgotten bump and a silently overwritten release.

App-version updates go through PRs

So that the validate and install-test pipelines actually run. The change-app-version.yml dispatch workflow commits directly to main and bypasses both; it exists for one-off cases, not as the normal path. The normal path is a Renovate PR.

App-major jumps are taken one line at a time

A v1 → v3 jump is two PRs: first to the last release of the old major line, merged and published, then to the newest major. Renovate produces exactly that shape itself via separateMultipleMajor.

Majors automerge like everything else — the review is what holds them, not a separate manual-merge rule (see Renovate → PR policy). The order is therefore kept at the review: approve the old-line PR first, let it merge and publish, and the new-major PR rebases onto it. Approving both at once hands the sequence to whichever pipeline turns green first, which is the one thing this procedure exists to prevent.

The reason is migrations: most apps support an upgrade from the previous major, not from any major. Skipping the intermediate release means the app's own migration path never runs, and the failure arrives inside a database that the new version has already started rewriting.

Who writes the version

  • A human, in any PR that changes the chart.
  • ci/renovate-bump-chart.sh, wired up as a Renovate postUpgradeTasks command. It receives the chart directory and the update type, and the chart jump follows it: major → chart major, minor → chart minor, patch/digest/pin → chart patch. No or an unknown update type falls back to the pre-decision behaviour (app major changed → major, otherwise patch), so a hook that loses its second argument still bumps the version instead of leaving every chart PR red. The +up suffix is recomputed from the new appVersion. Everything is derived from the base commit, so it is idempotent across the several updates one Renovate branch can carry — and it never lowers a higher version already on the branch, which is what makes a grouped PR's level independent of the order the updates are processed in.

Nothing else writes version:. That is also how one can tell whether the hook ran at all — see Renovate.

Frozen lines

minecraft-server is the one chart with published versions that will never be changed again: only the newest Java line is maintained out of the directory, and the older lines stay as frozen artifacts (java8 and java17 at 4.0.0, java21 at 4.1.0). Publishing several lines out of one directory is what made them drift in the first place. To run an older JVM with the current chart, set image.tagOverride rather than installing a frozen version — see minecraft-server.