Skip to content

Commit

Permalink
Add a guide about publishing dists via GH Actions
Browse files Browse the repository at this point in the history
  • Loading branch information
webknjaz committed Sep 15, 2019
1 parent fb64a4d commit e880724
Show file tree
Hide file tree
Showing 2 changed files with 169 additions and 0 deletions.
1 change: 1 addition & 0 deletions source/guides/index.rst
Expand Up @@ -29,3 +29,4 @@ introduction to packaging, see :doc:`/tutorials/index`.
migrating-to-pypi-org
using-testpypi
making-a-pypi-friendly-readme
publishing-package-distribution-releases-using-github-actions-ci-cd-workflows
@@ -0,0 +1,168 @@
Publishing Package Distribution 📦 Releases Using GitHub Actions CI/CD Workflows 🤖
===================================================================================

`GitHub Actions CI/CD`_ allow you to run a series of commands
whenever an event occurs in the GitHub Platform. One of the
popular choices is having a workflow that's triggered by a
``push`` event.
This guide will show you how to publish a Python distribution
package whenever a tagged commit is pushed.

.. attention::

This guide *assumes* that you already have a project that
you know how to build dists for and *it lives on GitHub*.

.. warning::

At the time of writing this guide, `GitHub Actions CI/CD`_
is still in public beta. If you don't have it enabled,
you should join the waitlist in order to gain the access.

N.B. It is known that GitHub is going to make Actions
publicly available on the Nov 13th, 2019.


Saving credentials on GitHub
----------------------------

In this guide, we'll demonstrate uploading to both production
PyPI and Test PyPI meaning that we'll have two separate sets
of creds. And we'll need to save them in GitHub repo settings.

Let's begin! 🚀

1. Go to https://pypi.org/manage/account/#api-tokens and
create a new `API token`_. If you have the project on PyPI
already, please limit the token scope to just that project.
You can call it smth like
``GitHub Actions CI/CD — project-org/project-repo``
in order for it to be easily distinguishable in the token
list.
**Don't close the page just yet — you won't see that token
again.**
2. In a separate browser tab or window, go to the ``Settings``
tab of your target repository and then click on `Secrets`_
in the left sidebar.
3. Create a new secret called ``pypi_password`` and copy-paste
the token from the fist step.
4. Now, go to https://test.pypi.org/manage/account/#api-tokens
and repeat the steps. Save that Test PyPI token on GitHub
as ``test_pypi_password``.


Creating a workflow definition
------------------------------

GitHub CI/CD Workflows are declared in YAML files stored under
``.github/`` of your repository.

Start it with a meaningful name and define the even that
should make GitHub run this workflow:

.. code-block:: yaml
name: Publish Python 🐛 distribution package 📦 to PyPIs
on: push
Defining a workflow job environment
-----------------------------------

Now, let's add initial setup for our job. It's a process that
will execute commands that we'll define later.
In this guide, we'll choose to use Ubuntu 18.04:

.. code-block:: yaml
build-n-publish:
name: Build and publish Python 🐛 dist 📦 to PyPIs
runs-on: ubuntu-18.04
Checking out the project and building dists
-------------------------------------------

Then, add the following under the ``build-n-publish`` section:

.. code-block:: yaml
steps:
- uses: actions/checkout@master
- name: Set up Python 3.7
uses: actions/setup-python@v1
with:
version: 3.7
This will download your repository into the CI runner and then
install and activate Python 3.7.

And now we can build dists from source. In this example, we'll
use ``pep517`` package, *assuming that your project has a ``pyproject.toml`` properly set up (see :pep:`517`/:pep:`518`)*.

.. tip::

You can use any other method for building dists as long as
it produces ready-to-upload artifacts saved into ``dist/``
folder.

So add this to the steps list:

.. code-block:: yaml
- name: Install pep517
run: >-
python -m
pip install
pep517
--user
- name: Build a binary wheel and a source tarball
run: >-
python -m
pep517.build
--source
--binary
--out-dir dist/
.
Publishing dist to Test PyPI and production PyPI
------------------------------------------------

Finally, add the following steps in the end:

.. code-block:: yaml
- name: Publish 📦 to Test PyPI
uses: pypa/gh-action-pypi-publish@master
with:
password: ${{ secrets.test_pypi_password }}
repository_url: https://test.pypi.org/legacy/
- name: Publish 📦 to production PyPI
if: startsWith(github.event.ref, 'refs/tags')
uses: pypa/gh-action-pypi-publish@master
with:
password: ${{ secrets.pypi_password }}
These two steps use `pypa/gh-action-pypi-publish`_ GitHub
Action: the first one uploads contents of the `dist/` folder
into Test PyPI unconditionally and the second does that to
production PyPI but only if the current commit is tagged.


That's all, folks!
------------------

Now, whenever you push a tagged commit to your Git repo remote
on GitHub, this workflow will publish it to PyPI.
And it'll publish any push to Test PyPI which is useful for
providing test builds to your alpha users as well as making
sure that your release pipeline keeps being healthy!


.. _API token: https://pypi.org/help/#apitoken
.. _GitHub Actions CI/CD: https://github.com/features/actions
.. _pypa/gh-action-pypi-publish:
.. _Secrets:
https://help.github.com/en/articles/virtual-environments-for-github-actions#creating-and-using-secrets-encrypted-variables

0 comments on commit e880724

Please sign in to comment.