Skip to content

Release Process

This page documents the release process for trueppm-suite. Releases are created by running scripts/release.sh on main, which bumps all version manifests, rotates the changelog, commits, and creates an annotated git tag. Pushing the tag triggers the CI publish jobs.

Before cutting any release:

  1. All MRs for the milestone are merged. Check with glab issue list --milestone <version>.
  2. main pipeline is green. Releases are cut from a clean, passing main.
  3. Changelog fragments are present. Every user-visible change should have a fragment in changelog.d/. Run bash scripts/assemble-changelog.sh --dry-run to preview the assembled changelog.
  4. Smoke test passes.
    Terminal window
    make release-smoke
    This boots the dev stack, seeds the demo project, and curls every shipped endpoint. Fix any failures before proceeding.

TruePPM follows semantic versioning. The script manages both stable and pre-release series:

CommandExampleResult
./scripts/release.sh patch0.1.0 → 0.1.1Bugfix release
./scripts/release.sh minor0.1.0 → 0.2.0New features, backwards-compatible
./scripts/release.sh major0.1.0 → 1.0.0Breaking changes
./scripts/release.sh minor alpha0.1.0 → 0.2.0-alpha.1Start alpha series
./scripts/release.sh alpha0.2.0-alpha.1 → 0.2.0-alpha.2Next alpha
./scripts/release.sh beta0.2.0-alpha.2 → 0.2.0-beta.1Promote to beta
./scripts/release.sh rc0.2.0-beta.1 → 0.2.0-rc.1Promote to RC
./scripts/release.sh release0.2.0-rc.1 → 0.2.0Finalize pre-release
./scripts/release.sh 1.2.3explicitPin to specific version

Pre-release CHANGELOG behaviour: Alpha/beta/RC bumps do NOT rotate the [Unreleased] section — notes accumulate until the final stable release.

Terminal window
# 1. Ensure you're on a clean, up-to-date main
git checkout main && git pull origin main
git status # must be clean
# 2. Verify the milestone is complete
glab issue list --milestone 0.2 # should return 0 open issues
# 3. Run the smoke test
make release-smoke
# 4. Cut the release
./scripts/release.sh minor # e.g. 0.1.0 → 0.2.0
# 5. Review the generated commit and tag
git log --oneline -3
git show v0.2.0 --stat
# 6. Push — this triggers the CI publish jobs
git push origin main v0.2.0

The git push origin main v0.2.0 command triggers three CI publish jobs:

  • api:publish — pushes ghcr.io/trueppm/api:0.2.0, 0.2, and latest
  • web:publish — pushes ghcr.io/trueppm/web:0.2.0, 0.2, and latest
  • helm:publish — packages and pushes the Helm chart to oci://ghcr.io/trueppm/charts

Additionally, if you push a scheduler-v* tag, scheduler:publish publishes trueppm-scheduler to PyPI. Scheduler releases are versioned independently (see below).

The scheduler package (packages/scheduler) is versioned independently from the rest of the platform. Its tag format is scheduler-v* (e.g. scheduler-v0.2.0), not v*.

Terminal window
# Bump the scheduler version and push its tag
./scripts/release.sh minor # bumps all manifests including scheduler
git push origin main scheduler-v0.2.0

The scheduler:publish CI job fires on scheduler-v* tags and publishes to PyPI.

After pushing the OSS tag, run the enterprise release script in trueppm-enterprise:

Terminal window
cd ../trueppm-enterprise
./scripts/release.sh --oss-tag v0.2.0

The enterprise script pins TRUEPPM_OSS_TAG to the OSS release and bumps the enterprise version independently.

For a critical fix on an already-released version:

Terminal window
# Branch from the release tag
git checkout -b fix/critical-bug v0.1.0
# Apply the fix, commit, open an MR back to main
# After the MR merges to main, cherry-pick or re-cut as a patch release:
git checkout main && git pull origin main
./scripts/release.sh patch # 0.1.0 → 0.1.1
git push origin main v0.1.1
FileChange
packages/scheduler/pyproject.tomlversion = "x.y.z"
packages/api/pyproject.tomlversion = "x.y.z"
packages/web/package.json"version": "x.y.z"
CHANGELOG.md[Unreleased][x.y.z] - YYYY-MM-DD (stable only)

The Helm chart version in packages/helm/Chart.yaml is kept in sync manually — bump version and appVersion to match before running release.sh.

“Tag vX.Y.Z already exists” — the tag was already pushed. Check if the CI jobs ran correctly; if the images are already published, no action is needed.

“Working tree is not clean” — stash or commit pending changes before running the script.

“[Unreleased] section is empty” — add changelog fragments to changelog.d/ and run bash scripts/assemble-changelog.sh to populate [Unreleased] before releasing.

CI publish job fails — verify GHCR_TOKEN and GHCR_USER are set in GitLab CI/CD variables (Settings → CI/CD → Variables) and that the PAT has write:packages scope.