I have a few private Github repositories where I use Travis for running checks on each of my commits. A couple of days ago I received a message from Travis telling me that I only had 10 builds left as part of my trial. Luckily, someone told me CircleCI allows unlimited private builds for free, so I’m going to try it out.

Creating an account

The first step is to create an account. They allow to sign up with Github, so I just chose that option:

Sign up with Github

Build config file

The next step is to create the build config file. Inside the repo, run these commands:

1
2
mkdir .circleci/
touch .circleci/config.yml

Adding build commands

The next thing we want to do is create a job and add a build command to it. I usually create a script with all the steps I want to do as part of my build and just call that file:

1
2
3
4
5
6
7
8
9
version: 2.1

jobs:
  build:
    machine:
      image: ubuntu-1604:201903-01
    steps:
      - checkout
      - run: sh scripts/publish.sh

Notice that the code is not checked out automatically. We need to do it as one of our steps. We also need to specify the environment where our build will run. I decided to run my publish.sh script in an ubuntu machine. The documentation explains the different executors that can be used.

Choosing branches

Currently my build step takes care of creating a publishing artifacts as well as running checks. For that reason, I prefer to only build the master branch. Configuration file version 2.1 forces us to create a workflow. Let’s create one:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
version: 2.1

jobs:
  build:
    machine:
      image: ubuntu-1604:201903-01
    steps:
      - checkout
      - run: sh scripts/publish.sh

workflows:
  version: 2
  push_and_publish:
    jobs:
      - build:
          filters:
            branches:
              only: master

A workflow is a set of build steps that can be executed sequentially or in parallel as part of your build. For example, you might want to build your package and run the linter in parallel, then run your tests, and finally publish your artifacts.

In this scenario, I’m not taking advantage of the workflows, I’m just creating it, because that’s the only way to specify that I only want to run my build for the master branch. The workflow is called push_and_publish and it will run the build job (defined in the jobs section of the configuration file). I make use of filters to specify that only master branch should be built.

Environment variables and secrets

It is common that some private information is needed in order to execute some of the build steps. In my case, I want to create a docker image and publish the image to a docker registry. I don’t want the credentials to the docker registry to be checked into the code repository, so I want a way to inject them to the CircleCI build before it runs.

We can set up environment variables by going to the settings of the project and choosing the Environment variables option:

CircleCI environment variables

Since I usually create a docker image and push it to a registry, I add here a key that would allow the system to push to the registry.

Pushing back to Github

Something else I do as part of my build is tag the commit that was built with the version of the artifact that was generated. To do this, CircleCI needs push permissions to the repo, which it doesn’t have by default.

When we start using CircleCI for building a Github repo, it creates a new read-only key. To be able to push, we need a read-write key. To create a key, we can use these commands:

1
2
openssl genrsa -out ~/.ssh/circleci 2048
ssh-keygen -y -f ~/.ssh/circleci > ~/.ssh/circleci.pub

Then, we need to add this as a Deploy key for the repo. This can be done from Github, in the repository settings:

Github deploy keys

When prompted, enter the public key.

The private key needs to be added to CircleCI. This can be done from SSH Permissions within the project settings:

CircleCI SSH Permissions

When prompted, enter github.com as hostname and the private key.

We also need to add a step to our build to register our ssh key. This is how my final config.yml looks like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
version: 2.1

jobs:
  build:
    machine:
      image: ubuntu-1604:201903-01
    steps:
      - add_ssh_keys:
          fingerprints:
            - "d5:86:ca:bd:62:d5:48:8c:bc:76:77:c9:8c:43:89:89"
      - checkout
      - run: sh scripts/publish.sh

workflows:
  version: 2
  push_and_publish:
    jobs:
      - build:
          filters:
            branches:
              only: master

The last step is just committing this file and pushing it.

[ automation  testing  ]
Using testify for Golang tests
Unit testing Golang code
Building an Android project from scratch using gradle
Android UI Automation using Espresso
Creating a Robolectric project from scratch with ant