Skip to content

Commit 273258c

Browse files
committed
feat: split release workflow into prepare and publish
1 parent 328acba commit 273258c

3 files changed

Lines changed: 379 additions & 1 deletion

File tree

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
name: Release
1+
name: Legacy Release (deprecated)
22

3+
# DEPRECATED: Replaced by release-prepare.yml and release-publish.yml
4+
# Kept as a fallback. Remove once new workflows are verified.
35
on:
46
workflow_dispatch:
57
inputs:
Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
name: Release Prepare
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
bump_type:
7+
description: 'Version bump type'
8+
required: true
9+
type: choice
10+
options:
11+
- patch
12+
- minor
13+
- major
14+
- pre
15+
changelog:
16+
description: 'Custom changelog entry (optional - leave empty to auto-generate)'
17+
required: false
18+
type: string
19+
20+
permissions:
21+
contents: write
22+
pull-requests: write
23+
24+
jobs:
25+
prepare-release:
26+
name: Prepare Release
27+
runs-on: ubuntu-latest
28+
outputs:
29+
version: ${{ steps.bump.outputs.version }}
30+
31+
steps:
32+
- name: Validate running from main
33+
run: |
34+
if [[ "${{ github.ref }}" != "refs/heads/main" ]]; then
35+
echo "⚠️ WARNING: Running from ${{ github.ref }}"
36+
echo "⚠️ Production releases should only run from main branch"
37+
fi
38+
39+
- name: Checkout code
40+
uses: actions/checkout@v5
41+
with:
42+
fetch-depth: 0
43+
44+
- name: Setup Python
45+
uses: actions/setup-python@v6
46+
with:
47+
python-version: '3.10'
48+
49+
- name: Configure git
50+
run: |
51+
git config --global user.name "github-actions[bot]"
52+
git config --global user.email "github-actions[bot]@users.noreply.github.com"
53+
54+
- name: Install uv
55+
run: |
56+
curl -LsSf https://astral.sh/uv/install.sh | sh
57+
echo "$HOME/.local/bin" >> $GITHUB_PATH
58+
59+
- name: Get current version
60+
id: current
61+
run: |
62+
VERSION=$(grep -m1 -oP '^version = "\K[^"]+' pyproject.toml)
63+
echo "version=$VERSION" >> $GITHUB_OUTPUT
64+
echo "Current version: $VERSION"
65+
66+
- name: Bump version
67+
id: bump
68+
env:
69+
CHANGELOG_INPUT: ${{ github.event.inputs.changelog }}
70+
BUMP_TYPE: ${{ github.event.inputs.bump_type }}
71+
run: |
72+
chmod +x scripts/bump_version.py
73+
74+
if [ -z "$CHANGELOG_INPUT" ]; then
75+
echo "ℹ️ No custom changelog provided. Will auto-generate from commits."
76+
fi
77+
78+
if [ -n "$CHANGELOG_INPUT" ]; then
79+
python scripts/bump_version.py "$BUMP_TYPE" --changelog "$CHANGELOG_INPUT"
80+
else
81+
python scripts/bump_version.py "$BUMP_TYPE"
82+
fi
83+
84+
uv lock --no-progress
85+
86+
NEW_VERSION=$(grep -m1 -oP '^version = "\K[^"]+' pyproject.toml)
87+
echo "version=$NEW_VERSION" >> $GITHUB_OUTPUT
88+
echo "New version: $NEW_VERSION"
89+
90+
- name: Create release branch and push
91+
env:
92+
NEW_VERSION: ${{ steps.bump.outputs.version }}
93+
run: |
94+
BRANCH_NAME="release/v$NEW_VERSION"
95+
96+
if git ls-remote --exit-code --heads origin $BRANCH_NAME; then
97+
echo "⚠️ Branch $BRANCH_NAME already exists. Deleting it first..."
98+
git push origin --delete $BRANCH_NAME
99+
fi
100+
101+
if git show-ref --verify --quiet refs/heads/$BRANCH_NAME; then
102+
git branch -D $BRANCH_NAME
103+
fi
104+
105+
git checkout -b $BRANCH_NAME
106+
git add -A
107+
git commit -m "chore: bump version to $NEW_VERSION
108+
109+
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>"
110+
111+
git push origin $BRANCH_NAME
112+
113+
COMMITTED_VERSION=$(git show HEAD:pyproject.toml | grep -m1 -oP '^version = "\K[^"]+')
114+
if [ "$COMMITTED_VERSION" != "$NEW_VERSION" ]; then
115+
echo "❌ ERROR: Version not committed correctly!"
116+
exit 1
117+
fi
118+
119+
- name: Create Pull Request
120+
env:
121+
GH_TOKEN: ${{ github.token }}
122+
NEW_VERSION: ${{ steps.bump.outputs.version }}
123+
GITHUB_REF: ${{ github.ref }}
124+
GITHUB_ACTOR: ${{ github.actor }}
125+
run: |
126+
BRANCH_NAME="release/v$NEW_VERSION"
127+
128+
WARNING_TEXT=""
129+
if [ "$GITHUB_REF" != "refs/heads/main" ]; then
130+
WARNING_TEXT="**WARNING**: Not running from main branch!"
131+
else
132+
WARNING_TEXT="✅ Running from main branch"
133+
fi
134+
135+
gh pr create \
136+
--base main \
137+
--head "$BRANCH_NAME" \
138+
--title "Release v$NEW_VERSION" \
139+
--body "## 🚀 Release v$NEW_VERSION
140+
141+
This PR was automatically created by the release workflow.
142+
143+
### ⚠️ Pre-merge Checklist
144+
- [ ] Review CHANGELOG.md - ensure it has meaningful release notes
145+
- [ ] Verify version numbers are correct in all files
146+
- [ ] All CI checks are passing
147+
148+
### 📝 How to improve changelog
149+
If the auto-generated changelog isn't good enough:
150+
1. Edit CHANGELOG.md in this PR
151+
2. Commit the changes
152+
3. Then approve and merge
153+
154+
### 🔄 Release Process
155+
After merging this PR, the **release-publish** workflow will:
156+
1. Build the package from main
157+
2. Require **manual approval** before publishing to PyPI
158+
3. Publish to PyPI, create tag and GitHub release
159+
160+
### 🚨 Running from: $GITHUB_REF
161+
$WARNING_TEXT
162+
163+
---
164+
*Triggered by @$GITHUB_ACTOR*"
165+
166+
test-and-build:
167+
name: Test and Build
168+
needs: prepare-release
169+
runs-on: ubuntu-latest
170+
171+
steps:
172+
- uses: actions/checkout@v5
173+
with:
174+
ref: release/v${{ needs.prepare-release.outputs.version }}
175+
176+
- name: Verify version before build
177+
env:
178+
EXPECTED_VERSION: ${{ needs.prepare-release.outputs.version }}
179+
run: |
180+
ACTUAL_VERSION=$(grep -m1 -oP '^version = "\K[^"]+' pyproject.toml)
181+
echo "Expected version: $EXPECTED_VERSION"
182+
echo "Actual version: $ACTUAL_VERSION"
183+
184+
if [ "$ACTUAL_VERSION" != "$EXPECTED_VERSION" ]; then
185+
echo "❌ ERROR: Version mismatch!"
186+
exit 1
187+
fi
188+
echo "✓ Version verified: $ACTUAL_VERSION"
189+
190+
- name: Set up Python
191+
uses: actions/setup-python@v6
192+
with:
193+
python-version: '3.10'
194+
195+
- name: Install uv
196+
run: |
197+
curl -LsSf https://astral.sh/uv/install.sh | sh
198+
echo "$HOME/.local/bin" >> $GITHUB_PATH
199+
200+
- name: Setup build environment
201+
run: |
202+
uv venv
203+
source .venv/bin/activate
204+
uv pip install build twine
205+
206+
- name: Build and check package
207+
run: |
208+
source .venv/bin/activate
209+
uv build
210+
twine check dist/*
211+
echo "=== Package contents ==="
212+
python -m zipfile -l dist/*.whl | head -20
213+
214+
- name: Upload artifacts
215+
uses: actions/upload-artifact@v4
216+
with:
217+
name: dist
218+
path: dist/
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
name: Release Publish
2+
3+
on:
4+
pull_request:
5+
types: [closed]
6+
branches: [main]
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
build:
13+
name: Build from Main
14+
if: >
15+
github.event.pull_request.merged == true &&
16+
startsWith(github.event.pull_request.head.ref, 'release/v')
17+
runs-on: ubuntu-latest
18+
outputs:
19+
version: ${{ steps.version.outputs.version }}
20+
21+
steps:
22+
- uses: actions/checkout@v5
23+
with:
24+
fetch-depth: 0
25+
26+
- name: Extract version from pyproject.toml
27+
id: version
28+
run: |
29+
VERSION=$(grep -m1 -oP '^version = "\K[^"]+' pyproject.toml)
30+
echo "version=$VERSION" >> $GITHUB_OUTPUT
31+
echo "Version: $VERSION"
32+
33+
- name: Set up Python
34+
uses: actions/setup-python@v6
35+
with:
36+
python-version: '3.10'
37+
38+
- name: Install uv
39+
run: |
40+
curl -LsSf https://astral.sh/uv/install.sh | sh
41+
echo "$HOME/.local/bin" >> $GITHUB_PATH
42+
43+
- name: Build and check package
44+
run: |
45+
uv venv
46+
source .venv/bin/activate
47+
uv pip install build twine
48+
uv build
49+
twine check dist/*
50+
51+
- name: Upload artifacts
52+
uses: actions/upload-artifact@v4
53+
with:
54+
name: dist
55+
path: dist/
56+
57+
release-approval:
58+
name: Release Approval
59+
needs: build
60+
runs-on: ubuntu-latest
61+
environment:
62+
name: pypi-approval
63+
64+
steps:
65+
- name: Approval checkpoint
66+
env:
67+
VERSION: ${{ needs.build.outputs.version }}
68+
run: |
69+
echo "✅ Build successful for v$VERSION"
70+
echo "📦 Package ready for PyPI publication"
71+
echo ""
72+
echo "⚠️ MANUAL APPROVAL REQUIRED"
73+
echo "Verify version and changelog before approving."
74+
75+
publish-pypi:
76+
name: Publish to PyPI
77+
needs: [build, release-approval]
78+
runs-on: ubuntu-latest
79+
environment:
80+
name: pypi
81+
url: https://pypi.org/project/bedrock-agentcore/
82+
83+
steps:
84+
- uses: actions/checkout@v5
85+
with:
86+
fetch-depth: 0
87+
88+
- name: Download artifacts
89+
uses: actions/download-artifact@v5
90+
with:
91+
name: dist
92+
path: dist/
93+
94+
- name: Verify PyPI token exists
95+
env:
96+
PYPI_TOKEN_SET: ${{ secrets.PYPI_API_TOKEN != '' }}
97+
run: |
98+
if [ "$PYPI_TOKEN_SET" != "true" ]; then
99+
echo "❌ ERROR: PYPI_API_TOKEN not configured!"
100+
exit 1
101+
fi
102+
echo "✓ PyPI token is configured"
103+
104+
- name: Check if version exists on PyPI
105+
env:
106+
VERSION: ${{ needs.build.outputs.version }}
107+
run: |
108+
if pip index versions bedrock-agentcore | grep -q "^Available versions.*$VERSION"; then
109+
echo "❌ ERROR: Version $VERSION already exists on PyPI!"
110+
exit 1
111+
fi
112+
echo "✓ Version $VERSION is not on PyPI, safe to publish"
113+
114+
- name: Publish to PyPI
115+
uses: pypa/gh-action-pypi-publish@release/v1
116+
with:
117+
password: ${{ secrets.PYPI_API_TOKEN }}
118+
skip-existing: false
119+
verbose: true
120+
121+
- name: Wait for PyPI availability
122+
env:
123+
VERSION: ${{ needs.build.outputs.version }}
124+
run: |
125+
echo "Waiting for package to be available on PyPI..."
126+
for i in {1..10}; do
127+
if pip index versions bedrock-agentcore | grep -q "$VERSION"; then
128+
echo "✓ Package version $VERSION is now available on PyPI"
129+
break
130+
fi
131+
echo "Attempt $i/10: Package not yet available, waiting 30s..."
132+
sleep 30
133+
done
134+
135+
- name: Create and push tag
136+
env:
137+
VERSION: ${{ needs.build.outputs.version }}
138+
run: |
139+
git config --global user.name "github-actions[bot]"
140+
git config --global user.email "github-actions[bot]@users.noreply.github.com"
141+
git tag -a "v$VERSION" -m "Release v$VERSION"
142+
git push origin "v$VERSION"
143+
144+
- name: Create GitHub Release
145+
uses: softprops/action-gh-release@v2
146+
with:
147+
tag_name: v${{ needs.build.outputs.version }}
148+
name: Bedrock AgentCore SDK v${{ needs.build.outputs.version }}
149+
files: dist/*
150+
generate_release_notes: true
151+
body: |
152+
## Installation
153+
```bash
154+
pip install bedrock-agentcore==${{ needs.build.outputs.version }}
155+
```
156+
157+
## What's Changed
158+
See [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/v${{ needs.build.outputs.version }}/CHANGELOG.md) for details.

0 commit comments

Comments
 (0)