• Stars
    star
    878
  • Rank 51,998 (Top 2 %)
  • Language
    Python
  • License
    BSD 3-Clause "New...
  • Created over 5 years ago
  • Updated 4 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

The blessed :octocat: GitHub Action, for publishing your ๐Ÿ“ฆ distribution files to PyPI: https://github.com/marketplace/actions/pypi-publish

SWUbanner

๐Ÿงช GitHub Actions CI/CD workflow tests badge pre-commit.ci status badge

PyPI publish GitHub Action

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 opt-in to use a full Git commit SHA and Dependabot.

Usage

Trusted publishing

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 example jumps right into the current best practice. If you want to use API tokens directly or a less secure username and password, check out how to specify username and password.

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:

# .github/workflows/ci-cd.yml
jobs:
  pypi-publish:
    name: Upload release to PyPI
    runs-on: ubuntu-latest
    environment:
      name: pypi
      url: https://pypi.org/p/<your-pypi-project-name>
    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

Note
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.

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/

(don't forget to update the environment name to testpypi or similar!)

Note
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.

A common use case is to upload packages only on a tagged commit, to do so add a filter to the job:

    if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')

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 and actions/download-artifact actions for sharing the built dists across stages and jobs. Then, use the needs 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 job 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 under an environment used in your job. Though, passing a password would disable the secretless trusted publishing so it's better to configure it instead, when publishing to TestPyPI and not something custom.

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-publish@release/v1
  with:
    packages-dir: custom-dir/

Disabling metadata verification

It is recommended that you run twine check just after producing your files, but this also runs twine check before upload. You can also disable the twine check with:

   with:
     verify-metadata: false

Tolerating release package file duplicates

Sometimes, when you publish releases from multiple places, your workflow may hit race conditions. For example, when publishing from multiple CIs or even having workflows with the same steps triggered within GitHub Actions CI/CD for different events concerning the same high-level act.

To facilitate this use-case, you may use skip-existing (disabled by default) setting as follows:

   with:
     skip-existing: true

Note
Pro tip: try to avoid enabling this setting where possible. If you have steps for publishing to both PyPI and TestPyPI, consider only using it for the latter, having the former fail loudly on duplicates.

For Debugging

Sometimes, twine upload can fail and to debug use the verbose setting as follows:

   with:
     verbose: true

Showing hash values of files to be uploaded

You may want to verify whether the files on PyPI were automatically uploaded by CI script. It will show SHA256, MD5, BLAKE2-256 values of files to be uploaded.

  with:
    print-hash: true

Specifying a different username

The default username value is __token__. If you publish to a custom registry that does not provide API tokens, like devpi, you may need to specify a custom username and password pair. This is how it's done.

  with:
    user: guido
    password: ${{ secrets.DEVPI_PASSWORD }}

The secret used in ${{ secrets.DEVPI_PASSWORD }} needs to be created on the environment page under the settings of your project on GitHub. See Creating & using secrets.

In the past, when publishing to PyPI, the most secure way of the access scoping for automatic publishing was to use the API tokens feature of PyPI. One would make it project-scoped and save as an environment-bound secret in their GitHub repository settings, naming it ${{ secrets.PYPI_API_TOKEN }}, for example. See Creating & using secrets. While still secure, trusted publishing is now encouraged over API tokens as a best practice on supported platforms (like GitHub).

License

The Dockerfile and associated scripts and documentation in this project are released under the BSD 3-clause license.

More Repositories

1

pipenv

Python Development Workflow for Humans.
Python
24,785
star
2

pipx

Install and Run Python Applications in Isolated Environments
Python
9,971
star
3

pip

The Python package installer
Python
9,448
star
4

hatch

Modern, extensible Python project management
Python
5,754
star
5

sampleproject

A sample project that exists for PyPUG's "Tutorial on Packaging and Distributing Projects"
Python
5,054
star
6

virtualenv

Virtual Python Environment builder
Python
4,770
star
7

pipfile

Python
3,232
star
8

setuptools

Official project repository for the Setuptools build system
Python
2,413
star
9

flit

Simplified packaging of Python modules
Python
2,143
star
10

cibuildwheel

๐ŸŽก Build Python wheels for all the platforms with minimal configuration.
Python
1,796
star
11

twine

Utilities for interacting with PyPI
Python
1,568
star
12

manylinux

Python wheels that work on any linux (almost)
Shell
1,410
star
13

packaging.python.org

Python Packaging User Guide
Python
1,394
star
14

pip-audit

Audits Python environments, requirements files and dependency trees for known security vulnerabilities, and can automatically fix them
Python
951
star
15

setuptools_scm

the blessed package to manage your versions by scm tags
Python
839
star
16

get-pip

Helper scripts to install pip, in a Python installation that doesn't have it.
Python
723
star
17

build

A simple, correct Python build frontend
Python
710
star
18

packaging

Core utilities for Python packages
Python
602
star
19

wheel

The official binary distribution format for Python
Python
494
star
20

bandersnatch

A PyPI mirror client according to PEP 381 http://www.python.org/dev/peps/pep-0381/
Python
439
star
21

auditwheel

Auditing and relabeling cross-distribution Linux wheels.
Python
425
star
22

advisory-database

Advisory database for Python packages published on pypi.org
250
star
23

python-manylinux-demo

Demo project for building Python wheels for Linux with Travis-CI
C
222
star
24

sample-namespace-packages

Tests against namespace packages
Python
175
star
25

readme_renderer

Safely render long_description/README files in Warehouse
Python
158
star
26

packaging-problems

An issue tracker for the problems in packaging
143
star
27

trove-classifiers

Canonical source for classifiers on PyPI.
Python
134
star
28

pyproject-hooks

A low-level library for calling build-backends in `pyproject.toml`-based project
Python
120
star
29

installer

A low-level library for installing from a Python wheel distribution.
Python
118
star
30

gh-action-pip-audit

A GitHub Action for pip-audit
Python
66
star
31

scripttest

Utilities to help with testing command line scripts
Python
60
star
32

distlib

A low-level library which implements some Python packaging standards (PEPs) and which could be used by third-party packaging tools to achieve interoperability.
Python
48
star
33

distutils

distutils as found in cpython
Python
44
star
34

.github

Community health files for the Python Packaging Authority
34
star
35

pyproject-metadata

PEP 621 metadata parsing
Python
30
star
36

pypa.io

Source code for the pypa.io website
Python
24
star
37

interoperability-peps

Development repo for evolution of PyPA interoperability standards (released versions are published as PEPs on python.org)
Python
22
star
38

integration-test

ensure core packaging tools work well with each other
17
star
39

pkg_resources

Abandoned extraction of pkg_resources. Official version found at /pypa/setuptools.
Python
16
star
40

get-virtualenv

13
star
41

history

history generates history/changelog files for a project
Python
7
star
42

easy_install

Python
7
star
43

wheel-builders

Companion repo for the [email protected] mailing list
7
star
44

browntruck

Python
6
star
45

pypa-docs-theme

Common base Sphinx theme for PyPA projects
Python
6
star
46

docker-python

5
star
47

copr

Package files for building PyPA packages in copr
4
star
48

pypa-bot

Source code behind @pypa-bot (eventually)
4
star
49

pep470

Python
4
star
50

pip-test-package

Used in pip's test suite
Python
4
star
51

bootstrap

Assets for bootstrap.pypa.io
Dockerfile
4
star
52

pypi-camo

Dockerfile
3
star
53

bot-test

1
star
54

rootbeer

Bootstrapping Python build backends for source-only environments.
1
star