Skip to content

Release process

The release pipeline lives in .github/workflows/release.yml and is driven by Git tags:

on:
push:
tags: ['v*']
workflow_dispatch:
inputs:
tag:
description: 'Existing v* tag to publish (omit to use github.ref_name)'
required: false

Pushing a v* tag runs the full pipeline. workflow_dispatch lets you re-run the workflow from master while publishing an existing tag (useful when fixing workflow logic without recutting the tag).

Every successful v* run publishes four artefacts, all pinned to the same vX.Y.Z:

ArtefactWhere it lands
Server image (multi-arch linux/amd64 + linux/arm64)ghcr.io/azrtydxb/kryton/kryton:vX.Y.Z, plus X.Y and latest tags
Operator image (multi-arch)ghcr.io/azrtydxb/kryton/kryton-operator:vX.Y.Z, plus X.Y and latest tags
Helm chart (OCI)oci://ghcr.io/azrtydxb/charts/kryton:X.Y.Z
kryton-crds.yamlAttached to the GitHub Release (concatenation of every CRD under operator/config/crd/bases/)

The release job at the end of the workflow calls softprops/action-gh-release@v2 with notes generated by orhun/git-cliff-action@v4 from cliff.toml, and attaches kryton-crds.yaml.

The mirror job copies the server image, operator image, and helm chart from ghcr.io to the in-cluster zot at 192.168.10.123:5000 using skopeo copy. From there the cluster’s Harbor instance (harbor.kw.local) serves the same tags inside the cluster network.

This is a non-blocking mirror: the GitHub Release is still cut even if mirror fails (the release job does not depend on mirror).

The DAG, from the workflow’s own comments:

typecheck ─┐
lint │ ┌── helm-publish ──┐
test ├── build-arm64 ────────────┐ │ │
e2e │ ├── manifest ──────────┼── mirror ├── release
build ─────┴── build-amd64 ────────────┘ │ │
├── build-operator-arm64 ─┐ └── manifest-operator
└── build-operator-amd64 ─┴── manifest-operator ──┘

release waits on manifest, manifest-operator, and helm-publish (plus the upstream quality gates). It does not wait on mirror.

The chart’s appVersion and version are stamped from the tag at publish time. helm-publish resolves the version from the tag (${REF#v}) and calls:

Terminal window
helm package charts/kryton \
--version "${VERSION}" \
--app-version "${VERSION}" \
--destination .

The committed charts/kryton/Chart.yaml carries an in-development version for local work (currently 4.6.5-pre.5); only the tagged build is what consumers install.

Iteration toward a new version uses vX.Y.Z-pre.N tags. The 10 most recent tags follow that convention exactly:

v4.6.5-pre.5
v4.6.5-pre.4
v4.6.5-pre.3
v4.6.5-pre.2
v4.6.5-pre.1
v4.6.4
v4.6.3
v4.6.2
v4.6.1
v4.6.0

A clean vX.Y.Z is cut only after the matching pre series has stabilised.

The repo includes .changeset/ with @changesets/cli configured (baseBranch: master, access: public). It is used to collect notes for the @azrtydxb/kryton-init and @azrtydxb/kryton-mcp CLI packages, which publish on cli-v* tags via a separate workflow (.github/workflows/cli-publish.yml). The four server/client/sdk/ui workspaces are listed under ignore in .changeset/config.json — their version bumps come from the v* tag, not from changesets.