Merge pull request #1 from Molecule-AI/chore/pypi-publish-workflow
chore(ci): tag-triggered PyPI publish via OIDC trusted-publisher
This commit is contained in:
commit
3e428dde2b
69
.github/workflows/publish.yml
vendored
Normal file
69
.github/workflows/publish.yml
vendored
Normal 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
|
||||
25
README.md
25
README.md
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user