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.
Two version tracks
Section titled “Two version tracks”Buntime maintains two independent versions in sync through pairs of files:
| Version | File | Tracks | Paired with |
|---|---|---|---|
version | charts/Chart.yaml | Chart/release | package.json (root) |
version | package.json (root) | Chart/release | charts/Chart.yaml:version |
appVersion | charts/Chart.yaml | Runtime | apps/runtime/package.json:version |
version | apps/runtime/package.json | Runtime | charts/Chart.yaml:appVersion |
Sync rules (validated by Lefthook hooks):
apps/runtime/package.json:version===Chart.yaml:appVersionpackage.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.
Why keep them separate?
Section titled “Why keep them separate?”appVersiontracks only the runtime code inapps/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--tagin the script. - The
--tagflag is tied to the chart bump, not to appVersion.
Unified bump script
Section titled “Unified bump script”bun scripts/bump-version.ts --chart=<bump> [--app=<bump>] [--tag] [--no-commit] [--no-push]| Flag | Required | Effect |
|---|---|---|
--chart=patch|minor|major|x.y.z | Yes | Bumps Chart.yaml:version + root package.json:version |
--app=patch|minor|major|x.y.z | No | Bumps apps/runtime/package.json:version + Chart.yaml:appVersion |
--tag | No | Creates git tag v{chartVersion} (triggers Docker CI) |
--no-commit | No | Does not commit |
--no-push | No | Does not push (push happens by default when --tag is set) |
When to use --tag
Section titled “When to use --tag”| Change | --tag? | --app? |
|---|---|---|
Runtime code (apps/runtime/) | Yes | Yes |
Plugin code or manifest (plugins/) | Yes | No |
Chart only (charts/templates/, values) | No | No |
| Chart + runtime together | Yes | Yes |
Automatic validations
Section titled “Automatic validations”--chartmissing → error (always required).--appwithout--tag→ warning.
Lefthook hooks
Section titled “Lefthook hooks”| Hook | Triggers on | Validates |
|---|---|---|
version-sync | package.json, apps/runtime/package.json, or charts/Chart.yaml staged | version/appVersion pairs match |
chart-version | Any charts/** staged | Chart.yaml:version was bumped |
Fix: bun scripts/bump-version.ts --chart=<bump>.
Common scenarios
Section titled “Common scenarios”Chart template fix (no image rebuild)
Section titled “Chart template fix (no image rebuild)”# 1. Edit charts/templates/ingress.yaml# 2. Patch bump for chart onlybun 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 rebuildPlugin manifest or code change (image rebuild)
Section titled “Plugin manifest or code change (image rebuild)”# 1. Edit plugins/plugin-proxy/manifest.yaml or plugin.ts# 2. Bump chart with tagbun 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)Runtime change (image rebuild)
Section titled “Runtime change (image rebuild)”# 1. Edit apps/runtime/src/# 2. Bump both versions with tagbun 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 triggerPreparatory bump without commit
Section titled “Preparatory bump without commit”bun scripts/bump-version.ts --chart=patch --app=patch --no-commitgit add .git commit -m "fix: …"Release notes
Section titled “Release notes”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- ...Flow 1 — GitHub Actions (branch main)
Section titled “Flow 1 — GitHub Actions (branch main)”Three workflows publish public infrastructure:
| Workflow | Triggers on | Output |
|---|---|---|
docker-publish.yml | Tags v*.*.* | Image ghcr.io/djalmajr/buntime:{tag,latest,major,major.minor} |
helm-publish.yml | Push to main touching charts/** or plugins/*/manifest.yaml | Sync to djalmajr/charts |
jsr-publish.yml | workflow_dispatch | @buntime/shared on JSR via OIDC |
Docker image
Section titled “Docker image”Tags published to GHCR on each v*.*.*:
| Tag | Example |
|---|---|
latest | always 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).
Chart sync
Section titled “Chart sync”djalmajr/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:
| Job | Stage | Role |
|---|---|---|
image:build | image | Build + push to registry.example.com/zomme/buntime |
cli:build:linux | cli | Linux amd64 + arm64 |
cli:build:windows | cli | Windows amd64 |
cli:build:macos | cli | macOS amd64 + arm64 (shell runner tagged macos) |
Published tags
Section titled “Published tags”| Tag | When |
|---|---|
$CI_COMMIT_SHORT_SHA | Always (immutable image) |
$CI_COMMIT_REF_SLUG | Always (stable per branch/tag) |
latest | Always |
$CI_COMMIT_TAG | Only when the pipeline runs for a git tag |
Chart catalog
Section titled “Chart catalog”The publish generates to gitlab.example.com/zomme/charts. The local Rancher instance points to this repository.
CLI artifacts on GitLab
Section titled “CLI artifacts on GitLab”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.
Required runners
Section titled “Required runners”| Runner | Tag | Role |
|---|---|---|
| Docker executor | docker | image:build, Linux CLI, Windows CLI |
| Shell macOS | macos | macOS CLI (Go 1.23 + Xcode CLT) |
For the registry.example.com registry, the DinD in image:build uses --insecure-registry=registry.example.com.
CI/CD variables
Section titled “CI/CD variables”GitLab provides CI_REGISTRY, CI_REGISTRY_IMAGE, CI_REGISTRY_USER, CI_REGISTRY_PASSWORD. No extra required env vars. Optional:
| Variable | Default | Use |
|---|---|---|
CLI_ARTIFACT_EXPIRE_IN | 30 days | Artifact retention |
RUN_MACOS_CLI_BUILD | unset | 1 forces macOS build on branches |
Deploying from GitLab
Section titled “Deploying from GitLab”image: repository: registry.example.com/zomme/buntime tag: runtime-performance-resilience # or commit SHA pullPolicy: AlwaysimagePullSecrets: - name: gitlab-registryCreate the secret in the namespace:
kubectl create secret docker-registry gitlab-registry \ --namespace zomme \ --docker-server=registry.example.com \ --docker-username=<user> \ --docker-password=<token>Version flow (visualization)
Section titled “Version flow (visualization)”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 djalmajr/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)Local lab DNS
Section titled “Local lab DNS”For gitlab.example.com/rancher.home/registry.example.com to resolve via dnsmasq:
dig @127.0.0.1 gitlab.example.com +shortdig @127.0.0.1 rancher.home +shortdig @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).