Skip to content

Plan: OpenAPI Version Bump on Every Release

Archived: fully implemented as of 2026-05-05. Option B (release-please) shipped in PR #358. All success criteria met.

Status: Done — Option B (release-please) implemented Scope: Auto-increment api/main.py version on every prod deploy/tag


Goal

The OpenAPI version field in api/main.py (e.g. version="0.8.0") should always match the current release tag. Today it is bumped manually and often lags behind.


Current State

api/main.py:

python
app = FastAPI(
    title="Portfolio API",
    version="0.8.0",   # ← manual, often stale
    ...
)

The version appears in Swagger UI and the generated OpenAPI JSON. It is not connected to git tags.


Approach Options

Option A — Bump in CI before deploy (simplest)

In deploy-application.yml, after the tag is resolved:

bash
VERSION=$(git describe --tags --abbrev=0 | sed 's/^v//')
sed -i "s/version=\"[^\"]*\"/version=\"$VERSION\"/" api/main.py

Then build the Docker image with the updated file. Version is baked into the image.

  • Pros: zero extra tooling, works today
  • Cons: doesn't commit the change back to main (version in repo stays stale)

Option B — release-please (preferred, aligns with roadmap)

release-please reads Conventional Commits, creates a Release PR with bumped version in api/main.py (via extra-files), and generates a changelog. Merging the Release PR creates the tag.

yaml
# .release-please-manifest.json
{
  ".": "0.8.0"
}

# release-please-config.json
{
  "packages": {
    ".": {
      "release-type": "python",
      "extra-files": ["api/main.py"]
    }
  }
}
  • Pros: version always committed to main; changelog auto-generated; replaces manual v* tag pushes
  • Cons: requires setup; slight workflow restructure

Option C — Read version from git tag at runtime

python
import subprocess
version = subprocess.check_output(["git", "describe", "--tags"]).decode().strip()
app = FastAPI(version=version)
  • Pros: always accurate
  • Cons: git not available in container; fragile

Recommendation

Short term: Option A — sed in CI, zero friction. Long term: Option B — release-please replaces manual tag pushes (already on roadmap as release-please).


Option A Implementation (deploy-application.yml)

Add after "Checkout repository", before "Build and Push" steps:

yaml
- name: Set API version from tag
  run: |
    VERSION=$(git tag --sort=-version:refname | head -1 | sed 's/^v//')
    if [[ -n "$VERSION" ]]; then
      sed -i "s/version=\"[^\"]*\"/version=\"$VERSION\"/" api/main.py
      echo "API version set to $VERSION"
    fi

Option B Implementation (release-please)

  1. Add .github/workflows/release-please.yml
  2. Add release-please-config.json + .release-please-manifest.json to repo root
  3. Configure extra-files: ["api/main.py"] so release-please patches the version string
  4. On merge to main: release-please opens a "Release v0.x.0-alpha" PR
  5. Merging that PR → creates tag → triggers existing deploy workflows

release-please-config.json

json
{
  "release-type": "simple",
  "packages": {
    ".": {
      "changelog-path": "CHANGELOG.md",
      "extra-files": [
        {
          "type": "generic",
          "path": "api/main.py",
          "search-pattern": "version=\"[^\"]*\""
        }
      ]
    }
  }
}

Success Criteria

  • [x] GET /api/openapi.json returns "version" matching the current release tag
  • [x] Version visible in Swagger UI matches what is deployed
  • [x] No manual version bump required for releases