Release Management
Release management coordinates when and how Python services ship: versioning rules, release trains, change approvals, and communication. Good release hygiene makes rollback credible and stakeholders predictable.
Search across all documentation pages
Release management coordinates when and how Python services ship: versioning rules, release trains, change approvals, and communication. Good release hygiene makes rollback credible and stakeholders predictable.
Quick-reference recipe card - copy-paste ready.
# Release: orders-api v2026.07.09
## Artifacts
- Image: `orders-api:sha-9f2a1bc` (Python 3.14.0)
- Wheel (internal lib): `acme-billing==2.4.0`
## Migrations
- alembic `20260709_add_tax_code` (expand, backward compatible)
## Rollback
- `kubectl rollout undo` to `sha-7c1b2aa`
- Pause `billing` workers if queue depth > 5k
## Stakeholders
- #releases, support macro updatedWhen to reach for this:
"""version_bump.py - automate service version metadata for release notes."""
from __future__ import annotations
import subprocess
from dataclasses import dataclass
from datetime import date
@dataclass(frozen=True)
class ReleaseMetadata:
service: str
git_sha: str
python: str
release_date: date
def git_short_sha() -> str:
return subprocess.check_output(["git", "rev-parse", "--short", "HEAD"], text=True).strip()
def build_release_notes(meta: ReleaseMetadata, changes: list[str]) -> str:
lines = [
f"# {meta.service} release {meta.release_date.isoformat()}",
f"- Git: `{meta.git_sha}`",
f"- Python: {meta.python}",
"",
"## Changes",
]
lines.extend(f"- {c}" for c in changes)
return "\n".join(lines)
if __name__ == "__main__":
meta = ReleaseMetadata("orders-api", git_short_sha(), "3.14.0", date.today())
print(build_release_notes(meta, ["Add tax code field (nullable)", "Fix Celery retry backoff"]))What this demonstrates:
#releases posts| Type | Cadence | Typical scope |
|---|---|---|
| Standard train | Weekly | Features behind flags |
| Hotfix | Ad hoc | SEV mitigation |
| Library patch | Daily automerge | Security CVE |
| Major platform | Quarterly | Python minor bump |
# pyproject.toml - library versioning
[project]
name = "acme-billing"
version = "2.4.0"
requires-python = ">=3.13":latest in prod - Rollback ambiguity. Fix: Immutable tags with SHA; record in deploy annotation.#releases post is a release gate, not optional.| Alternative | Use When | Don't Use When |
|---|---|---|
| Continuous deploy | Strong flags + canary | Heavy schema coupling |
| GitOps (Argo CD) | K8s fleet | Manual Lambda-only shop |
| Dark launches | ML model swaps | Regulated disclosure required |
| Long-lived branches | Legacy release model | Modern trunk-based team |
Daily to weekly with flags is common when migrations are expand-contract and CFR is low.
Libraries release on demand; services pin versions in lockfile per train.
Rotating engineer owns checklist, comms, and go/no-go for that train.
IC or release captain approves; document exception in change ticket.
No - batch jobs and notebooks have separate promotion with data owner sign-off.
URL or header versioning documented in changelog; consumers pin client SDK.
Per-service tags and release notes; one merge can trigger multiple deploy pipelines.
Link JIRA/Linear tickets in release notes; retain build artifacts 90+ days.
Error budget exhausted, open SEV1, or migration load test failed in staging.
uv speeds CI; release process still gates on tests, migrations, and canary.
Stack versions: This page was written for Python 3.14.0 (stable 3.14, maintenance 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, and uv 0.6+.
Reviewed by Chris St. John·Last updated Jul 16, 2026