Skip to content

Releasing & Versioning

How to cut a release of any Aetos repository. The rule lives in the reference page Versioning & Changelog; this is the runbook you follow.

Every repository is one of two Drone shapes — a PyPI package or a Docker deployment (Drone Pipelines). Both are released the same way: bump the version file, promote the changelog, tag.


🧾 Before you start

  • main is green (the Drone quality gate passed on the last run).
  • You know whether this is a breaking, feature, or fix release.
  • The version file exists:
  • package → version in pyproject.toml
  • service / site → VERSION at the repo root

🚦 Pick the next version

The version file and the tag must be identical. For 0.y.z, 0.y is the major line (see the reference page); once at 1.0.0, normal SemVer applies.

Change 0.y.z → 1.0.0+ →
Breaking 0.(y+1).0 (x+1).0.0
Feature 0.y.(z+1) x.(y+1).0
Fix 0.y.(z+1) x.y.(z+1)

✍️ Promote the changelog

In CHANGELOG.md:

  1. Rename the content under [Unreleased] into a new ## [x.y.z] - YYYY-MM-DD heading (keep the sections that apply).
  2. Leave a fresh, empty ## [Unreleased] on top.
  3. Add the compare links at the bottom:
[Unreleased]: https://git.aetoskia.com/aetos/<repo>/compare/x.y.z...HEAD
[x.y.z]: https://git.aetoskia.com/aetos/<repo>/compare/x.y.(z-1)...x.y.z

🔢 Bump the version file

  • Package: edit version = "x.y.z" in pyproject.toml.
  • Service / site: edit the VERSION file.

Then commit and tag:

1
2
3
4
5
git add CHANGELOG.md pyproject.toml   # or VERSION
git commit -m "chore(release): x.y.z"
git tag x.y.z
git push origin HEAD
git push origin x.y.z

🤖 What Drone does

  • Type A (package): asserts tag == pyproject version, then skips if that version already exists on the index, runs the quality gate, builds, and uploads the wheel + sdist.
  • Type B (service): asserts tag == VERSION, resolves the tag, skips if the image already exists, runs the quality gate, builds, pushes, and restarts the container.
  • Type B (site): triggered on push, ships :latest and has no tag guard.

If the guard fails, nothing is published — fix the version file, amend the commit, and move the tag only if it was never pushed.


🛟 Backfill / recovery

If an older tag never published (a past version-file mismatch, an index outage):

  • Package: run the backfill-pypi-from-tags pipeline (custom event). It checks out every tag, verifies tag == pyproject version at that commit, and uploads the ones missing from the index. Already-fixed history is never rewritten.
  • Service: rebuild the image for the missing tag with a fresh commit and a new patch version; do not move a published tag.

🔁 If a release is wrong

  • Never reuse or force-move a pushed tag.
  • Fix forward: bump to the next patch, promote the changelog, tag again.