Skip to content
73 changes: 73 additions & 0 deletions .github/workflows/pypi-publish-on-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: Publish to PyPI

on:
release:
types:
- published

permissions: {}

jobs:
call-test:
permissions:
contents: read
pull-requests: read
security-events: write
actions: read
uses: ./.github/workflows/python.yml
with:
ref: ${{ github.event.release.target_commitish }}

call-integ-tests:
permissions:
id-token: write
contents: read
actions: read
uses: ./.github/workflows/python-integ.yml
with:
ref: ${{ github.event.release.target_commitish }}
secrets: inherit

build:
needs: [call-test, call-integ-tests]
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
persist-credentials: false

- name: Set up uv
uses: astral-sh/setup-uv@v4

- name: Build distribution packages
run: uv build

- name: Upload distribution packages
uses: actions/upload-artifact@v4
with:
name: python-package-distributions
path: dist/

deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/mcp-proxy-for-aws
permissions:
id-token: write
steps:
- name: Download distribution packages
uses: actions/download-artifact@v5
with:
name: python-package-distributions
path: dist/

- name: Set up uv
uses: astral-sh/setup-uv@v4

- name: Publish to PyPI
run: uv publish
9 changes: 8 additions & 1 deletion .github/workflows/python-integ.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@ name: Python Integration Tests


on:
workflow_call:
workflow_dispatch:
push:
branches: main
workflow_call:
inputs:
ref:
description: 'Git ref to checkout'
required: false
type: string

jobs:
integration:
Expand All @@ -24,6 +29,8 @@ jobs:

steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
ref: ${{ inputs.ref || github.ref }}

- name: Install uv
uses: astral-sh/setup-uv@85856786d1ce8acfbcc2f13a5f3fbd6b938f9f41 # v7.1.2
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ on:
push:
pull_request:
workflow_dispatch:
workflow_call:
inputs:
ref:
description: 'Git ref to checkout'
required: false
type: string

permissions: {}

Expand All @@ -25,6 +31,8 @@ jobs:
actions: read
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
ref: ${{ inputs.ref || github.ref }}

- name: Install uv
uses: astral-sh/setup-uv@85856786d1ce8acfbcc2f13a5f3fbd6b938f9f41 # v7.1.2
Expand Down
71 changes: 71 additions & 0 deletions .github/workflows/test-pypi-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: Test PyPI Publishing

on:
workflow_dispatch:

permissions: {}

jobs:
call-test:
permissions:
contents: read
pull-requests: read
security-events: write
actions: read
with:
ref: ${{ github.event.release.target_commitish }}
uses: ./.github/workflows/python.yml

call-integ-tests:
permissions:
id-token: write
contents: read
actions: read
uses: ./.github/workflows/python-integ.yml
with:
ref: ${{ github.event.release.target_commitish }}
secrets: inherit

build:
needs: [call-test, call-integ-tests]
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
persist-credentials: false

- name: Set up uv
uses: astral-sh/setup-uv@v4

- name: Build distribution packages
run: uv build

- name: Upload distribution packages
uses: actions/upload-artifact@v4
with:
name: python-package-distributions
path: dist/

deploy-test:
needs: build
runs-on: ubuntu-latest
environment:
name: testpypi
url: https://test.pypi.org/p/mcp-proxy-for-aws
permissions:
id-token: write
steps:
- name: Download distribution packages
uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/

- name: Set up uv
uses: astral-sh/setup-uv@v4

- name: Publish to TestPyPI
run: uv publish --publish-url https://test.pypi.org/legacy/
84 changes: 84 additions & 0 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -379,12 +379,96 @@ export LOG_LEVEL=DEBUG
uv run mcp_proxy_for_aws/server.py <endpoint>
```

## Releasing to PyPI

The project uses automated PyPI publishing through GitHub Actions. Releases are triggered by creating a GitHub Release.

### Release Process

1. **Ensure all changes are merged to main branch**
```bash
git checkout main
git pull origin main
```

2. **Create GitHub Release**

Go to the [Releases page](https://github.com/aws/mcp-proxy-for-aws/releases) and click "Draft a new release", then fill in:

- **Tag**: `v1.10.0` (must start with 'v' and follow semantic versioning)
- **Target**: `main`
- **Title**: `v1.10.0`
- **Description**: Click "Generate release notes" for auto-generated notes

Click **"Publish release"** (not "Save draft")

3. **Automated Publishing**

Once the release is published, GitHub Actions will automatically:
- Run all tests and linting checks
- Build distribution packages (wheel and source)
- Publish to PyPI using Trusted Publishing

Monitor the workflow at: [Actions tab](https://github.com/aws/mcp-proxy-for-aws/actions)

### Version Numbering

Follow [Semantic Versioning](https://semver.org/):
- **MAJOR** (v2.0.0): Breaking changes
- **MINOR** (v1.10.0): New features, backward compatible
- **PATCH** (v1.10.1): Bug fixes, backward compatible

Version is managed in `pyproject.toml`: `version = "1.10.0"`

Use Commitizen to bump versions automatically:
```bash
# Bump version based on conventional commits
uv run cz bump

# This will update both files and create a git tag
```

### Testing Releases

Before creating a production release, you can test with TestPyPI:

```bash
# Create a test tag
git tag v1.10.0-beta
git push origin v1.10.0-beta

# This triggers the TestPyPI workflow
# Monitor at: https://github.com/aws/mcp-proxy-for-aws/actions
```

### Troubleshooting Releases

**Release workflow failed:**
- Check the Actions tab for error details
- Ensure all tests pass locally: `uv run pytest`
- Verify the tag follows semantic versioning format

**Version already exists on PyPI:**
- PyPI doesn't allow re-uploading the same version
- Create a new patch version (e.g., v1.10.1)
- Delete and recreate the tag if needed:
```bash
git tag -d v1.10.0
git push origin --delete v1.10.0
```

**Trusted Publishing authentication failed:**
- Verify PyPI Trusted Publisher is configured correctly
- Check that the workflow file name matches the PyPI configuration
- Ensure the environment name is set to `pypi`

## Additional Resources

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

---

Expand Down