Make your first release

Picks up after First-run setup: you have a green dev cycle. This tutorial cuts a real release — branch, bump, changelog, tag, push.

Step 1 — Write a feature

Open src/afas_mcp_server/afas_mcp_server.py and edit hello():

def hello(someone: str = 'you') -> str:
    """Greet `someone` and announce the project."""
    return f'Hello {someone} from afas_mcp_server!'

Update the smoke test under tests/ to match. Confirm the dev cycle is still green:

./workflow.cmd format && ./workflow.cmd lint && ./workflow.cmd test

Step 2 — Commit with Conventional Commits

git add -A
git commit -m "feat: greet someone by name"

The prefix does not drive the version bump — you'll pass that explicitly in the next step. What it drives is the release notes: when commitizen generates the changelog, it groups commits by prefix (feat: under "Features", fix: under "Bug Fixes", etc.). The lint step rejects any message that doesn't parse as Conventional Commits.

Step 3 — Cut the release

./workflow.cmd release -i minor

-i is your explicit version-increment choice (major, minor, patch, alpha, beta, or rc). The template does not infer it from commit messages.

The release task is the orchestrator. In order, it:

  1. Validates — working tree is clean and synced with origin, you're on main.
  2. Resolves the next version — runs cz bump --dry-run to project the new version.
  3. Checks for collisions — fails if the target tag or release/<version> branch already exists locally or on origin.
  4. Branchesgit checkout -b release/<version>.
  5. Bumpscz bump writes the new version into pyproject.toml and creates the tag.
  6. Updates the changelogcz changelog regenerates docs/changelog.md and commits it. Signing follows your commit.gpgsign setting; if signing is configured but no key can be reached — the usual case in CI — the commit is made unsigned and says so. Nothing is committed when the changelog is already current.
  7. Pushes — branch and tag both go to origin.
  8. Opens the PR/MR — via the host's API when a token is set, otherwise prints a URL you can open yourself. Set GITHUB_TOKEN to a token with Pull requests: read/write.

Pass --no-push to keep the branch and tag local for inspection.

Step 4 — Approve and merge

On your git host, approve the release PR/MR and merge with a merge commit (not a squash). The tag and bump land on main. If CI is configured for trusted publishing, release.publish fires automatically when the tag appears on main and your wheel lands on PyPI.

Verify

  • pip install <your_project_slug>==<new_version> from a fresh venv succeeds.
  • pypi.org/project/<your_project_slug>/ shows the new version.

You're done

You've cut a release. Next: