PyPI Publishing¶
Publish your Python packages to the Python Package Index.
Overview¶
releasio handles the complete PyPI publishing workflow:
- Build source distribution and wheel
- Validate package metadata
- Authenticate with PyPI
- Upload to registry
- Verify successful publication
Prerequisites¶
Package Structure¶
Your project needs a valid pyproject.toml:
pyproject.toml
[project]
name = "my-package"
version = "1.0.0"
description = "My awesome package"
readme = "README.md"
license = {text = "MIT"}
authors = [
{name = "Your Name", email = "you@example.com"}
]
classifiers = [
"Development Status :: 4 - Beta",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
PyPI Account¶
- Create account at pypi.org
- Verify your email
- Set up trusted publishing or create API token
Authentication¶
Trusted Publishing (Recommended)¶
Configure on PyPI:
- Go to Manage → Publishing
- Add trusted publisher:
- Owner:
your-username - Repository:
your-repo - Workflow:
release.yml
Configure releasio:
Set workflow permissions:
API Token¶
Create token on PyPI:
- Go to Account settings → API tokens
- Create token with project scope
- Add as GitHub secret
PYPI_TOKEN
Use in workflow:
- uses: mikeleppane/releasio@v2
with:
command: release
dry-run: 'false'
pypi-token: ${{ secrets.PYPI_TOKEN }}
Configuration¶
Basic Setup¶
All Options¶
.releasio.toml
[publish]
# Build and publish tool
tool = "uv" # or "poetry", "pdm"
# Enable PyPI publishing
enabled = true
# Use OIDC trusted publishing
trusted_publishing = true
# Validate package before upload
validate_before_publish = true
# Target registry
registry = "https://upload.pypi.org/legacy/"
Workflow Examples¶
Standard Release¶
.github/workflows/release.yml
name: Release
on:
push:
branches: [main]
permissions:
contents: write
pull-requests: write
id-token: write
jobs:
release:
if: startsWith(github.event.head_commit.message, 'chore(release):')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: mikeleppane/releasio@v2
with:
command: release
dry-run: 'false'
github-token: ${{ secrets.GITHUB_TOKEN }}
With Build Verification¶
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install uv
uses: astral-sh/setup-uv@v4
- name: Build and verify
run: |
uv build
uv run twine check dist/*
- uses: mikeleppane/releasio@v2
with:
command: release
dry-run: 'false'
github-token: ${{ secrets.GITHUB_TOKEN }}
TestPyPI¶
Test your publishing workflow before going live.
Setup TestPyPI¶
- Create account at test.pypi.org
- Configure trusted publishing (same as PyPI)
Configuration¶
Workflow¶
.github/workflows/test-publish.yml
name: Test Publish
on:
push:
branches: [develop]
permissions:
id-token: write
jobs:
test-publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: mikeleppane/releasio@v2
with:
command: do-release
execute: 'true'
prerelease: dev
github-token: ${{ secrets.GITHUB_TOKEN }}
Installing from TestPyPI¶
Package Validation¶
releasio validates packages before upload:
Checks Performed¶
| Check | Description |
|---|---|
| Metadata | Required fields present |
| README | Renders correctly |
| License | Valid license specified |
| Version | Follows PEP 440 |
| Wheel | Platform tags correct |
Enable Validation¶
Manual Validation¶
Troubleshooting¶
"Package already exists"¶
Cause: Version already published to PyPI.
Solution: PyPI doesn't allow re-uploading. Bump version and release again.
"Invalid distribution"¶
Causes:
- Malformed
pyproject.toml - Missing required metadata
- Invalid version format
Solution: Validate locally:
"Authentication failed"¶
For trusted publishing:
- Verify
id-token: writepermission - Check publisher config on PyPI matches exactly
For API token:
- Verify token is valid and not expired
- Check token scope includes your project
"Rate limited"¶
Solution: Wait and retry. Consider:
- Using TestPyPI for testing
- Batching releases less frequently
Best Practices¶
Security¶
- Use trusted publishing over API tokens
- Use GitHub environments for production
- Enable two-factor authentication on PyPI
- Review package contents before release
Quality¶
- Test on TestPyPI first
- Validate package before upload
- Include comprehensive README
- Add proper classifiers
Process¶
- Use release PRs for review
- Tag releases in Git
- Keep CHANGELOG updated
- Announce major releases
See Also¶
- Trusted Publishing - OIDC authentication
- Build Tools - Configure uv, poetry, pdm
- Full Workflow - Complete CI/CD