Transitioning to CircleCI from Github Actions
I recently updated all JaxGaussianProcesses packages to use CircleCI for CI/CD. This post documents my experiences with this.
Why Run Continuous Integration and Continuous Deployment
Setting up CircleCI
Setting up CircleCI is straightforward. You simply create an account using your
Github account and then add the repository you want to use. You can then create
a .circleci
folder in the root of your repository and add a config.yml
file.
This file contains the configuration for your CI/CD pipeline. To start with, my
file took the following form:
|
|
One complication came in that JaxKern stores its dependencies in the setup.py
file, not the requirements.txt
file. It seems most CircleCI documentation
assumes the latter structure. To resolve this and install the dev
requirements
from your setup.py
file, simply replace the python/install-packages
step
with the following:
|
|
A further nuance is that to use JAX versions greater than 0.4.0, as we do in
JaxKern, you need a pip version greater than the one given in
cimg/python:3.8.0
. To resolve this, I simply added the following step:
|
|
Customising the CI/CD Pipeline
Continuous Deployment
Continuous deployment is wonderfully helpful. When a set of rules are met, the code is automatically deployed to PyPI. This means that you can be confident that the code on PyPI is always up to date. This is particularly useful for packages that are used by other packages. For example, JaxKern is used by GPJax. If JaxKern is not up to date on PyPI, then GPJax will not work.
To add this into your CircleCI config file, add the following job
|
|
There’s a lot here, so let’s unpack it. We first create a .pypirc
file. This
file contains the credentials for uploading to PyPI. We then build the package
and upload it to PyPI. The --verbose
flag is useful for debugging. If you have
multiple PyPI accounts, you can add them to the .pypirc
file. For example, I
have a PyPI account for JaxKern and a PyPI account for my personal projects. I
can add both to the .pypirc
file and then upload to the correct account by
specifying the -r
or --repository
flag.
Note: The environment variables used above i.e., JAXKERN_PYPI
and PYPI_TOKEN
are set in the CircleCI environment variables, not Github. To set
them, go to the project settings in CircleCI and then click on the Environment Variables
tab. You can then add the variables there. The variables themselves
are the API tokens for the PyPI accounts. You can create these tokens in your
personal token setting.
The coverage report generated by pytest
is also uploaded to CircleCI. This is achieved by adding the codecov
orb to the config.yml
file:
|
|
Before adding the following chunk to the build-and-test
job:
|
|
Note - you’ll also need to make an environmental variable in CircleCI for the CODECOV_TOKEN
. You can get this token from your Codecov settings.
To only build the package when a new tag is pushed, add the following to the workflows
section of the config.yml
file:
|
|
In this chunk, the publish
job is only run when a tag starting with v
is pushed. This can be achieved by running
|
|
The build-and-test
job is required for the publish
job to run.
Initial Observations
User Interface
The interface in CircleCI is nice. Compared to Github Actions, I find it much cleaner and easier to navigate. Whilst not critical, this is a nice improvement.
Triggering Workflows
Once a repository is added to CircleCI, it will automatically trigger a workflow for every commit to a branch containing .circleci/config.yml
. This is a nice feature, as it means that you can test your CI/CD pipeline before merging it into the main branch.
Builds can be manually triggered through the CircleCI web interface.
Local Testing
I always struggled to run Github actions locally. However, running CircleCI locally was a breeze. On my linux machine I installed CircleCI and Docker and connected the two through the following
|
|
You then must authenticate yourself with CircleCI by adding your API token. You can create an API token in your personal token setting. Once this is done, add the token to your CircleCI CLI by running
|
|