Publish packages to PyPI
your-orgyour-reporelease.ymlrelease)permissions:
contents: write
id-token: write # Required for trusted publishing
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: astral-sh/setup-uv@v4
- uses: a-line-services/release-pilot@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
If you can't use trusted publishing, use an API token:
PYPI_TOKEN secret in your repo- uses: astral-sh/setup-uv@v4
- uses: a-line-services/release-pilot@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
env:
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TOKEN }}
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- run: pip install build twine
- uses: a-line-services/release-pilot@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
To test publishing before going to production PyPI:
env:
UV_PUBLISH_URL: https://test.pypi.org/legacy/
UV_PUBLISH_TOKEN: ${{ secrets.TEST_PYPI_TOKEN }}
For private PyPI registries (Artifactory, DevPI, etc.):
env:
UV_PUBLISH_URL: https://pypi.your-company.com/simple/
UV_PUBLISH_TOKEN: ${{ secrets.PRIVATE_PYPI_TOKEN }}
[project]
name = "your-package"
version = "0.1.0"
description = "A short description"
readme = "README.md"
license = {text = "MIT"}
authors = [{name = "Your Name", email = "you@example.com"}]
requires-python = ">=3.8"
| Variable | Tool | Description |
|---|---|---|
UV_PUBLISH_TOKEN |
uv | PyPI API token |
UV_PUBLISH_URL |
uv | Custom registry URL |
TWINE_USERNAME |
twine | Username (__token__ for API tokens) |
TWINE_PASSWORD |
twine | Password or API token |