Files
turnstone/scripts/release.sh
Patrick Buckley 57080f4615 chore: release infrastructure for dual-track stable/experimental (#282)
* chore: release infrastructure for dual-track stable/experimental

CI/CD changes for the 1.0 release:

- Gate PyPI publish and Docker publish on CI success via workflow_run
- Add docker-publish.yml: builds and pushes to GHCR with smart tagging
  (stable gets :X.Y.Z/:X.Y/:stable/:latest, pre-release gets :experimental)
- Add stable/* and v* tags to CI and docker-scan triggers
- Remove stale [mq] extra and types-redis from CI (Redis MQ deleted)
- Remove stale redis from Renovate package rules

Release tooling:
- scripts/release.sh: bump version, uv lock, commit, tag (with --push)
- docs/releasing.md: documents stable/experimental workflow

Docker:
- Add /workspace mount point (WORKSPACE_MOUNT env var, defaults to empty volume)
- Update .env.example: remove stale Redis/auth-token refs, add workspace/model/discord

README:
- Remove beta warning, add hero image and release tracks table

* fix: derive release tag from git instead of workflow_run.head_branch

Use git tag --points-at HEAD after checkout to resolve the release
tag instead of relying on workflow_run.head_branch, which may not
reliably be the tag name for tag-triggered CI runs. Both publish
and docker-publish workflows now skip cleanly when no v* tag exists
at the checked-out commit.
2026-04-02 17:08:07 -07:00

63 lines
1.7 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# Bump version, regenerate lockfile, commit, and tag.
#
# Usage:
# scripts/release.sh 1.0.0 # stable release
# scripts/release.sh 1.1.0a1 # experimental pre-release
# scripts/release.sh 1.0.1 --push # bump + push tag to origin
#
set -euo pipefail
VERSION="${1:?Usage: scripts/release.sh VERSION [--push]}"
PUSH="${2:-}"
# Validate PEP 440 version
if ! echo "$VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+(a[0-9]+|b[0-9]+|rc[0-9]+)?$'; then
echo "error: invalid PEP 440 version: $VERSION" >&2
echo " examples: 1.0.0, 1.1.0a1, 1.0.1rc2" >&2
exit 1
fi
TAG="v${VERSION}"
# Check for clean working tree
if ! git diff --quiet || ! git diff --cached --quiet; then
echo "error: working tree is dirty — commit or stash first" >&2
exit 1
fi
# Check tag doesn't already exist
if git rev-parse "$TAG" >/dev/null 2>&1; then
echo "error: tag $TAG already exists" >&2
exit 1
fi
# Detect current version
CURRENT=$(grep -oP '(?<=^version = ")[^"]+' pyproject.toml)
echo "Bumping $CURRENT$VERSION"
# Update version in both files
sed -i "s/^version = \".*\"/version = \"$VERSION\"/" pyproject.toml
sed -i "s/^__version__ = \".*\"/__version__ = \"$VERSION\"/" turnstone/__init__.py
# Regenerate lockfile
echo "Regenerating uv.lock..."
uv lock
# Commit and tag
git add pyproject.toml turnstone/__init__.py uv.lock
git commit -m "chore: bump version to $VERSION"
git tag "$TAG"
echo ""
echo "Created commit and tag $TAG"
if [ "$PUSH" = "--push" ]; then
BRANCH=$(git rev-parse --abbrev-ref HEAD)
echo "Pushing $BRANCH + $TAG to origin..."
git push origin "$BRANCH" "$TAG"
else
echo "Run 'git push origin <branch> $TAG' to publish"
fi