#!/usr/bin/env bash # Build one complete release commit: version bump (or sync to a given # version, or no bump at all), changelog entry, and refreshed README # badges — all in a single commit, tagged at the end. Used by both the # merge-to-master release job and the hand-pushed-tag sync job, so "the # tag == a complete release commit" holds either way a release gets made. # # Usage: release-commit.sh [--no-bump|VERSION] # (no argument) bump the current patch version (normal merge path). # --no-bump don't touch the version — the branch already bumped it # (e.g. a manual minor/major bump); just build the # changelog/badge commit for whatever version is current. # VERSION sync the project to this exact version (tag-sync path). # # Preconditions: repo is checked out with full history (fetch-depth: 0), # `uv` is available and synced, and git user.name/user.email are configured. # Idempotent: if the resulting tag already exists, this is a no-op. set -euo pipefail VERSION_ARG="${1:-}" if [ "$VERSION_ARG" = "--no-bump" ]; then echo "Version already bumped by this branch; using current version as-is" elif [ -n "$VERSION_ARG" ]; then echo "Syncing project version to $VERSION_ARG" uv version "$VERSION_ARG" --no-sync uv lock else CURRENT_VERSION=$(uv version --short) echo "Bumping patch version from $CURRENT_VERSION" uv run bump-my-version bump patch --current-version "$CURRENT_VERSION" --no-commit --no-tag # bump-my-version's pre_commit_hooks (uv lock + git add uv.lock) only run # on its own commit path, which we skipped with --no-commit — so do it here. uv lock fi VERSION=$(uv version --short) TAG="v$VERSION" if git rev-parse "$TAG" >/dev/null 2>&1; then echo "Tag $TAG already exists; nothing to do" exit 0 fi uv run git-cliff --tag "$TAG" --unreleased --prepend CHANGELOG.md TEST_COUNT=$(uv run pytest --collect-only -q 2>/dev/null | grep -oE '^[0-9]+ tests? collected' | grep -oE '^[0-9]+') sed -i -E "s|badge/version-[^-]+-informational|badge/version-${VERSION}-informational|" README.md sed -i -E "s|badge/tests-[0-9]+%20passing-brightgreen|badge/tests-${TEST_COUNT}%20passing-brightgreen|" README.md # .bumpversion.toml stores its own current_version, which bump-my-version # rewrites even with --no-commit — must be staged or the next run sees a # dirty tree and bump-my-version refuses (allow_dirty = false). git add pyproject.toml .bumpversion.toml uv.lock CHANGELOG.md README.md if git diff --cached --quiet; then echo "Nothing changed; skipping release commit" exit 0 fi git commit -m "chore: release $TAG" git tag -a "$TAG" -m "$TAG" echo "Created release commit and tag $TAG"