name: Release to PyPI & GitHub
on:
push:
branches:
- main
permissions:
contents: write
deployments: write
id-token: write
jobs:
build_publish_and_release:
runs-on: ubuntu-latest
environment: pypi
steps:
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Read package metadata
id: metadata
run: |
VERSION=$(grep '^version' pyproject.toml | head -1 | sed -E 's/version *= *"(.*)"/\1/')
NAME=$(grep '^name' pyproject.toml | head -1 | sed -E 's/name *= *"(.*)"/\1/')
echo "VERSION=$VERSION" >> $GITHUB_OUTPUT
echo "PACKAGE_NAME=$NAME" >> $GITHUB_OUTPUT
- name: Start PyPI Deployment
id: create-deployment
uses: actions/github-script@v7
with:
script: |
const deployment = await github.rest.repos.createDeployment({
owner: context.repo.owner,
repo: context.repo.repo,
ref: context.ref,
environment: 'pypi',
auto_merge: false,
required_contexts: [],
transient_environment: true,
});
return deployment.data.id;
result-encoding: string
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install build & twine
run: |
python -m pip install --upgrade pip build twine
- name: Build sdist & wheel
run: python -m build --sdist --wheel
- name: Publish to PyPI
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
run: |
python -m twine upload --skip-existing dist/*
- name: Update Deployment Status
uses: actions/github-script@v7
with:
script: |
github.rest.repos.createDeploymentStatus({
owner: context.repo.owner,
repo: context.repo.repo,
deployment_id: ${{ steps.create-deployment.outputs.result }},
state: 'success',
environment_url: 'https://pypi.org/project/${{ steps.metadata.outputs.PACKAGE_NAME }}/'
});