This action allows you to upload your Python distribution packages
in the dist/
directory to PyPI.
This text suggests a minimalistic usage overview. For more detailed
walkthrough check out the PyPA guide.
If you have any feedback regarding specific action versions, please leave
comments in the corresponding per-release announcement discussions.
🌇 master
branch sunset ❗
The master
branch version has been sunset. Please, change the GitHub
Action version you use from master
to release/v1
or use an exact
tag, or a full Git commit SHA.
Usage
To use the action add the following step to your workflow file (e.g.
.github/workflows/main.yml
)
- name: Publish a Python distribution to PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: password: ${{ secrets.PYPI_API_TOKEN }}
Pro tip: instead of using branch pointers, like
unstable/v1
, pin
versions of Actions that you use to tagged versions or sha1 commit identifiers.
This will make your workflows more secure and better reproducible, saving you
from sudden and unpleasant surprises.
A common use case is to upload packages only on a tagged commit, to do so add a
filter to the step:
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
So the full step would look like:
- name: Publish package if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') uses: pypa/gh-action-pypi-publish@release/v1 with: password: ${{ secrets.PYPI_API_TOKEN }}
The example above uses the new API token feature of
PyPI, which is recommended to restrict the access the action has.
The secret used in ${{ secrets.PYPI_API_TOKEN }}
needs to be created on the
settings page of your project on GitHub. See Creating & using secrets.
Trusted publishing
IMPORTANT: This functionality is in beta, and will not work for you
unless you’re a member of the PyPI trusted publishing beta testers’ group.
For more information, see warehouse#12965.
NOTE: Trusted publishing is sometimes referred to by its
underlying technology — OpenID Connect, or OIDC for short.
If you see references to “OIDC publishing” in the context of PyPI,
this is what they’re referring to.
This action supports PyPI’s trusted publishing
implementation, which allows authentication to PyPI without a manually
configured API token or username/password combination. To perform
trusted publishing with this action, your project’s
publisher must already be configured on PyPI.
To enter the trusted publishing flow, configure this action’s job with the
id-token: write
permission and without an explicit username or password:
jobs: pypi-publish: name: Upload release to PyPI runs-on: ubuntu-latest permissions: id-token: write # IMPORTANT: this permission is mandatory for trusted publishing steps: # retrieve your distributions here - name: Publish package distributions to PyPI uses: pypa/gh-action-pypi-publish@release/v1
Other indices that support trusted publishing can also be used, like TestPyPI:
- name: Publish package distributions to TestPyPI uses: pypa/gh-action-pypi-publish@release/v1 with: repository-url: https://test.pypi.org/legacy/
Pro tip: only set the
id-token: write
permission in the job that does
publishing, not globally. Also, try to separate building from publishing
— this makes sure that any scripts maliciously injected into the build
or test environment won’t be able to elevate privileges while flying under
the radar.
Non-goals
This GitHub Action has nothing to do with building package
distributions. Users are responsible for preparing dists for upload
by putting them into the dist/
folder prior to running this Action.
IMPORTANT: Since this GitHub Action is docker-based, it can only
be used from within GNU/Linux based jobs in GitHub Actions CI/CD
workflows. This is by design and is unlikely to change due to a number
of considerations we rely on.This should not stop one from publishing platform-specific
distribution packages, though. It is strongly advised to separate jobs
for building the OS-specific wheels from the publish job. This allows
one to (1) test exactly the same artifacts that are about to be
uploaded to PyPI, (2) prevent parallel unsynchronized jobs from
publishing only part of the dists asynchronously (in case when part of
the jobs fail and others succeed ending up with an incomplete release
on PyPI) and (3) make an atomic upload to PyPI (when part of the dists
appear on PyPI, installers like pip will use that version for the
dependency resolution but this may cause some environments to use
sdists while the wheel for their runtime is not yet available).To implement this sort of orchestration, please use
actions/upload-artifact
andactions/download-artifact
actions for
sharing the built dists across stages and jobs. Then, use theneeds
setting to order the build, test and publish stages.
Advanced release management
For best results, figure out what kind of workflow fits your
project’s specific needs.
For example, you could implement a parallel workflow that
pushes every commit to TestPyPI or your own index server,
like devpi
. For this, you’d need to (1) specify a custom
repository-url
value and (2) generate a unique version
number for each upload so that they’d not create a conflict.
The latter is possible if you use setuptools_scm
package but
you could also invent your own solution based on the distance
to the latest tagged commit.
You’ll need to create another token for a separate host and then
save it as a GitHub repo secret.
The action invocation in this case would look like:
- name: Publish package to TestPyPI uses: pypa/gh-action-pypi-publish@release/v1 with: password: ${{ secrets.TEST_PYPI_API_TOKEN }} repository-url: https://test.pypi.org/legacy/
Customizing target package dists directory
You can change the default target directory of dist/
to any directory of your liking. The action invocation
would now look like:
- name: Publish package to PyPI uses: pypa/gh-action-pypi-p