-
Notifications
You must be signed in to change notification settings - Fork 558
refactor: extract build-and-publish workflow into reusable component #488
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
ashwin-ant
wants to merge
1
commit into
main
Choose a base branch
from
ashwin/refactor-publish-workflow
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+244
−161
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
- Refactor publish.yml to use a reusable workflow for build and publish steps
- Add new build-and-publish.yml as a reusable workflow that handles wheel building, PyPI publishing, and PR creation
- Add auto-release.yml for automated releases triggered by version changes
- Simplify publish.yml to only handle tests, lint, and orchestration
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Generated-By: Claude Code (cli/claude-opus-4-5=100%)
Claude-Steers: 17
Claude-Permission-Prompts: 1
Claude-Escapes: 1
Claude-Plan:
<claude-plan>
# Automated Release on CLI Version Bump
## Overview
Create a new workflow that automatically publishes to PyPI when a CLI version bump commit passes CI.
**Trigger**: Commit message starting with `chore: bump bundled CLI version to` pushed to main, after Test workflow succeeds.
**Actions**:
1. Auto-increment SDK patch version (0.1.20 → 0.1.21)
2. Build platform-specific wheels (linux, linux-arm, macos, windows)
3. Publish to PyPI
4. Update version files + changelog
5. Push directly to main (via deploy key)
6. Create git tag + GitHub Release
## Files to Create/Modify
### New: `.github/workflows/auto-release.yml`
```yaml
name: Auto Release on CLI Bump
on:
workflow_run:
workflows: ["Test"]
types: [completed]
branches: [main]
jobs:
check-trigger:
runs-on: ubuntu-latest
if: |
github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.event == 'push' &&
startsWith(github.event.workflow_run.head_commit.message, 'chore: bump bundled CLI version to')
outputs:
version: ${{ steps.version.outputs.version }}
previous_tag: ${{ steps.previous_tag.outputs.previous_tag }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get current SDK version and calculate next
id: version
run: |
CURRENT=$(python -c "import re; print(re.search(r'__version__ = \"([^\"]+)\"', open('src/claude_agent_sdk/_version.py').read()).group(1))")
IFS='.' read -ra PARTS <<< "$CURRENT"
NEXT="${PARTS[0]}.${PARTS[1]}.$((PARTS[2] + 1))"
echo "version=$NEXT" >> $GITHUB_OUTPUT
echo "Current: $CURRENT -> Next: $NEXT"
- name: Get previous release tag
id: previous_tag
run: |
PREVIOUS_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
echo "previous_tag=$PREVIOUS_TAG" >> $GITHUB_OUTPUT
build-wheels:
needs: check-trigger
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, ubuntu-24.04-arm, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install build dependencies
run: pip install build twine wheel
shell: bash
- name: Build wheel with bundled CLI
run: python scripts/build_wheel.py --version "${{ needs.check-trigger.outputs.version }}" --skip-sdist --clean
shell: bash
- uses: actions/upload-artifact@v4
with:
name: wheel-${{ matrix.os }}
path: dist/*.whl
if-no-files-found: error
publish:
needs: [check-trigger, build-wheels]
runs-on: ubuntu-latest
permissions:
contents: write
env:
VERSION: ${{ needs.check-trigger.outputs.version }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ssh-key: ${{ secrets.DEPLOY_KEY }}
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Update version files
run: python scripts/update_version.py "$VERSION"
- uses: actions/download-artifact@v4
with:
path: dist
pattern: wheel-*
merge-multiple: true
- name: Build sdist and publish to PyPI
run: |
pip install build twine
python -m build --sdist
twine upload dist/*
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
- name: Commit version changes
run: |
git config user.email "github-actions[bot]@users.noreply.github.com"
git config user.name "github-actions[bot]"
git add pyproject.toml src/claude_agent_sdk/_version.py
git commit -m "chore: release v$VERSION"
- name: Update changelog with Claude
continue-on-error: true
uses: anthropics/claude-code-action@v1
with:
prompt: "/generate-changelog new version: ${{ env.VERSION }}, old version: ${{ needs.check-trigger.outputs.previous_tag }}"
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
github_token: ${{ secrets.GITHUB_TOKEN }}
claude_args: |
--model claude-opus-4-5
--allowedTools 'Bash(git add:*),Bash(git commit:*),Edit'
- name: Push to main
run: git push origin main
- name: Create tag and GitHub Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git tag -a "v$VERSION" -m "Release v$VERSION"
git push origin "v$VERSION"
# Extract changelog section
awk -v ver="$VERSION" '/^## / { if (found) exit; if ($2 == ver) found=1; next } found { print }' CHANGELOG.md > release_notes.md
echo -e "\n---\n\n**PyPI:** https://pypi.org/project/claude-agent-sdk/$VERSION/\n\n\`\`\`bash\npip install claude-agent-sdk==$VERSION\n\`\`\`" >> release_notes.md
gh release create "v$VERSION" --title "v$VERSION" --notes-file release_notes.md
```
### Keep Existing: `publish.yml`
Keep as-is for manual releases (SDK-only changes, major/minor bumps, emergencies).
### Optional Cleanup: `create-release-tag.yml`
Can be removed since auto-release handles tagging. Or keep as fallback for manual publish flow.
## Setup Required
### Deploy Key (Required)
1. Generate SSH key:
```bash
ssh-keygen -t ed25519 -C "github-actions-deploy-key" -f deploy_key -N ""
```
2. Add public key as deploy key:
- Repo Settings → Deploy keys → Add deploy key
- Title: "GitHub Actions Auto Release"
- Paste `deploy_key.pub` contents
- Check "Allow write access"
3. Add private key as secret:
- Repo Settings → Secrets → New repository secret
- Name: `DEPLOY_KEY`
- Value: `deploy_key` contents
4. Delete local key files
### Existing Secrets (Already Present)
- `PYPI_API_TOKEN` - PyPI publishing
- `ANTHROPIC_API_KEY` - Changelog generation
## Flow Diagram
```
Push: "chore: bump bundled CLI version to 2.1.12"
↓
lint.yml + test.yml (parallel)
↓ (workflow_run)
auto-release.yml
↓
┌─ check conditions (CI passed, commit pattern matches)
├─ calculate version: 0.1.20 → 0.1.21
├─ build 4 platform wheels
├─ publish to PyPI
├─ update _version.py, pyproject.toml
├─ generate changelog
├─ push to main
├─ create tag v0.1.21
└─ create GitHub Release
```
## Verification
After implementation:
1. Create a test branch with the workflow
2. Add `workflow_dispatch` trigger temporarily for testing
3. Run manually and verify each step
4. Remove `workflow_dispatch`, merge to main
5. Test with an actual CLI version bump commit
</claude-plan>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
Goal: Fully Automated SDK Releases on CLI Bumps
When the bundled CLI version is bumped (e.g.,
chore: bump bundled CLI version to 2.1.12), we want the SDK to automatically publish a new patch version to PyPI without any manual intervention. This PR implements that automation.How it works
Changes
auto-release.yml(new): Triggers on CLI bump commits after Test workflow passes. Uses deploy key to push directly to main.build-and-publish.yml(new): Reusable workflow for building wheels and publishing. Supports both direct-push (auto) and PR (manual) flows.publish.yml(updated): Now calls the reusable workflow. Still available for manual releases (SDK-only changes, major/minor bumps).productionenvironment for secrets (DEPLOY_KEY,PYPI_API_TOKEN).Setup Required
productionenvironment in repo settingsDEPLOY_KEYsecret (SSH deploy key with write access)PYPI_API_TOKENto production environmentTest plan
Changelog
N/A - Internal CI/CD workflow changes only
🤖 Generated with Claude Code