Publishing Guide (CI/CD First)¶
This guide is for automated releases with GitHub Actions. Recommended approach: PyPI Trusted Publishing (OIDC), not long-lived API tokens.
Release Model (Recommended)¶
- Pull requests run CI (tests, lint, typecheck, build check).
- Merging to
mainkeeps the branch releasable. - Creating a version tag (
vX.Y.Z) triggers publish workflow. - Workflow builds once, publishes to TestPyPI, then publishes to PyPI.
One-Time Setup¶
1. Create package projects¶
2. Configure Trusted Publishing on PyPI and TestPyPI¶
In each index (PyPI and TestPyPI), add a Trusted Publisher pointing to this repo:
- Owner:
sirhan1 - Repository:
modelFineTuneRiskAssessment - Workflow filename: your publishing workflow file (for example
publish.yml) - Environment name:
testpypifor TestPyPI publisherpypifor PyPI publisher
Use exact workflow filename and environment names to match your GitHub workflow.
3. Configure GitHub environments¶
In GitHub repo settings, create environments:
testpypipypi
Recommended protections:
- Require reviewers for
pypi. - Restrict allowed branches/tags (for example, only release tags).
Versioning¶
Before release, bump version in both files:
pyproject.toml([project].version)src/alignment_risk/__about__.py(__version__)
Use semantic versioning (MAJOR.MINOR.PATCH).
Pre-Release Checks¶
Run before tagging:
make test
make lint
make typecheck
make check-dist
Suggested CI Workflow (PR + main)¶
Create .github/workflows/ci.yml:
name: CI
on:
pull_request:
push:
branches: [main]
jobs:
checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: python -m pip install --upgrade pip
- run: pip install -e ".[dev]"
- run: make test
- run: make lint
- run: make typecheck
- run: make check-dist
Suggested Publish Workflow (Trusted Publishing)¶
Create .github/workflows/publish.yml:
name: Publish
on:
push:
tags:
- "v*"
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: python -m pip install --upgrade pip
- run: pip install -e ".[dev]"
- run: make check-dist
- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/*
publish-testpypi:
needs: build
runs-on: ubuntu-latest
environment: testpypi
permissions:
id-token: write
steps:
- uses: actions/download-artifact@v4
with:
name: dist
path: dist
- uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/
publish-pypi:
needs: publish-testpypi
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
Notes:
- Build artifacts once and reuse them for both indexes.
- Keep
environmentvalues exactly aligned with Trusted Publisher config. - For Trusted Publishing, avoid calling publish from a reusable workflow.
Release Procedure¶
- Merge release PR into
main. - Create and push tag:
git tag v0.1.1
git push origin v0.1.1
- Watch
publish.ymlin GitHub Actions. - Verify package on TestPyPI and PyPI.
- Create GitHub release notes from the tag.
Rollback and Recovery¶
If publish fails:
- Fix workflow/config issue.
- Delete broken tag locally and remotely if needed.
- Bump to next patch version (do not overwrite released files on PyPI).
- Re-tag and republish.
Emergency Manual Publishing (Fallback)¶
Use this only if CI is unavailable:
make check-dist
python -m twine upload --repository testpypi dist/*
python -m twine upload dist/*
Token-based uploads are fallback-only when Trusted Publishing cannot be used.