Continuous Integration on GitLab with Scala and SBT

With Continuous Integration (CI) we aim to be able to test the changes we make to our projects automatically and externally. An usual setup involves e.g. GitHub and Jenkins and requires quite some configuration.

In this post we look at an alternative approach using GitLab which offers both the features of the aforementioned services: git hosting and continuous integration.

In this post we specifically focus on Scala projects with SBT as the build tool. Let’s assume we have an SBT project that contains tests and is hosted on GitLab. Now we have to tell GitLab that we want CI. We do this by adding a .gitlab-cy.yml file in the root directory of our project.

The .gitlab-ci.yml File

Builds are run in Docker and therefore we have to specify in the .gitlab-ci.yml file which Docker image we want to use. Additionally we define some commands before our tests are run. We use the Java 8 image and make sure SBT is installed and available in our builds:

image: java:8

before_script:
  # Enable the usage of sources over https
  - apt-get update -yqq
  - apt-get install apt-transport-https -yqq
  # Add keyserver for SBT
  - echo "deb http://dl.bintray.com/sbt/debian /" | tee -a /etc/apt/sources.list.d/sbt.list
  - apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 642AC823
  # Install SBT
  - apt-get update -yqq
  - apt-get install sbt -yqq
  # Log the sbt version
  - sbt sbt-version

Now let’s define the stages we want to use. We add the test stage with the following lines:

stages:
  - test

At last, we define a job in the test stage that executes the the tests in our project:

test:
  stage: test
  script:
    # Execute your project's tests
    - sbt clean test

Builds within the same stage run in parallel and the jobs in a next stage are started after all previous stages are successfully finished. We can define as much stages and builds as we want. Together, they are called a pipeline.

After we commit and push the .gitlab-ci.yml file to GitLab, CI is enabled and the pipeline is executed on every new push to the project.

Measuring Test Coverage

To display the test coverage of our test job we need to take two steps:

Add test coverage measuring in our SBT project.

Instruct GitLab how to extract the coverage percentage from the build trace.

We measure test coverage by using the SBT plugin sbt-scoverage. Add the following line to /project/plugins.sbt:

addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.3.5")

You can now measure test coverage with sbt clean coverage test coverageReport. We change this in .gitlab-ci.yml:

test:
  stage: test
  script:
    # Execute your project's tests and measure test coverage
    - sbt clean coverage test coverageReport

And in our project settings under CI/CD pipelines > Test coverage parsing we add the following regular expression: Coverage was \[\d+.\d+\%\]. This enables GitLab to extract the coverage percentage from a build trace and display it next the the build results.

Source Code

The source code of a demo SBT project implementing the steps described in this post can be found here:

What’s Next?

Next week we are going a step further and we implement continuous delivery (CD) in GitLab with the Play Framework and Heroku.