Setting up a Continuous Delivery pipeline

In this post we will go over the steps neccessary to setup a complete Continuous Delivery (CD) pipeline using Travis, Github and Leiningen, which will deploy our project to the Clojars repository.

The work involved in deploying a release version of your plugin/library can be tedious and difficult to perform consistently from one release to another, as it involves a lot of repeatable steps.
Fortunately it is also ripe for automation, so let us go over the steps neccessary to achieve this.

Start by creating a separate profile on Clojars.
Deploying and to Clojars repository needs authentication credentials, in the typical form of a username/password.
We will specify to have these credentials looked up in the environment by using a namespaced keyword.

Add the following :deploy-repositories specification to your project.clj:

With this setup, if the project’s current version has a SNAPSHOT qualifier, it will default to deploying to the "snapshots" repository; otherwise it will default to the "releases" repository.
The :sign-releases key set to false is there to make sure that the process doesn’t hang while prompting for a GPG passphrase.

Once we have the repositories and the user credentials for them configured, we can specify the steps for actually deploying the release version.
Include the following :release-tasks key in your project.clj:

This very basic file contains i.e. information on the language of the repository and the test command.

Travis supports storing encrypted values in this file, such as environment variables, only readable by Travis CI, meaning the repository owner does not need to keep any private keys.
We will use this to store the credentials to access Clojars during CI/CD build.

Start by installing the travis-cli and its dependencies:

sudo apt-get install ruby-dev
gem install travis

Now in the root of your repository, where the .travis.yml file resides, run these commands, substituting placeholders with the real credentials:

Travis will execute lein release :patch on the master branch of your repository if the CI build was successful.
If the deploy command returns a non-zero status, deployment is considered a failure, and the build is marked as errored.

There is one more problem which needs addressing.
As you recall when specifying the tasks, we push two commits, and a tagged release to the repository.
This doesn not pose a problem when done locally, but in the CI/CD environment we will push from an unauthenticated Travis server.

This is where Github’s access tokens come in handy.
You can generate one from here, selecting public_repo as the token permissons.

Next, similar to storing the clojars credentials, we will encrypt and add the token as an environment variable to the .travis.yml file:

travis encrypt GH_TOKEN=<your_token_here> --add

We then need to switch to an origin remote which uses the token to authenticate.
I order to do so specify the after-success step in the .travis.yml file:

Placeholders need to be replaced with the value corresponding to your project.
GH_TOKEN will be substituted inside the build server with the un-encrypted token carrying commit rights, and we pipe the output to the /dev/null to avoid leaking the token in the Travis’s build logs.

Note

Alternatively these steps can be done as part of the Travis’s deploy step script.

As a final bonus Clojars creates version badges, which always point to the latest version of your library, saving you the need to manually alter projects documentation, you can display one by adding to the project’s README: