Introduction to GitLab CI/CD

By Arun AK, 9 November, 2019

Gitlab is a web-based Dev ops tool that provides git repository manager along with CI/CD pipeline features. Here we will see how to set up gitlab CI/CD pipeline for a project.

Continuous integration is a development practice that can help to identify the issues early in the code by verifying each check-in by the developers. Before we start with CI let us understand what is a runner.

Runners are the server that provides an environment to check out the code and allow perform actions such as validate, build and deploy to a different server. That means runners are clean servers, so we need to prepare the environment to run our code. That means, if we need to validate your code using some specific tool, for example, phpcs, you need to install phpcs on the server. If you are using composer to manage the dependency then you need to install the composer on the runner.

To make things easier you can use a predefined Docker image to set up the environment. For example, if you are setting up the environment for a Drupal project you need to have the following items installed on your server.

  • PHP
  • Composer
  • Drush

You can choose the required docker image from the docker hub.

Now let us see how to configure CI for your repository. The first step is you need to create a .gitlab-ci.yml file in the root of your project directory. This is the key file where you configure what CI does with your project.

The first thing that you need to mention your .gitlab-ci.yml is which docker image you need to use to prepare the environment. For example here we are using nbcuniversalpaint/drupal-php image.

image: "nbcuniversalpaint/drupal-php"

Then next is you need to declare the different stages of your CI process. Here we go only with one stage called 'Deploy'.

stages:
  - Deploy

Next is you have to set up the required applications to perform certain actions. For example, here we are going to see how to deploy your changes to the server using rsync. To set up rsync you need to set up the following items:

  1. Add a SSH private key to your runner.
  2. Install rsync on the runner.

You can do the setup using 'before_script' directive as below:

before_script:
  ##
 ## Install ssh-agent if not already installed, it is required by Docker.
 ## (change apt-get to yum if you use an RPM-based image)
 ##
 - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'

  ##
 ## Run ssh-agent (inside the build environment)
 ##
 - eval $(ssh-agent -s)

  ##
 ## Create the SSH directory and give it the right permissions
 ##
 - mkdir -p ~/.ssh
  - chmod 700 ~/.ssh

  - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'

  ##
 ## Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store
 ## We're using tr to fix line endings which makes ed25519 keys work
 ## without extra base64 encoding.
 ## https://gitlab.com/gitlab-examples/ssh-private-key/issues/1#note_48526556
 ##
 - ssh-add <(echo "$SSH_PRIVATE_KEY")

  ##
 ## Install rsync
 ##
 - apt-get update -qy
  - apt-get install rsync

In the above code you can see that it is using variable '$SSH_PRIVATE_KEY'. To protect the ssh private key we are using gitlab CI variables. As the .gitlab-ci.yml file is version controlled and CI log is visible in the gitlab we should use GitLab CI/CD environment variables to define security keys such as username, password, ssh keys, etc.

You can set up the environment variables under Settings -> CI/CD -> Variables section of your repository.

GitLab CI/CD environment variables

In the next step, you need to define the stages that you have already declare at the top.

Develop:
  stage: Deploy
  script:
    - rsync -r -e 'ssh -p 2222' --exclude='.git/' --exclude='sites/*/settings*.php' --exclude='sites/*/files' --exclude='sites/*/private' --exclude='.gitlab-ci.yml' ./ username@yourwebsite.com:public_html

Under the script section, you can have the code that needs to run as part of the stage. Here it is pushing files to the server using rsync. In the above code, you need to mention the 'username' and 'yourwebsite' domain. You can see the available options in the rsync command. In the above code, it is excluding the following files from deploy to the server.

  1. sites/*/settings*.php
  2. sites/*/files
  3. sites/*/private
  4. gitlab-ci.yml

So the final .gitlab-ci.yml file will looks like below:

image: "nbcuniversalpaint/drupal-php"

stages:
  - Deploy

before_script:
  ##
 ## Install ssh-agent if not already installed, it is required by Docker.
 ## (change apt-get to yum if you use an RPM-based image)
 ##
 - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'

  ##
 ## Run ssh-agent (inside the build environment)
 ##
 - eval $(ssh-agent -s)

  ##
 ## Create the SSH directory and give it the right permissions
 ##
 - mkdir -p ~/.ssh
  - chmod 700 ~/.ssh

  - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'

  ##
 ## Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store
 ## We're using tr to fix line endings which makes ed25519 keys work
 ## without extra base64 encoding.
 ## https://gitlab.com/gitlab-examples/ssh-private-key/issues/1#note_48526556
 ##
 - ssh-add <(echo "$SSH_PRIVATE_KEY")

  ##
 ## Install rsync
 ##
 - apt-get update -qy
  - apt-get install rsync

Develop:
  stage: Deploy
  script:
    - rsync -r -e 'ssh -p 2222' --exclude='.git/' --exclude='sites/*/settings*.php' --exclude='sites/*/files' --exclude='sites/*/private' --exclude='.gitlab-ci.yml' ./ username@yourwebsite.com:public_html

Hope this helps you to set up continuous integration for your project with GitLab. Always remember to choose the right docker image based upon the required configuration of your project.