Add PyPI publishing workflow via Trusted Publisher (OIDC)

Publishes on v* tags (version validated against pyproject.toml), with an
offline pytest gate, build/test-install smoke checks, then a publish job to
the pypi environment using id-token OIDC and gh-action-pypi-publish. Adds
project URLs metadata and a README releasing guide.

Co-Authored-By: Claude <[email protected]>
This commit is contained in:
John Smith
2026-09-02 23:43:47 -04:00
co-authored by Claude
parent 2d6b57be77
commit 75265952a8
3 changed files with 150 additions and 0 deletions
+122
View File
@@ -0,0 +1,122 @@
# Publishes the chaturbate-mcp package to PyPI via a Trusted Publisher (OIDC).
# Mirrors Heretek-AI/heretek-swarm .github/workflows/publish-python.yml, with an
# added offline pytest gate before publishing.
#
# Trigger: push a tag like `v0.1.0` (must match the `version` in pyproject.toml),
# or run manually from the Actions tab (still subject to the version check).
#
# The PyPI trusted publisher for this project must be registered with:
# Project: chaturbate-mcp · Owner: Heretek-AI · Repository: chaturbate-mcp
# Workflow name: publish-python.yml · Environment: pypi
name: Publish Python Package
on:
push:
tags: ['v*']
workflow_dispatch:
env:
PYTHON_VERSION: '3.11'
jobs:
# Offline test gate — a failing suite blocks publishing.
tests:
name: Run tests
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Set up uv
uses: astral-sh/setup-uv@v10
- name: Install dependencies
run: uv sync --dev
- name: Run tests
run: uv run pytest -q
build:
name: Build Package
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Extract version from tag
run: |
TAG_VERSION="${GITHUB_REF#refs/tags/v}"
echo "TAG_VERSION=$TAG_VERSION" >> "$GITHUB_ENV"
echo "tag_version=$TAG_VERSION"
- name: Validate version matches pyproject.toml
run: |
FILE_VERSION=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])")
echo "FILE_VERSION=$FILE_VERSION"
if [ "$TAG_VERSION" != "$FILE_VERSION" ]; then
echo "ERROR: Tag version '$TAG_VERSION' does not match pyproject.toml version '$FILE_VERSION'"
echo "Update pyproject.toml to version '$TAG_VERSION' and push a new tag."
exit 1
fi
echo "Version validated: $TAG_VERSION"
- name: Set up uv
uses: astral-sh/setup-uv@v10
- name: Build package
run: uv build --out-dir dist
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
test-install:
name: Test Installation
runs-on: ubuntu-latest
needs: build
steps:
- name: Download artifacts
uses: actions/download-artifact@v8
with:
name: dist
path: dist/
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install and smoke-test wheel
run: |
pip install --force-reinstall dist/*.whl
python -c "import chaturbate_mcp; from chaturbate_mcp.server import build_server; build_server(); print('wheel OK', chaturbate_mcp.__version__)"
- name: Install and smoke-test sdist
run: |
pip install --force-reinstall dist/*.tar.gz
python -c "import chaturbate_mcp; print('sdist OK', chaturbate_mcp.__version__)"
publish:
name: Publish to PyPI
runs-on: ubuntu-latest
needs: [build, test-install, tests]
environment:
name: pypi
url: https://pypi.org/project/chaturbate-mcp
permissions:
id-token: write
steps:
- name: Download artifacts
uses: actions/download-artifact@v8
with:
name: dist
path: dist/
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
+24
View File
@@ -95,6 +95,30 @@ never prints or persists them:
uv run python scripts/smoke_test.py
```
## Releasing (PyPI)
This package publishes to PyPI from GitHub Actions via a **Trusted Publisher (OIDC)** — no API
tokens or passwords are used.
To cut a release:
1. Bump `version` in `pyproject.toml`, commit, and push.
2. Tag and push the tag (must match the new version):
`git tag v0.1.0 && git push origin v0.1.0`
3. `.github/workflows/publish-python.yml` runs the offline tests, builds the wheel + sdist, smoke-tests
the install, then publishes to `https://pypi.org/project/chaturbate-mcp`.
The PyPI trusted publisher is registered once at https://pypi.org/manage/account/publishing/ with
exactly these values (the workflow name and environment must match the file/job in this repo):
| Field | Value |
|---|---|
| PyPI Project Name | `chaturbate-mcp` |
| Owner | `Heretek-AI` |
| Repository | `chaturbate-mcp` |
| Workflow name | `publish-python.yml` |
| Environment | `pypi` |
## Security notes
- `review/` (a saved copy of your authtoken page — contains live tokens) and
+4
View File
@@ -11,6 +11,10 @@ dependencies = [
"python-dotenv>=1.0.1",
]
[project.urls]
Homepage = "https://github.com/Heretek-AI/chaturbate-mcp"
Repository = "https://github.com/Heretek-AI/chaturbate-mcp"
[project.scripts]
chaturbate-mcp = "chaturbate_mcp.server:main"