Versioning and Releases
AgentArea uses a build-once / promote-on-tag release model:- ci.yml builds immutable per-commit Docker images on every merge to
main. - release-publish.yaml never rebuilds. On a semver git tag (
vX.Y.Z), it retags an already-built image with the stable release tags and creates the GitHub Release. - release-helm.yml publishes the Helm chart on the same tag push.
scripts/release.sh, validates pre-conditions and pushes the tag.
Version Architecture
Application Version (VERSION file)
- Location:
VERSIONat repo root. - Purpose: Single source of truth for the application’s version.
- Managed by:
scripts/bump-version.pyvia thePrepare Releaseworkflow. - Propagated to: all
pyproject.toml,package.json,Chart.yamlappVersion,.bumpversion.yaml, Goconst versioninagentarea-mcp-managerandagentarea-event-service.
Chart Version (Chart.yaml version)
- Location:
charts/agentarea/Chart.yamlversionfield. - Bumped automatically by
release-helm.ymlon everyv*tag push (patch by default; manual dispatch lets you choose patch/minor/major). - Independent of application version. Do not edit manually.
Docker Image Tags
What gets pushed when
| Event | Workflow | Tags pushed for each of 7 components |
|---|---|---|
Merge to main | ci.yml → docker-build-push.yml | <version>-<sha> (e.g. 0.0.8-a8eaf7b) — immutable |
Git tag push vX.Y.Z | release-publish.yaml | <version>, <maj.min>, <maj>, latest — all pointing to the same digest as <version>-<sha> (retag, no rebuild) |
Tag semantics
0.0.8-a8eaf7b— Immutable per-commit. Built once by ci.yml. Safe to pin in prod.0.0.8— Immutable semver. Created once by release-publish on tagv0.0.8. Points to the same digest as the<version>-<sha>of that commit. Never overwritten.0.0— Rolling minor. Moves forward to the latest0.0.xrelease.0— Rolling major. Moves forward to the latest0.x.yrelease.latest— Always points to the most recent release.
Tag usage guidelines
| Use case | Tag | Why |
|---|---|---|
| Production pin | 0.0.8-a8eaf7b | Fully traceable, guaranteed not to change |
| Production (auto patch) | 0.0 | Gets patch-level fixes automatically |
| Staging | 0.0.8-<latest-main-sha> | Test unreleased main builds |
| ”Show me the latest” | latest | Most recent release |
Components
Seven Docker images are published:api, worker, frontend, bootstrap, mcp-manager, mcp-runner, events
Registry
All images go to Docker Hub:agentarea/agentarea-<component>.
Release Process
1. Prepare Release (bump VERSION)
Via GitHub UI: Actions → “Prepare Release” → Run workflow → selectpatch/minor/major.
The release-prepare.yaml workflow:
- Runs CI validation (lints, tests, build).
- Runs
scripts/bump-version.py <type>— bumps VERSION and propagates to all version files. - Creates branch
release/vX.Y.Zand opens a PR labelledrelease.
patch— bug fixes (0.0.8 → 0.0.9)minor— new features, backward compatible (0.0.8 → 0.1.0)major— breaking changes (0.0.8 → 1.0.0)
2. Review and merge the release PR
- Verify all version files updated.
- Add release notes to
CHANGELOG.mdif you keep one. - Merge. The merge to
maintriggersci.yml, which builds and pushes0.0.9-<sha>for all 7 components.
3. Publish the release with scripts/release.sh
Once ci.yml is green on the release PR merge commit:
- Working tree is clean.
- On
main(or confirms override). - Local
mainis up-to-date withorigin/main. VERSIONcontains a valid semver; tagv<version>doesn’t already exist locally or on origin.scripts/verify-version-sync.shpasses (all version files agree).ci.ymlis green on HEAD (viaghCLI).- All 7
agentarea-<component>:<version>-<sha>images exist on Docker Hub. - Shows a summary with commit list since the previous tag.
- Asks
y/Nconfirmation. - Creates an annotated tag
v<version>and pushes it to origin.
4. Automated: retag + GitHub Release + Helm chart
The tag push triggers two workflows in parallel:release-publish.yaml:
- Validates tag matches VERSION on the tagged commit.
- For each of 7 components, waits for
<version>-<sha>to appear in Docker Hub (retries up to 15 min ifci.ymlis still running). - Uses
docker buildx imagetools createto add tags<version>,<maj.min>,<maj>,latestto the existing image. No rebuild. Same digest. - Creates a GitHub Release with auto-generated notes from
git log <prev-tag>..HEAD.
release-helm.yml:
- Bumps chart
version(patch by default). - Packages the chart and publishes to the
agentarea/helm-chartsrepo.
TL;DR Release Checklist
Key Invariants
<version>(bare semver) is published exactly once, via retag. It is never overwritten.<version>-<sha>is built byci.ymlon every merge to main. Immutable per-commit.<version>-<sha>and<version>on the release commit share the same digest — they are the exact same image under different tags.VERSIONalways contains a stable semver (no-rc,-beta). Pre-release testing uses<version>-<sha>directly.- Chart
versionis owned byrelease-helm.yml; do not edit it manually.
Why This Model
Problem (before):ci.yml pushed both <version> and <version>-<sha> on every merge to main. The bare <version> tag was overwritten on every merge, breaking immutability (prod and staging could both run 0.0.8 but be different images) and making rollback unreliable.
Fix: ci.yml pushes only <version>-<sha>. Promotion to the stable <version> tag happens exactly once, via retag, when someone pushes a semver git tag. The image is never rebuilt — semver tag and dev tag are bit-identical.
Verification
Manual CI check anyone can run:.bumpversion.yamlcurrent_versionmatches VERSION- All
pyproject.tomlfiles match VERSION package.jsonmatches VERSIONChart.yamlappVersion matches VERSION- Go
const versionmatches VERSION (mcp-manager, event-service) - Chart
versionis not checked (intentionally independent)
version-check job in ci.yml.
Troubleshooting
Versions out of sync
verify-version-sync.sh or ci.yml fails with a mismatch.
release.sh says “tag already exists on origin”
Someone (or a prior run) already pushed v<version>. If you need to re-release the same version:
release.sh says images are missing in Docker Hub
ci.yml hasn’t finished building the release commit yet, or some component’s build failed.
Helm dev release needs testing before a full release
Use manual dispatch onrelease-helm.yml via the Actions UI. That path is not covered by release.sh.
Hotfix on an older release
Related Files
VERSION— source of truthscripts/bump-version.py— bumps VERSION + all consumersscripts/release.sh— pre-flight + tag pushscripts/verify-version-sync.sh— consistency checkscripts/sync-versions.py— emergency resyncscripts/update-appversion.py— sync Chart.yaml appVersion to VERSIONscripts/bump-chart-version.py— chart version bumper (used by release-helm.yml).github/workflows/release-prepare.yaml— opens release PR.github/workflows/ci.yml→docker-build-push.yml— builds<version>-<sha>on main.github/workflows/release-publish.yaml— retags on tag push, creates GitHub Release.github/workflows/release-helm.yml— publishes Helm chart on tag push