# Automating Pip Package Deployment With Github Actions

> Learn how to use GitHub Actions to speed up your Pip package deployments to PyPi.

- Canonical: https://dennisokeeffe.com/blog/2021-08-11-automating-pip-package-deployment-with-github-actions
- Published: 2021-08-11
- Updated: 2021-08-11
- Tags: python, 100daysofpython, pip, github actions

> This is Day 23 of the #100DaysOfPython challenge.

This post will use GitHub actions to help automate the deploy of your Pip package to the [PyPi](https://pypi.org/) registry.

We will work off the code repository written in yesterday's post ["Semantic Versioning In Python With Git Hooks"](https://blog.dennisokeeffe.com/blog/2021-08-10-semantic-versioning-in-python-with-git-hooks)

The final code can be found [here](https://github.com/okeeffed/automating-pip-package-deployment-with-github-actions).

## Prerequisites

1. Familiarity with [Pipenv](https://pipenv.pypa.io/en/latest/). See [here](https://blog.dennisokeeffe.com/blog/2020-07-04-abcs-of-pipenv) for my post on Pipenv.
2. You will need an access token from PyPi to deploy your package. You can create one for your project [here](https://pypi.org/manage/account/token/).
3. Read ["PyTest With GitHub Actions"](https://blog.dennisokeeffe.com/blog/2021-08-08-pytest-with-github-actions) to get an initial taste of Python GitHub actions.
4. This post will also use the [GitHub CLI](https://github.com/cli/cli).

## Getting started

We will clone the [code from yesterday's post](https://github.com/okeeffed/semantic-versioning-in-python-with-git-hooks) as our starting place.

```s
# Clone the repo
$ git clone https://github.com/okeeffed/semantic-versioning-in-python-with-git-hooks automating-pip-package-deployment-with-github-actions
$ cd automating-pip-package-deployment-with-github-actions
# I am going to reset the Git history for my own repo.
$ rm -rf .git
$ git init
$ git add --all
$ git commit -m "feat: init commit"
$ git tag -a 0.1.0 -m "Init version"

# Install all dependencies
$ pipenv install --dev

# Create a new GitHub action to run our deployment from
$ touch .github/workflows/publish-to-pypi.yml
```

At this stage, we are ready to create our workflow.

## Creating the workflow

We need to add our code to the workflow file `.github/workflows/publish-to-pypi.yml`.

Much of this file will get inspiration from `.github/workflows/pytest.yml`.

Add the following code to `.github/workflows/publish-to-pypi.yml`:

```yml
name: Publish Python 🐍 distributions 📦 to PyPI

on: push
jobs:
  build-and-publish:
    name: Build and publish Python 🐍 distributions 📦 to PyPI
    runs-on: ubuntu-latest
    steps:
      - name: Check out repository code
        uses: actions/checkout@v2

      # Setup Python (faster than using Python container)
      - name: Setup Python
        uses: actions/setup-python@v2
        with:
          python-version: "3.x"

      - name: Install pipenv
        run: |
          python -m pip install --upgrade pipenv wheel
      - id: cache-pipenv
        uses: actions/cache@v1
        with:
          path: ~/.local/share/virtualenvs
          key: ${{ runner.os }}-pipenv-${{ hashFiles('**/Pipfile.lock') }}

      - name: Install dependencies
        if: steps.cache-pipenv.outputs.cache-hit != 'true'
        run: |
          pipenv install --deploy --dev
      - name: Build a binary wheel and a source tarball
        run: |
          pipenv run build
      - name: Publish distribution 📦 to PyPI
        uses: pypa/gh-action-pypi-publish@master
        with:
          password: ${{ secrets.PYPI_API_TOKEN }}
```

Our `pipenv run build` step comes from the script we added in a previous post.

We are now almost ready to test our workflow. The next step will be to ready the `PYPI_API_TOKEN` value on the final line.

> Worth noting: There is also a [test package index](https://test.pypi.org/) that you can use so you do not affect to main index. I am using the main index for my package.

## Adding our PyPi token to GitHub

A prerequisite for this post was to setup a PyPi token to use.

With that token, we will use the GitHub CLI to post it up for use:

```s
# First we need a remote repo to push to
$ gh repo create your-gh-username/automating-pip-package-deployment-with-github-actions --public -y
✓ Created repository your-gh-username/automating-pip-package-deployment-with-github-actions on GitHub
✓ Added remote https://github.com/your-gh-username/automating-pip-package-deployment-with-github-actions.git

# Now we create our token
$ gh secret set PYPI_API_TOKEN
? Paste your secret ********************************************************************
✓ Set secret PYPI_API_TOKEN for your-repo/automating-pip-package-deployment-with-github-actions
```

## Testing our workflow

At this stage, all we need to do is push to remote:

```s
$ git push
Enumerating objects: 28, done.
Counting objects: 100% (28/28), done.
Delta compression using up to 8 threads
Compressing objects: 100% (25/25), done.
Writing objects: 100% (28/28), 12.99 KiB | 1.44 MiB/s, done.
Total 28 (delta 6), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (6/6), done.
To https://github.com/your-gh-username/automating-pip-package-deployment-with-github-actions.git
 * [new branch]      main -> main
Branch 'main' set up to track remote branch 'main' from 'origin'.
```

Head to the link supplied to visit the repository and head to the actions tab and view the `Publish Python 🐍 distributions 📦 to PyPI`.

You should see your workflow succeed.

![GitHub action success](https://cdn.dennisokeeffe.com/assets/2021-08-11-automating-pip-package-deployment-with-github-actions/1-github-action-publish.png)

The GitHub action also provides a link to your package on PyPi.

![Update version on PyPi](https://cdn.dennisokeeffe.com/assets/2021-08-11-automating-pip-package-deployment-with-github-actions/2-updated-package.png)

## Summary

Today's post demonstrated how to automate your publish flow to PyPi on a push action.

Actions are a great way to automate your workflow. Today's simple example enables a publish on each `push`, but you can improve on this to lock branches and even automate the versioning process.

## Resources and further reading

1. [The ABCs of Pipenv](https://blog.dennisokeeffe.com/blog/2020-07-04-abcs-of-pipenv)
2. [Pipenv](https://pipenv.pypa.io/en/latest/)
3. [Repo code](https://github.com/okeeffed/automating-pip-package-deployment-with-github-actions)
4. [Test package index](https://test.pypi.org/)
5. ["PyTest With GitHub Actions"](https://blog.dennisokeeffe.com/blog/2021-08-08-pytest-with-github-actions)
6. [GitHub CLI](https://github.com/cli/cli)

_Photo credit: [`worldsbetweenlines`](https://unsplash.com/@worldsbetweenlines)_
