Merge pull request #1 from Molecule-AI/chore/pypi-publish-workflow
Some checks failed
Publish to PyPI / build (push) Failing after 13m39s
Publish to PyPI / publish (push) Has been cancelled

chore(ci): tag-triggered PyPI publish via OIDC trusted-publisher
This commit is contained in:
Hongming Wang 2026-05-04 18:38:38 -07:00 committed by GitHub
commit 3e428dde2b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 94 additions and 0 deletions

69
.github/workflows/publish.yml vendored Normal file
View File

@ -0,0 +1,69 @@
name: Publish to PyPI
# Triggered on tag push (vX.Y.Z). Tag-on-push instead of release-creation
# is the cheaper UX — `git tag v0.1.0 && git push origin v0.1.0` ships
# without leaving the terminal.
on:
push:
tags:
- "v[0-9]+.[0-9]+.[0-9]+"
- "v[0-9]+.[0-9]+.[0-9]+rc[0-9]+"
permissions:
contents: read
# OIDC token for PyPI trusted-publisher auth — no secret token needed.
# PyPI side: register
# github.com/Molecule-AI/codex-channel-molecule
# workflow=publish.yml environment=pypi
# under "Trusted publisher management" on the codex-channel-molecule
# PyPI project page (see README "Releasing" section).
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Verify tag matches pyproject version
run: |
tag="${GITHUB_REF#refs/tags/v}"
pkg=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
if [ "$tag" != "$pkg" ]; then
echo "::error::tag $tag does not match pyproject version $pkg — aborting publish to keep PyPI in sync with git tags"
exit 1
fi
- name: Build sdist + wheel
run: |
python -m pip install --upgrade pip build
python -m build
- name: Smoke-import the built wheel
run: |
python -m venv /tmp/install-test
/tmp/install-test/bin/pip install dist/*.whl
/tmp/install-test/bin/codex-channel-molecule --help
- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
publish:
needs: build
runs-on: ubuntu-latest
environment: pypi
permissions:
id-token: write
steps:
- uses: actions/download-artifact@v4
with:
name: dist
path: dist/
- uses: pypa/gh-action-pypi-publish@release/v1

View File

@ -70,6 +70,31 @@ pytest -q
Tests are entirely real-subprocess (no mocking the spawn boundary) so the boot path is covered the same way the daemon runs in production.
## Releasing
Tag-on-push triggers `publish.yml` which builds + publishes to PyPI via OIDC trusted publishing (no API token needed).
```sh
# Bump pyproject.toml `version`, commit, then:
git tag v0.1.1 && git push origin v0.1.1
```
The workflow refuses to publish if the tag doesn't match `pyproject.toml`'s `version` — keeps PyPI versions and git tags in lockstep.
**One-time PyPI setup** (before the first release):
1. Create the project on PyPI by uploading the first wheel manually, OR
2. Pre-register the project on PyPI under a "Pending publisher" config so the first tagged push creates it.
Either way, on the project's PyPI page → "Manage" → "Publishing" → "Add a new publisher", configure:
- Owner: `Molecule-AI`
- Repository: `codex-channel-molecule`
- Workflow filename: `publish.yml`
- Environment name: `pypi`
After this, every `git push origin v*.*.*` ships the wheel to PyPI without any further intervention.
## License
Apache-2.0