Releasing to PyPI
This project uses automated, tag-driven releases via GitHub Actions with a TestPyPI gate and smoke test before PyPI publish.
Workflow file:
.github/workflows/release.yml
Release Checklist (Quick Reference)
Stage |
Check |
Command / Action |
|---|---|---|
Pre-flight |
On |
|
Pre-flight |
Version/changelog updated |
Verify |
Pre-flight |
Tests pass locally |
|
Trigger (tag path) |
Create and push tag |
|
Trigger (manual fallback) |
Run workflow manually |
GitHub Actions → |
Verification |
Confirm tag exists remotely |
`git ls-remote –tags origin |
Verification |
Confirm workflow completed |
Check |
Verification |
Confirm install/version |
|
Release Pipeline (Current Behavior)
Trigger options:
Push a version tag that matches
v*(for examplev0.2.0)Run manually from GitHub Actions (
workflow_dispatch)
Pipeline stages:
Run tests (
pytest -q)Build package artifacts (
sdist+wheel)Validate metadata (
twine check)Publish artifacts to TestPyPI
Smoke install package from TestPyPI
Publish the same artifacts to PyPI
One-Time Setup: Trusted Publishing
No PyPI API token is required. Publishing uses GitHub OIDC.
Configure Trusted Publisher in both:
For each index, set:
Owner:
dowlinglabRepository:
grad-visit-schedulerWorkflow:
release.ymlEnvironment: leave empty (unless you later add a GitHub Environment gate)
Standard Release (Recommended)
Ensure
pyproject.tomlversion is updated (for example0.2.0).Update
CHANGELOG.md.Merge release changes to
main.Create and push tag:
git tag v0.2.0
git push origin v0.2.0
Open GitHub Actions and monitor
Releaseworkflow.
Manual Release Runs (workflow_dispatch)
GitHub Actions → Release → Run workflow
Inputs:
target=testpypiRuns build/test/check + TestPyPI publish + smoke install
Stops before PyPI publish
target=pypiRuns full pipeline including PyPI publish
version(optional)Used to pin smoke install (e.g.
0.2.1orv0.2.1)If omitted, smoke install uses latest package visible on TestPyPI
Verifying a Published Release
PyPI install check:
python -m pip install --upgrade grad-visitor-scheduler
python -c "import grad_visit_scheduler as gvs; print(gvs.__version__)"
TestPyPI install check:
python -m pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple grad-visitor-scheduler
python -c "import grad_visit_scheduler as gvs; print(gvs.__version__)"
Common Failure Modes
Trusted Publisher mismatch (
invalid-publisher/auth errors):Verify owner/repo/workflow filename exactly match configuration.
Smoke install cannot find version on TestPyPI:
Wait a minute and rerun; index propagation can lag.
Confirm version in
pyproject.tomlmatches tag.
File already existson publish:That version is already uploaded; bump version and retag.
Tag exists but no
on: pushrelease workflow appears:Confirm tag exists on remote:
git ls-remote --tags origin | grep vX.Y.ZUse manual workflow dispatch on
mainas deterministic fallback:target=pypi,version=X.Y.Z.
Build/test failures:
Release pipeline is intentionally blocked until tests/build succeed.
Notes for Future You
Package name on index:
grad-visitor-schedulerImport name in Python:
grad_visit_schedulerCurrent release trigger is tag-first; no GitHub Release object is required.