Files
docs/standards/src/wiki/04_development/02_releasing.md
Vishesh 'ironeagle' Bangotra 5971f26c08 feat(standards): MR-based tag strategy + repository inventory (registry://repos)
Versioning standard now documents the MR flow: bump pyproject.toml/VERSION and promote CHANGELOG in the MR (referencing the version/tag, not a commit id), merge/squash, then tag the resulting commit. Adds the agent-assisted tagging procedure (wait for the go-ahead, find the version-bump commit, tag only it, ask the user to push) to both the reference page and the releasing wiki runbook. Adds the repo inventory (src/repos.json -> mcp/repos.json), the registry://repos resource + list_repos tool, the 15_repository_inventory lib page, and two MCP prompts: compliance (remediate repos) and release (agent tagging).
2026-10-15 14:39:21 +05:30

4.2 KiB

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 release the same way: the version bump and changelog promotion go in the merge request, and the tag is created on the merged commit.


🧾 Before you start

  • You have an open merge request holding the change, and 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)

🌿 Release in the MR

The version is known while the change is still a merge request, so the bump rides along with it. Do both edits in the MR:

  • Promote the changelog in CHANGELOG.md: move the [Unreleased] content under a new ## [x.y.z] - YYYY-MM-DD heading, leave a fresh empty [Unreleased] on top, and add the compare links — naming the version/tag, never a commit id:

    [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 to the intended release version: version = "x.y.z" in pyproject.toml (packages) or the VERSION file (services/sites).


🏷️ Tag the merged commit

  1. Merge or squash the MR into main.
  2. Create the tag on the resulting commit: git tag x.y.z (lightweight).
  3. Push the tag (git push origin x.y.z) — Drone builds the release.

🤖 Agent-assisted tagging

The agent does not author or merge the MR and never tags before the merge. After you confirm the MR is merged/squashed and tell it to proceed, the agent:

  1. Waits for that explicit go-ahead.
  2. Finds the commit that introduced the bump:
    • package: git log -S 'version = "x.y.z"' -n 1 --format='%H %s' -- pyproject.toml
    • service / site: git log -S 'x.y.z' -n 1 --format='%H %s' -- VERSION
  3. Verifies that commit's version file equals x.y.z, then tags only that commit: git tag x.y.z <sha>.
  4. Does not push — it asks you to run 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.