DEV Community

Tek Kshetri
Tek Kshetri

Posted on

Publish Package to PyPI and Release Version Automation Using GitHub Actions

Manually creating tags, publishing the package and creating the GitHub release is time consuming repetitive task. Creating the version means, same version should be used to create the release and also to publish the package to PyPI library. In this article, I am going to automate this process. Please follow the following steps to automate such task,

1. Create the API token from PyPI

The API token can be created from PyPI user account setting. After creating the token, it will be listed out in the API key section.

create API token from pypi

2. Add API key to the GitHub secret

Now, you need to add the same to the GitHub repository secret. To add that, you need to go to the repository setting, then click on Secrets > actions > New repository secret. Add the name of the secret as PYPI_API_TOKEN.

add GitHub secret

3. Add the YML file to GitHub Workflow

In the repository, create .github/workflows/release_to_pypi.yml file. In this file, you need to write the configuration code for publishing your package. Write the following code into release file to get start,

name: Publish ${package_name} to PyPI / GitHub

on:
  push:
    tags:
      - "v*"
Enter fullscreen mode Exit fullscreen mode

The first name key denotes the name of the task. The second chunk, on key denotes on which condition this condition should run. In above case, whenever the tag starting with letter v is pushed into GitHub, this action will run.

Now add the jobs for this action,

jobs:
  build-n-publish:
    name: Build and publish to PyPI
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source
        uses: actions/checkout@v2

      - name: Set up Python
        uses: actions/setup-python@v2
        with:
          python-version: "3.x"

      - name: Build source and wheel distributions
        run: |
          python -m pip install --upgrade build twine
          python -m build
          twine check --strict dist/*
      - name: Publish distribution to PyPI
        uses: pypa/gh-action-pypi-publish@master
        with:
          user: __token__
          password: ${{ secrets.PYPI_API_TOKEN }}

      - name: Create GitHub Release
        id: create_release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
        with:
          tag_name: ${{ github.ref }}
          release_name: ${{ github.ref }}
          draft: false
          prerelease: false

      - name: Get Asset name
        run: |
          export PKG=$(ls dist/ | grep tar)
          set -- $PKG
          echo "name=$1" >> $GITHUB_ENV
      - name: Upload Release Asset (sdist) to GitHub
        id: upload-release-asset
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: dist/${{ env.name }}
          asset_name: ${{ env.name }}
          asset_content_type: application/zip
Enter fullscreen mode Exit fullscreen mode

These all things are the default things for publishing the package to the PyPI library and to release the GitHub version. You simply copy and paste this code to release_to_pypi.yml library.

I only want to address two things here, the first one is, in the password key(password: ${{ secrets.PYPI_API_TOKEN }}), the secrets we created in previous step is going to use. Make sure the name of the secret creating in the GitHub repository matched to the name of the above variable. Another things is, the GITHUB_TOKEN key (GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}), this secret is provided by GitHub actions, you don't need to create your own token.

If you only want to publish package to PyPI (Do not want to release in GitHub, feel free to remove the last two section from above code, i.e.,

 - name: Create GitHub Release
        id: create_release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
        with:
          tag_name: ${{ github.ref }}
          release_name: ${{ github.ref }}
          draft: false
          prerelease: false

      - name: Get Asset name
        run: |
          export PKG=$(ls dist/ | grep tar)
          set -- $PKG
          echo "name=$1" >> $GITHUB_ENV
      - name: Upload Release Asset (sdist) to GitHub
        id: upload-release-asset
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: dist/${{ env.name }}
          asset_name: ${{ env.name }}
          asset_content_type: application/zip
Enter fullscreen mode Exit fullscreen mode

4. Test whether it will work or not

Finally, it is time to test our workflow whether it will work or not. To test it, first of all, lets create the version in using git,

git tag -a "v0.0.1-beta" -m "beta version testing"
git push --tags
Enter fullscreen mode Exit fullscreen mode

After pushing this tag to the GitHub, it should trigger your GitHub action something like below,

GitHub action

Congratulations! you are successfully integrated this automation.

If you like this blog, please support me by subscribing to my YouTube channel: https://www.youtube.com/c/iamtekson

Top comments (2)

Collapse
 
wjplatformer profile image
Wj

Woah, I did not know there was another way of uploading to PYPI. I did the documentation way which is to use the command line. Genius when using GitHub!

Collapse
 
iamtekson profile image
Tek Kshetri

I got to know about it lately!