Language Guide: Clojure

Overview

This guide will help you get started with a Clojure application on CircleCI. If you’re in a rush, just copy the sample configuration below into a .circleci/config.yml in your project’s root directory and start building.

Otherwise, we recommend reading our walkthrough for a detailed explanation of our configuration.

We’re going to make a few assumptions here:

You’re using clojure.test with Leiningen’s built-in test task.

Your application can be distributed as an all-in-one uberjar.

If you use another testing tool, you can just adjust that step to run a different lein task.

Get the Code

If you want to step through it yourself, you can fork the project on GitHub and download it to your machine. Go to the Add Projects page in CircleCI and click the Build Project button next to your project. Finally, delete everything in .circleci/config.yml.

Now we’re ready to build a config.yml from scratch.

Config Walkthrough

We always start with the version.

version: 2

Next, we have a jobs key. Each job represents a phase in your Build-Test-Deploy process. Our sample app only needs a build job, so everything else is going to live under that key.

In each job, we have the option of specifying a working_directory. In this sample config, we’ll name it after the project in our home directory.

version: 2
jobs:
build:
working_directory: ~/cci-demo-clojure

This path will be used as the default working directory for the rest of the job unless otherwise specified.

Directly beneath working_directory, we can specify container images under a docker key.

We set JVM_OPTS here in order to limit the maximum heap size; otherwise we’ll run into out of memory errors. The standard container limit is 4 GB, but we leave some extra room for Leiningen itself as well as things the JVM keeps outside the heap. (You can avoid the Leiningen overhead by using lein trampoline ... in some cases.) If you have background containers for your database, queue, etc, be sure to factor them in when you allocate memory for the main JVM heap.

Normally Leiningen expects to be run as a non-root user and will assume you’re running as root by accident. We set the LEIN_ROOT environment variable to indicate that it’s intentional in this case.

environment:
JVM_OPTS: -Xmx3200m
LEIN_ROOT: nbd

Now we’ll add several steps within the build job.

We start with checkout so we can operate on the codebase.

Next we pull down the cache, if present. If this is your first run, or if you’ve changed project.clj, this won’t do anything. We run lein deps next to pull down the project’s dependencies. Normally you never call this task directly since it’s done automatically when it’s needed, but calling it directly allows us to insert a save_cache step that will store the dependencies in order to speed things up for next time.

Then lein do test, uberjar runs the actual tests, and if they succeed, it creates an “uberjar” file containing the application source along with all its dependencies.

Finally we store the uberjar as an artifact using the store_artifacts step. From there this can be tied into a continuous deployment scheme of your choice.

Detailed Examples

This app illustrates the simplest possible setup for a Clojure web app. Real world projects tend to be more complex, so you may find these more detailed examples of real-world apps useful as you configure your own projects: