Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/auto-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,8 @@ jobs:
needs: check-trigger
permissions:
contents: write
pull-requests: write
uses: ./.github/workflows/build-and-publish.yml
with:
version: ${{ needs.check-trigger.outputs.version }}
previous_tag: ${{ needs.check-trigger.outputs.previous_tag }}
push_directly: true
secrets: inherit
57 changes: 0 additions & 57 deletions .github/workflows/build-and-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,6 @@ on:
required: false
type: string
default: ''
push_directly:
description: 'Push directly to main (true) or create PR (false)'
required: false
type: boolean
default: false

jobs:
build-wheels:
Expand Down Expand Up @@ -51,35 +46,21 @@ jobs:
environment: production
permissions:
contents: write
pull-requests: write
env:
VERSION: ${{ inputs.version }}
steps:
- uses: actions/checkout@v4
if: inputs.push_directly
with:
fetch-depth: 0
ssh-key: ${{ secrets.DEPLOY_KEY }}

- uses: actions/checkout@v4
if: ${{ !inputs.push_directly }}
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}

- uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Update version files
run: python scripts/update_version.py "$VERSION"

- name: Read CLI version from code
id: cli_version
run: |
CLI_VERSION=$(python -c "import re; print(re.search(r'__cli_version__ = \"([^\"]+)\"', open('src/claude_agent_sdk/_cli_version.py').read()).group(1))")
echo "cli_version=$CLI_VERSION" >> $GITHUB_OUTPUT

- uses: actions/download-artifact@v4
with:
path: dist
Expand Down Expand Up @@ -116,15 +97,12 @@ jobs:
--model claude-opus-4-5
--allowedTools 'Bash(git add:*),Bash(git commit:*),Edit'

# Direct push flow (auto-release)
- name: Push to main
if: inputs.push_directly
run: |
git remote set-url origin git@github.com:anthropics/claude-agent-sdk-python.git
git push origin main

- name: Create tag and GitHub Release
if: inputs.push_directly
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
Expand All @@ -135,38 +113,3 @@ jobs:
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

# PR flow (manual publish)
- name: Create release branch
if: ${{ !inputs.push_directly }}
run: |
BRANCH_NAME="release/v$VERSION"
echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV
git checkout -b "$BRANCH_NAME"

- name: Push branch and create PR
if: ${{ !inputs.push_directly }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git push origin "$BRANCH_NAME"

PR_BODY="This PR updates the version to $VERSION after publishing to PyPI.

## Changes
- Updated version in \`pyproject.toml\` to $VERSION
- Updated version in \`src/claude_agent_sdk/_version.py\` to $VERSION
- Updated \`CHANGELOG.md\` with release notes

## Release Information
- Published to PyPI: https://pypi.org/project/claude-agent-sdk/$VERSION/
- Bundled CLI version: ${{ steps.cli_version.outputs.cli_version }}
- Install with: \`pip install claude-agent-sdk==$VERSION\`

🤖 Generated by GitHub Actions"

gh pr create \
--title "chore: release v$VERSION" \
--body "$PR_BODY" \
--base main \
--head "$BRANCH_NAME"
73 changes: 0 additions & 73 deletions .github/workflows/create-release-tag.yml

This file was deleted.

3 changes: 2 additions & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,10 @@ jobs:

release:
needs: [test, lint, get-previous-tag]
permissions:
contents: write
uses: ./.github/workflows/build-and-publish.yml
with:
version: ${{ github.event.inputs.version }}
previous_tag: ${{ needs.get-previous-tag.outputs.previous_tag }}
push_directly: false
secrets: inherit
63 changes: 63 additions & 0 deletions RELEASING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Releasing

There are two ways to release the SDK: **automatic** (triggered by a CLI version bump) and **manual** (triggered via GitHub Actions UI).

Both flows call the same reusable `build-and-publish.yml` workflow, which builds platform-specific wheels on 4 OS targets (Ubuntu x86, Ubuntu ARM, macOS, Windows), publishes to PyPI, updates version files, generates a changelog entry using Claude, pushes to `main`, and creates a git tag + GitHub Release.

## Versioning

The project tracks two separate version numbers:

- **SDK version** — in `pyproject.toml` and `src/claude_agent_sdk/_version.py`
- **Bundled CLI version** — in `src/claude_agent_sdk/_cli_version.py`

Both follow semver (`MAJOR.MINOR.PATCH`). Git tags use the format `vX.Y.Z`.

## Automatic Release (CLI Version Bump)

This is the most common release path. Every CLI version bump automatically produces a new SDK patch release.

**Flow:**

1. A commit with message `chore: bump bundled CLI version to X.Y.Z` is pushed to `main`, updating `_cli_version.py`.
2. The `Test` workflow runs on that push.
3. On successful completion, `auto-release.yml` fires via `workflow_run`.
4. It verifies the trigger commit message and that `_cli_version.py` changed.
5. It reads the current SDK version from `_version.py` and increments the patch number (e.g., `0.1.24` → `0.1.25`).
6. It calls `build-and-publish.yml`, which builds, publishes, pushes, tags, and creates a GitHub Release.

**Typical commit log after an auto-release:**
```
ccdf20a chore: bump bundled CLI version to 2.1.25
baf9bc3 chore: release v0.1.25
```

## Manual Release

Use this when you need to release with a specific version number (e.g., for minor/major bumps or non-CLI-bump changes).

**Flow:**

1. Go to [**Actions → Publish to PyPI**](https://github.com/anthropics/claude-agent-sdk-python/actions/workflows/publish.yml) and click **Run workflow**.
2. Enter the desired version (e.g., `0.2.0`).
3. The workflow runs the full test suite (Python 3.10–3.13) and lint checks.
4. On success, it calls `build-and-publish.yml`, which builds, publishes, pushes, tags, and creates a GitHub Release.

## Scripts

All release-related scripts live in `scripts/`:

| Script | Purpose |
|---|---|
| `update_version.py` | Updates SDK version in `pyproject.toml` and `_version.py` |
| `update_cli_version.py` | Updates CLI version in `_cli_version.py` |
| `build_wheel.py` | Downloads the CLI binary, builds the wheel, retags with platform-specific tags |
| `download_cli.py` | Downloads the Claude Code CLI binary for the current platform |

## Required Secrets

| Secret | Used For |
|---|---|
| `PYPI_API_TOKEN` | Publishing to PyPI |
| `ANTHROPIC_API_KEY` | Changelog generation and e2e tests |
| `DEPLOY_KEY` | SSH key for direct pushes to `main` |