Skip to content

Release flow

How Buntime versions the chart vs. the runtime, when to run bump-version.ts, what triggers each CI pipeline, and the two parallel flows: GitHub (main) and self-hosted GitLab (test/gitlab-ci).

To regenerate charts before bumping, see Helm & Kubernetes. To publish @buntime/shared to JSR, see Publishing to JSR.

Buntime maintains two independent versions in sync through pairs of files:

VersionFileTracksPaired with
versioncharts/Chart.yamlChart/releasepackage.json (root)
versionpackage.json (root)Chart/releasecharts/Chart.yaml:version
appVersioncharts/Chart.yamlRuntimeapps/runtime/package.json:version
versionapps/runtime/package.jsonRuntimecharts/Chart.yaml:appVersion

Sync rules (validated by Lefthook hooks):

  • apps/runtime/package.json:version === Chart.yaml:appVersion
  • package.json:version === Chart.yaml:version
  • The two tracks are independent — the chart can be ahead or behind appVersion

Git tags follow the chart version (v0.3.0, v0.3.1, …), never the appVersion.

  • appVersion tracks only the runtime code in apps/runtime/. It does not change when a plugin changes.
  • The Docker image contains the runtime + all plugins. A new image is required whenever either changes.
  • Image rebuild is triggered by a git tag (v*.*.*), created via --tag in the script.
  • The --tag flag is tied to the chart bump, not to appVersion.
Terminal window
bun scripts/bump-version.ts --chart=<bump> [--app=<bump>] [--tag] [--no-commit] [--no-push]
FlagRequiredEffect
--chart=patch|minor|major|x.y.zYesBumps Chart.yaml:version + root package.json:version
--app=patch|minor|major|x.y.zNoBumps apps/runtime/package.json:version + Chart.yaml:appVersion
--tagNoCreates git tag v{chartVersion} (triggers Docker CI)
--no-commitNoDoes not commit
--no-pushNoDoes not push (push happens by default when --tag is set)
Change--tag?--app?
Runtime code (apps/runtime/)YesYes
Plugin code or manifest (plugins/)YesNo
Chart only (charts/templates/, values)NoNo
Chart + runtime togetherYesYes
  • --chart missing → error (always required).
  • --app without --tag → warning.
HookTriggers onValidates
version-syncpackage.json, apps/runtime/package.json, or charts/Chart.yaml stagedversion/appVersion pairs match
chart-versionAny charts/** stagedChart.yaml:version was bumped

Fix: bun scripts/bump-version.ts --chart=<bump>.

Terminal window
# 1. Edit charts/templates/ingress.yaml
# 2. Patch bump for chart only
bun scripts/bump-version.ts --chart=patch
# → chart: 0.2.26 → 0.2.27, root: 0.2.27
# → commits (no tag, no push)
git push origin main
# → helm-publish triggers (path in charts/**)
# → no Docker rebuild

Plugin manifest or code change (image rebuild)

Section titled “Plugin manifest or code change (image rebuild)”
Terminal window
# 1. Edit plugins/plugin-proxy/manifest.yaml or plugin.ts
# 2. Bump chart with tag
bun scripts/bump-version.ts --chart=patch --tag
# → chart: 0.2.26 → 0.2.27, root: 0.2.27
# → commits, tags v0.2.27, pushes
# → docker-publish triggers (tag v0.2.27)
# → helm-publish triggers (charts/** changed via auto-regen)
Terminal window
# 1. Edit apps/runtime/src/
# 2. Bump both versions with tag
bun scripts/bump-version.ts --chart=patch --app=patch --tag
# → runtime: 1.1.0 → 1.1.1, appVersion: "1.1.1"
# → chart: 0.2.26 → 0.2.27, root: 0.2.27
# → commits, tags v0.2.27, pushes
# → docker-publish + helm-publish trigger
Terminal window
bun scripts/bump-version.ts --chart=patch --app=patch --no-commit
git add .
git commit -m "fix: …"

charts/release-notes.md is injected into Chart.yaml as catalog.cattle.io/release-notes (an annotation read by Rancher).

Rules:

  • Describe what changed in that version, not cumulatively.
  • Keep it relevant to chart consumers (runtime, plugins, helm config). Skip internal tooling.
  • Update before running bump-version.ts.

Typical structure:

## What's New
### Runtime
- ...
### CLI
- ...
### Deployment
- ...
### Performance
- ...

Three workflows publish public infrastructure:

WorkflowTriggers onOutput
docker-publish.ymlTags v*.*.*Image ghcr.io/zommehq/buntime:{tag,latest,major,major.minor}
helm-publish.ymlPush to main touching charts/** or plugins/*/manifest.yamlSync to zommehq/charts
jsr-publish.ymlworkflow_dispatch@buntime/shared on JSR via OIDC

Tags published to GHCR on each v*.*.*:

TagExample
latestalways the most recent
{version}0.2.27
{major}.{minor}0.2
{major}0

The image contains the runtime + all built-in plugins. The deployment.yaml template consumes image.tag from the Helm values (default: latest).

zommehq/charts is the public catalog repository. Rancher detects a higher Chart.yaml:version and displays “Upgrade Available”. The publish workflow uses release-notes.md to generate the catalog entry.

Retention: 30 days by default (CLI_ARTIFACT_RETENTION_DAYS).

Download: Actions → Build CLI → run → Artifacts.

Flow 2 — Self-hosted GitLab (branch test/gitlab-ci)

Section titled “Flow 2 — Self-hosted GitLab (branch test/gitlab-ci)”

Pipeline in .gitlab-ci.yml for the gitlab.example.com lab:

JobStageRole
image:buildimageBuild + push to registry.example.com/zomme/buntime
cli:build:linuxcliLinux amd64 + arm64
cli:build:windowscliWindows amd64
cli:build:macosclimacOS amd64 + arm64 (shell runner tagged macos)
TagWhen
$CI_COMMIT_SHORT_SHAAlways (immutable image)
$CI_COMMIT_REF_SLUGAlways (stable per branch/tag)
latestAlways
$CI_COMMIT_TAGOnly when the pipeline runs for a git tag

The publish generates to gitlab.example.com/zomme/charts. The local Rancher instance points to this repository.

Same targets as the GitHub flow, but downloaded under Project → Build → Pipelines → run → Jobs → Download artifacts. Retention CLI_ARTIFACT_EXPIRE_IN (default 30 days).

cli:build:macos runs automatically on git tags or when RUN_MACOS_CLI_BUILD=1; otherwise it is manual on branch pipelines.

RunnerTagRole
Docker executordockerimage:build, Linux CLI, Windows CLI
Shell macOSmacosmacOS CLI (Go 1.23 + Xcode CLT)

For the registry.example.com registry, the DinD in image:build uses --insecure-registry=registry.example.com.

GitLab provides CI_REGISTRY, CI_REGISTRY_IMAGE, CI_REGISTRY_USER, CI_REGISTRY_PASSWORD. No extra required env vars. Optional:

VariableDefaultUse
CLI_ARTIFACT_EXPIRE_IN30 daysArtifact retention
RUN_MACOS_CLI_BUILDunset1 forces macOS build on branches
values-k3s.yaml
image:
repository: registry.example.com/zomme/buntime
tag: runtime-performance-resilience # or commit SHA
pullPolicy: Always
imagePullSecrets:
- name: gitlab-registry

Create the secret in the namespace:

Terminal window
kubectl create secret docker-registry gitlab-registry \
--namespace zomme \
--docker-server=registry.example.com \
--docker-username=<user> \
--docker-password=<token>
Plugin/manifest changed (no runtime change)
→ bun scripts/bump-version.ts --chart=patch --tag
→ Chart.yaml:version = 0.2.27
→ package.json:version = 0.2.27
→ tag v0.2.27 + push
→ CI: GHCR image updated
→ CI: chart synced to zommehq/charts
→ Rancher detects upgrade
Runtime changed
→ bun scripts/bump-version.ts --chart=patch --app=patch --tag
→ apps/runtime/package.json:version = 1.1.1
→ Chart.yaml:appVersion = "1.1.1"
→ Chart.yaml:version = 0.2.27
→ tag v0.2.27 + push
Chart only changed (templates, values)
→ bun scripts/bump-version.ts --chart=patch
→ Chart.yaml:version = 0.2.27 (no tag)
→ manual git push
→ CI: chart sync only (no Docker rebuild)

For gitlab.example.com/rancher.home/registry.example.com to resolve via dnsmasq:

Terminal window
dig @127.0.0.1 gitlab.example.com +short
dig @127.0.0.1 rancher.home +short
dig @127.0.0.1 registry.example.com +short

.home points to the VM’s fixed IP; dnsmasq listens on the host (e.g., 192.168.0.5).