CICD to PyPI with Bitbucket Pipelines

I use Bitbucket for source control and I absolutely love Bitbucket Pipelines.
I have been using Pipelines for a while to do automated testing of many of my Python projects utilizing tox. However, the one piece that was missing was the Continuous Deployment to PyPI. I started by following the documentation on Atlassian’s own site but found it to not be complete. Couple that with some of the recent updates to Bitbucket Pipelines I’ve decided to update with my own FAQ on how I do it!

The Recipe

Here is my bitbucket pipeline “recipe” for an example project:

image: python:3.6  # Default image for all steps
pipelines:
  default:
      - step:
          name: Python 2 Tests
          image: python:2.7
          script:
            - pip install -U tox
            - tox -e py27
      - step:
          name: Python3 Tests
          script:
            - pip install -U tox
            - tox -e py36
  branches:
    master:
      - step:
          name: Python 2 Tests
          image: python:2.7
          script:
            - pip install -U tox
            - tox -e py27
      - step:
          name: Python3 Tests
          script:
            - pip install -U tox
            - tox -e py36
      - step:
          name: Deploy To PyPI
          script:
            - bash -e deploy.bash

This configuration allows tests of Python2 and Python3 on all branches including master. The only difference on master the additional step to actually do the deploy to PyPI. For my deploy script I first created some secure environment variables in my Bitbucket Repo configuration to store my PyPI Username/Password (I didn’t want to hard code these into the repo so that just anyone could see them). I then created the following script, based of the Atlassian example:

 #!/bin/bash -e
 cat <<EOF >> ~/.pypirc
 [distutils]
 index-servers=pypi
 [pypi]
 repository=https://upload.pypi.org/pypi
 username=${PYPI_USERNAME}
 password=${PYPI_PASSWORD}
 EOF
 python setup.py sdist upload;
 rm ~/.pypirc;

And that is it! Now when I commit to any branch besides master my automated testing is run using both Python2 and Python3 and when I complete a release cut and merge to master the tests run as normal but then a the deploy.bash script runs and sends the updated code to PyPI.

I hope you find this useful in turning up CICD for Python projects using Bitbucket Pipelines!

P.S. You could have another step for any release* branch that automatically tests your upload to the PyPi dev site. I haven’t included those steps here but they should be easy enough to figure out!

 
comments powered by Disqus