Release process
Trigger
Section titled “Trigger”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: falsePushing 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).
What gets produced
Section titled “What gets produced”Every successful v* run publishes four artefacts, all pinned to the same vX.Y.Z:
| Artefact | Where 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.yaml | Attached 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.
Mirror to the in-cluster registry
Section titled “Mirror to the in-cluster registry”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).
Pipeline shape
Section titled “Pipeline shape”The DAG, from the workflow’s own comments:
typecheck ─┐lint │ ┌── helm-publish ──┐test ├── build-arm64 ────────────┐ │ │e2e │ ├── manifest ──────────┼── mirror ├── releasebuild ─────┴── 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.
Version pinning
Section titled “Version pinning”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:
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.
Pre-release discipline
Section titled “Pre-release discipline”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.5v4.6.5-pre.4v4.6.5-pre.3v4.6.5-pre.2v4.6.5-pre.1v4.6.4v4.6.3v4.6.2v4.6.1v4.6.0A clean vX.Y.Z is cut only after the matching pre series has stabilised.
Changesets
Section titled “Changesets”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.