Skip to content

Cut Release

Cut Release #1

Workflow file for this run

# AgentOps Toolkit — Cut Release
#
# Workflows:
# 1. ci.yml — Lint + test on every push/PR
# 2. _build.yml — Reusable build (test + package), called by staging and release
# 3. staging.yml — Staging: release/* branch → TestPyPI → verify
# 4. release.yml — Production: v* tag → TestPyPI → verify → PyPI → GitHub Release
# 5. cut-release.yml — Manual dispatch: create release branch + PR from develop
#
# One-click release branch creation. Triggered manually from the Actions tab.
# Creates a release branch from develop, updates CHANGELOG.md, and opens a PR to main.
# The branch push then triggers staging.yml automatically.
#
# Usage:
# Actions tab → "Cut Release" → "Run workflow" → enter version (e.g. 0.2.0)
name: Cut Release
on:
workflow_dispatch:
inputs:
version:
description: "Release version (e.g. 0.2.0) — no 'v' prefix"
required: true
type: string
permissions:
contents: write
pull-requests: write
jobs:
cut-release:
runs-on: ubuntu-latest
steps:
- name: Validate version format
run: |
VERSION="${{ inputs.version }}"
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "::error::Version must be in semver format (e.g. 0.2.0), got: $VERSION"
exit 1
fi
echo "version=$VERSION" >> "$GITHUB_ENV"
- name: Checkout develop
uses: actions/checkout@v4
with:
ref: develop
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Check release branch does not exist
run: |
if git ls-remote --exit-code origin "refs/heads/release/v${{ env.version }}" >/dev/null 2>&1; then
echo "::error::Branch release/v${{ env.version }} already exists. Delete it first or use a different version."
exit 1
fi
- name: Check CHANGELOG has Unreleased section
run: |
if ! grep -q '## \[Unreleased\]' CHANGELOG.md; then
echo "::error::CHANGELOG.md is missing the [Unreleased] section."
exit 1
fi
- name: Create release branch
run: |
git checkout -b "release/v${{ env.version }}"
- name: Update CHANGELOG
run: |
DATE=$(date +%Y-%m-%d)
# Replace [Unreleased] with versioned section, add fresh Unreleased above
sed -i "s/## \[Unreleased\]/## [Unreleased]\n\n## [${{ env.version }}] - $DATE/" CHANGELOG.md
- name: Configure git
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
- name: Commit and push
run: |
git add CHANGELOG.md
git commit -m "chore: prepare release ${{ env.version }}"
git push origin "release/v${{ env.version }}"
- name: Create PR to main
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh pr create \
--base main \
--head "release/v${{ env.version }}" \
--title "Release v${{ env.version }}" \
--body "## Release v${{ env.version }}
Automated release branch created from \`develop\`.
### What happened
- Branch \`release/v${{ env.version }}\` created from \`develop\`
- \`CHANGELOG.md\` updated: \`[Unreleased]\` → \`[${{ env.version }}]\`
- Staging pipeline triggered automatically (build → TestPyPI → verify)
### Next steps
1. Wait for the **Staging** pipeline to pass
2. Review and approve this PR
3. Merge to \`main\`
4. Tag and push: \`git tag v${{ env.version }} && git push origin v${{ env.version }}\`
5. Approve the PyPI publish in the **Release** workflow
6. Sync develop: \`git checkout develop && git merge main && git push origin develop\`
### Checklist
- [ ] Staging pipeline passes (build + TestPyPI + verify)
- [ ] CHANGELOG entries reviewed
- [ ] PR approved and merged to main
- [ ] Tag \`v${{ env.version }}\` pushed
- [ ] PyPI publish approved
- [ ] develop synced from main"
- name: Summary
run: |
echo "## ✅ Release branch created" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "- Branch: \`release/v${{ env.version }}\`" >> "$GITHUB_STEP_SUMMARY"
echo "- CHANGELOG updated with version **${{ env.version }}**" >> "$GITHUB_STEP_SUMMARY"
echo "- PR opened: \`release/v${{ env.version }}\` → \`main\`" >> "$GITHUB_STEP_SUMMARY"
echo "- Staging pipeline triggered automatically" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "### Next: wait for staging, then tag \`v${{ env.version }}\` to publish" >> "$GITHUB_STEP_SUMMARY"