A simple GitLab CI example

In the past, we have tried different tools for managing our projects in order to keep them in good conditions. What we need are:

  • Version control
  • Issue tracker
  • Documentation
  • Continuous integration
  • Continuous delivery
  • Repository (artifacts/docker images)

Tools like Jenkins which is good for continuous integration and delivery, Mantis could help tracking issues. But to improve the project efficiency and quality, it is good to bring those tools together. For example, we would like to have the git commit hook up with the issues, or to trigger an automated test after pushing commits to the master branch. Usually, most tools have already provided integration with other services but still it is trouble to configure them. Moreover, the workflow would be broken if any one of the service goes down. So it would be great if there is a single platform which could fulfill all these desires and that’s why we pick GitLab.

GitLab CI

GitLab.com is a SAAS service where you could host your Git repository, track the issues and write the wiki in markdown. They are intuitive features so just register an account and you could try them out. On the other hand, GitLab CI allows us to setup continuous integration and we could even utilize any Docker image available on Docker Hub to implement them. Let’s take a look in the following example.

The .gitlab-ci.yml

This yml contains the definition of all the stages after a CI / CD pipeline is triggered in response to a git push/merge. In this example, we have a simple nodejs project and we would like to make sure the code is good by linting and unit-test. Fork this repository and check it out.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
stages:
  - lint-css
  - lint-js
  - unit-test

image: node:6.11.2


lint css:
  stage: lint-css
  before_script:
    - npm install
  cache:
    untracked: true
  only:
    - master
  script:
    - ./node_modules/gulp/bin/gulp.js lint-css

lint js:
  stage: lint-js
  cache:
    untracked: true
    policy: pull
  only:
    - master
  script:
    - ./node_modules/gulp/bin/gulp.js lint-js

run unit test:
  stage: unit-test
  cache:
    untracked: true
    policy: pull
  only:
    - master
  script:
    - ./node_modules/gulp/bin/gulp.js test

We defined 3 stages, each stage actually is just a gulp task defined in the gulpfile.js. Anyone could run the task locally as long as the have a proper nodejs installed. But in GitLab CI, we only need to tell which Docker image is needed. In our case, that is node:6.11.2. Furthermore, this image attribute could be defined within the stage definition such that you could use different tool for each stage.

More details on the stage definition

Let’s take a deeper look in the stage definition.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
lint css:
  stage: lint-css     # <- Should map to the value defined in the 'stages'
  before_script:      # <- Pre-script
    - npm install
  cache:              # <- Enable caching on files so they are available in the next stage
    untracked: true   # <- Cache the git untracked files (ex. node_modules)
  only:
    - master          # <- This stage run only on master branch update
  script:             # <- The actually script of this stage
    - ./node_modules/gulp/bin/gulp.js lint-css

Both the values of before_script and script could be multiple (array in .yml). And if the script execution has error, this stage will be classified as failed.

Trigger the pipeline

Just make some changes on the master branch and could find the pipeline running on the CI / CD -> Pipeline page.

The pipeline history

The pipeline history

View the stage in detail

Click the pipeline and you could read the console output of each stage. Useful when the stage/job fails.

The stage output

The stage output

The benefits of using GitLab CI with Docker

Different projects needs different tools such as nodejs, ant, maven… etc and in the past when using tool like Jenkins i have to make sure all of them are installed on the server. By using Docker, the developers could pick whatever tools available on Docker Hub without asking the server admin to setup such tools on the server.

Actually Jenkins also has a pipeline plugin and it could work with Docker to serve exactly the same purpose. But extra effort on integrating Jenkins with the version control is needed and as i mentioned before.

Although i prefer using GitLab CI, it doesn’t mean it could completely replace Jenkins. Jenkins offers configurable user interface which is convenient for non-developers such as QA to execute certain tasks like deployments and integration test.

Pick the suitable one but not the perfect one

The key is not about the tool itself, instead it is more about the people who use it. So before start searching for a new tool, try to identify the problem which you would like to solve first.