Versioning
All container images and the installer bundle follow semver (MAJOR.MINOR.PATCH). Versioned releases are triggered by git tags.
For the full list of images, workflows, triggers, and secrets, see Build Pipelines.
Tag Conventions
Since ctms.devops hosts multiple services in one repo, each service has its own tag prefix:
api-gateway-v1.2.0 → zynomi/ctms-api-gateway:1.2.0
ctms-init-v1.0.3 → zynomi/ctms-init:1.0.3
supabase-seed-v1.1.0 → zynomi/ctms-supabase-seed:1.1.0
frappe-v1.0.0 → zynomi/frappe-marley-health:1.0.0
bundle-v2.35.20260315 → zynctl-bundle-v2.35.20260315.tar.gz (GitHub Release)
Single-service repos use plain v*.*.*:
v1.5.0 → zynomi/zynexa:1.5.0, 1.5, 1
Bundle Version Format
Bundle releases use a date-stamped version:
bundle-v{MAJOR}.{MINOR}.{YYYYMMDD}
| Segment | Meaning | Example |
|---|---|---|
MAJOR | Platform generation (currently 2) | 2 |
MINOR | Sequential release number (increment by 1) | 35 |
YYYYMMDD | Release date | 20260315 |
Example: bundle-v2.35.20260315 → Platform gen 2, 35th release, built 2026-03-15.
Image Tags per Push
Every push to main produces multiple tags:
| Tag | Example | Purpose |
|---|---|---|
latest | zynomi/zynexa:latest | Always points to newest main build |
1.{run_number} | zynomi/zynexa:1.42 | Auto-incrementing build number |
| Short SHA | zynomi/zynexa:a1b2c3d | Trace back to exact commit |
| Semver (on tag push) | zynomi/zynexa:1.5.0 | Immutable release version |
Creating a Service Release
# Tag a service in ctms.devops
git tag api-gateway-v1.2.0
git push origin api-gateway-v1.2.0
# Tag in single-service repos
git tag v1.5.0
git push origin v1.5.0
Creating a Bundle Release
Bundle releases are coordinated across 4 repos — all get the same tag to mark exactly which code is included in the bundle:
| Repository | Why it gets tagged |
|---|---|
ctms.devops | Docker Compose, configs, env — triggers build |
ctms-web | Zynexa web app, API routes, OpenAPI spec |
docs.zynomi.com | Documentation site, synced OpenAPI spec |
ctms-data-pipeline-ai-analytics | dbt models, ingester, Cube.dev, MCP server |
# 1. Ensure all repos are committed and pushed to main
for repo in ctms.devops ctms-web docs.zynomi.com ctms-data-pipeline-ai-analytics; do
echo "=== $repo ===" && cd /path/to/$repo && git status --short
done
# 2. Find the latest bundle tag
cd /path/to/ctms.devops
git tag -l 'bundle-*' --sort=-version:refname | head -3
# 3. Tag all 4 repos (increment MINOR, use today's date)
TAG="bundle-v2.35.20260315"
MSG="fix: Marquez init, pipeline trigger semantics, env completeness"
for repo in ctms.devops ctms-web docs.zynomi.com ctms-data-pipeline-ai-analytics; do
cd /path/to/$repo && git tag "$TAG" -m "$MSG"
done
# 4. Push all tags (ctms.devops push triggers the bundle build)
for repo in ctms.devops ctms-web docs.zynomi.com ctms-data-pipeline-ai-analytics; do
cd /path/to/$repo && git push origin "$TAG"
done
# 5. Verify the workflow triggered
gh run list --workflow=build-install-bundle.yml --limit 1
Tag Message Convention
Use Conventional Commits prefixes:
git tag bundle-v2.35.20260315 -m "fix: Marquez init, pipeline trigger semantics"
git tag bundle-v2.36.20260320 -m "feat: new analytics dashboard, CDISC export"
git tag bundle-v2.37.20260325 -m "chore: dependency updates, security patches"
Build Caching
All workflows use Docker Buildx with registry-level caching (type=registry). Unchanged layers are reused, so incremental builds are fast.
| Scenario | Behavior |
|---|---|
| No code changes | Fully cached (seconds) |
| App code changes | Only final layers rebuild |
| Dependency changes | Dependency + app layers rebuild |
Multi-Architecture
ctms.devops workflows build for linux/amd64 + linux/arm64. Other repos build linux/amd64 only.
Related
- Build Pipelines — all images, triggers, and secrets
- Installer Bundle — bundle contents and deployment
- Bundle Deployment — deploy using pre-built images
- Environment Variables — runtime configuration reference