Skip to content

Commit 1ff8763

Browse files
harv-awsHarvish N SkyoncalKyon Calderaarangatang
authored
feat: Add Automated PyPI Publishing Workflow (aws#83)
* pypi release automation through github actions * Forward region via meta (aws#71) * feat(sigv4_helper): inject AWS_REGION in _meta * Override the sigv4 signature when adding _meta. * feat(sigv4_helper): add region and service argument to _inject_metadata_hook to allow for proper resigning of sigv4 to work * feat(server.py): add forwarding region as optional argument * feat: replace forwarding region with metadata forwarding * refactor: move the hooks from sigv4_helper.py into a new folder and add tests * refactor(siv4_helper.py): move signing logic from client creation to an event hook * test(test_hooks.py): add assertions * refactor(sigv4_helper.py): remove hooks.py module and move hooks to sigv4_helper.py This refactor was needed in order to avoid a circular depdency, which resulted in a mid-module import. --------- Co-authored-by: Kyon Caldera <[email protected]> Co-authored-by: Leonardo Araneda Freccero <[email protected]> * docs: mention creating issues first before sending large PR with new feature (aws#76) * feat: allow iam mcp client to take a botocore credentials object (aws#84) * pypi release automation through github actions * chore: pypi publishing added to development.md * chore: simplifying uv install * fix: adding input commit id for integ tests, and passing it in publish workflows. --------- Co-authored-by: Harvish N S <[email protected]> Co-authored-by: Kyon <[email protected]> Co-authored-by: Kyon Caldera <[email protected]> Co-authored-by: Leonardo Araneda Freccero <[email protected]> Co-authored-by: wzxxing <[email protected]> Co-authored-by: Leonardo Araneda Freccero <[email protected]>
1 parent 3f58d5d commit 1ff8763

File tree

5 files changed

+244
-1
lines changed

5 files changed

+244
-1
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
name: Publish to PyPI
2+
3+
on:
4+
release:
5+
types:
6+
- published
7+
8+
permissions: {}
9+
10+
jobs:
11+
call-test:
12+
permissions:
13+
contents: read
14+
pull-requests: read
15+
security-events: write
16+
actions: read
17+
uses: ./.github/workflows/python.yml
18+
with:
19+
ref: ${{ github.event.release.target_commitish }}
20+
21+
call-integ-tests:
22+
permissions:
23+
id-token: write
24+
contents: read
25+
actions: read
26+
uses: ./.github/workflows/python-integ.yml
27+
with:
28+
ref: ${{ github.event.release.target_commitish }}
29+
secrets: inherit
30+
31+
build:
32+
needs: [call-test, call-integ-tests]
33+
runs-on: ubuntu-latest
34+
permissions:
35+
contents: read
36+
steps:
37+
- name: Checkout code
38+
uses: actions/checkout@v4
39+
with:
40+
persist-credentials: false
41+
42+
- name: Set up uv
43+
uses: astral-sh/setup-uv@v4
44+
45+
- name: Build distribution packages
46+
run: uv build
47+
48+
- name: Upload distribution packages
49+
uses: actions/upload-artifact@v4
50+
with:
51+
name: python-package-distributions
52+
path: dist/
53+
54+
deploy:
55+
needs: build
56+
runs-on: ubuntu-latest
57+
environment:
58+
name: pypi
59+
url: https://pypi.org/p/mcp-proxy-for-aws
60+
permissions:
61+
id-token: write
62+
steps:
63+
- name: Download distribution packages
64+
uses: actions/download-artifact@v5
65+
with:
66+
name: python-package-distributions
67+
path: dist/
68+
69+
- name: Set up uv
70+
uses: astral-sh/setup-uv@v4
71+
72+
- name: Publish to PyPI
73+
run: uv publish

.github/workflows/python-integ.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@ name: Python Integration Tests
22

33

44
on:
5-
workflow_call:
65
workflow_dispatch:
76
push:
87
branches: main
8+
workflow_call:
9+
inputs:
10+
ref:
11+
description: 'Git ref to checkout'
12+
required: false
13+
type: string
914

1015
jobs:
1116
integration:
@@ -24,6 +29,8 @@ jobs:
2429

2530
steps:
2631
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
32+
with:
33+
ref: ${{ inputs.ref || github.ref }}
2734

2835
- name: Install uv
2936
uses: astral-sh/setup-uv@85856786d1ce8acfbcc2f13a5f3fbd6b938f9f41 # v7.1.2

.github/workflows/python.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ on:
44
push:
55
pull_request:
66
workflow_dispatch:
7+
workflow_call:
8+
inputs:
9+
ref:
10+
description: 'Git ref to checkout'
11+
required: false
12+
type: string
713

814
permissions: {}
915

@@ -25,6 +31,8 @@ jobs:
2531
actions: read
2632
steps:
2733
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
34+
with:
35+
ref: ${{ inputs.ref || github.ref }}
2836

2937
- name: Install uv
3038
uses: astral-sh/setup-uv@85856786d1ce8acfbcc2f13a5f3fbd6b938f9f41 # v7.1.2
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
name: Test PyPI Publishing
2+
3+
on:
4+
workflow_dispatch:
5+
6+
permissions: {}
7+
8+
jobs:
9+
call-test:
10+
permissions:
11+
contents: read
12+
pull-requests: read
13+
security-events: write
14+
actions: read
15+
with:
16+
ref: ${{ github.event.release.target_commitish }}
17+
uses: ./.github/workflows/python.yml
18+
19+
call-integ-tests:
20+
permissions:
21+
id-token: write
22+
contents: read
23+
actions: read
24+
uses: ./.github/workflows/python-integ.yml
25+
with:
26+
ref: ${{ github.event.release.target_commitish }}
27+
secrets: inherit
28+
29+
build:
30+
needs: [call-test, call-integ-tests]
31+
runs-on: ubuntu-latest
32+
permissions:
33+
contents: read
34+
steps:
35+
- name: Checkout code
36+
uses: actions/checkout@v4
37+
with:
38+
persist-credentials: false
39+
40+
- name: Set up uv
41+
uses: astral-sh/setup-uv@v4
42+
43+
- name: Build distribution packages
44+
run: uv build
45+
46+
- name: Upload distribution packages
47+
uses: actions/upload-artifact@v4
48+
with:
49+
name: python-package-distributions
50+
path: dist/
51+
52+
deploy-test:
53+
needs: build
54+
runs-on: ubuntu-latest
55+
environment:
56+
name: testpypi
57+
url: https://test.pypi.org/p/mcp-proxy-for-aws
58+
permissions:
59+
id-token: write
60+
steps:
61+
- name: Download distribution packages
62+
uses: actions/download-artifact@v4
63+
with:
64+
name: python-package-distributions
65+
path: dist/
66+
67+
- name: Set up uv
68+
uses: astral-sh/setup-uv@v4
69+
70+
- name: Publish to TestPyPI
71+
run: uv publish --publish-url https://test.pypi.org/legacy/

DEVELOPMENT.md

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,12 +379,96 @@ export LOG_LEVEL=DEBUG
379379
uv run mcp_proxy_for_aws/server.py <endpoint>
380380
```
381381

382+
## Releasing to PyPI
383+
384+
The project uses automated PyPI publishing through GitHub Actions. Releases are triggered by creating a GitHub Release.
385+
386+
### Release Process
387+
388+
1. **Ensure all changes are merged to main branch**
389+
```bash
390+
git checkout main
391+
git pull origin main
392+
```
393+
394+
2. **Create GitHub Release**
395+
396+
Go to the [Releases page](https://github.com/aws/mcp-proxy-for-aws/releases) and click "Draft a new release", then fill in:
397+
398+
- **Tag**: `v1.10.0` (must start with 'v' and follow semantic versioning)
399+
- **Target**: `main`
400+
- **Title**: `v1.10.0`
401+
- **Description**: Click "Generate release notes" for auto-generated notes
402+
403+
Click **"Publish release"** (not "Save draft")
404+
405+
3. **Automated Publishing**
406+
407+
Once the release is published, GitHub Actions will automatically:
408+
- Run all tests and linting checks
409+
- Build distribution packages (wheel and source)
410+
- Publish to PyPI using Trusted Publishing
411+
412+
Monitor the workflow at: [Actions tab](https://github.com/aws/mcp-proxy-for-aws/actions)
413+
414+
### Version Numbering
415+
416+
Follow [Semantic Versioning](https://semver.org/):
417+
- **MAJOR** (v2.0.0): Breaking changes
418+
- **MINOR** (v1.10.0): New features, backward compatible
419+
- **PATCH** (v1.10.1): Bug fixes, backward compatible
420+
421+
Version is managed in `pyproject.toml`: `version = "1.10.0"`
422+
423+
Use Commitizen to bump versions automatically:
424+
```bash
425+
# Bump version based on conventional commits
426+
uv run cz bump
427+
428+
# This will update both files and create a git tag
429+
```
430+
431+
### Testing Releases
432+
433+
Before creating a production release, you can test with TestPyPI:
434+
435+
```bash
436+
# Create a test tag
437+
git tag v1.10.0-beta
438+
git push origin v1.10.0-beta
439+
440+
# This triggers the TestPyPI workflow
441+
# Monitor at: https://github.com/aws/mcp-proxy-for-aws/actions
442+
```
443+
444+
### Troubleshooting Releases
445+
446+
**Release workflow failed:**
447+
- Check the Actions tab for error details
448+
- Ensure all tests pass locally: `uv run pytest`
449+
- Verify the tag follows semantic versioning format
450+
451+
**Version already exists on PyPI:**
452+
- PyPI doesn't allow re-uploading the same version
453+
- Create a new patch version (e.g., v1.10.1)
454+
- Delete and recreate the tag if needed:
455+
```bash
456+
git tag -d v1.10.0
457+
git push origin --delete v1.10.0
458+
```
459+
460+
**Trusted Publishing authentication failed:**
461+
- Verify PyPI Trusted Publisher is configured correctly
462+
- Check that the workflow file name matches the PyPI configuration
463+
- Ensure the environment name is set to `pypi`
464+
382465
## Additional Resources
383466

384467
- [MCP Specification](https://spec.modelcontextprotocol.io/)
385468
- [FastMCP Documentation](https://fastmcp.readthedocs.io/)
386469
- [AWS SDK for Python (Boto3)](https://boto3.amazonaws.com/v1/documentation/api/latest/index.html)
387470
- [Project README](README.md)
471+
- [PyPI Publishing Guide](https://packaging.python.org/en/latest/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/)
388472

389473
---
390474

0 commit comments

Comments
 (0)