GitLab has a built-in CI system. A GitLab CI pipeline consists of a number of stages. In a stage, a number of jobs are executed in parallel. Jobs are executed as scripts within a docker container.

In the last days I set out to expand my basic knowledge of GitLab CI pipelines (e.g. compiling a Java project with gradle) in order to write a pipelines that compiles, tests and deploys a project to a CloudFoundry instance. Here are 3 things I learnt about.

Reusing jobs with “extends”

“extends” lets us reuse a job. It’s kind of “extract to method” refactoring: suppose I write a job to publish to CloudFoundry. It consists of three steps:

  1. install CloudFoundry CLI
  2. Login to CloudFoundry
  3. Publish app to CloudFoundry

A job that publishes an app to “dev” stage only differs in step 3 to a job that publishes the app to “test” stage. So we write a job that publishes an app to CloudFoundry based on some variables (e.g. “STAGE”)

and then our job “deploy-to-dev” just extends this job and redefines STAGE

We can further “refactoring” our CI pipeline by “extracting” the install&login part because we have two CF foundations and therefore, two different values for “CF_USER” and “CF_PASSWORD”

Test results

GitLab CI understands JUnit test result XML and we just need to provides it as artifact report:

You can see the test results in the pipeline and in the merge request screen.

Speed up caches

Our pipeline uses the cache to avoid downloading gradle (our build tool) and all dependencies everytime a job builds or tests the code. But it is painfully slow, especially collecting the files and pushing the cache.

In my case it takes several minutes (!) to collect 3000+ files in .gradle dir. Things sped up significantly when adding:

Here is the documentation.