What is a GitLab CI/CD?

Continuous Integration (CI) and Continuous Delivery (CD), or CI/CD for short. It’s a tool provided by most git-based project management tools. Each provider might call it by a different name. For example, GitHub has GitHub Actions, Gitlab has GitLab CI/CD and Bitbucket has Bitbucket Pipelines.

What Does GitLab CI/CD Offer?

CI/CD allows executing automatically various steps of the deployment. From executing automatic tests and blocking an entire deployment process for security reasons, through compilation of your application up to deploying your code on the server. But all of these functionalities depend on the provided configuration. Scripts can provide different behaviors for different environments or various actions in a repository. Combining GitLab CI/CD with Laravel Envoy allows performing Zero Downtime Deployment.

Configuration of GitLab CI/CD

Configuration of GitLab CI/CD is done by including a .gitlab-ci.yml in the root directory of your project. GitLab provides example configuration for various technologies: CI/CD templates. But configuration can be done on your own suites for your project. For example this configuration is dedicated to the Laravel application. It includes two stages: Test and Deploy. The test stage executes automatic tests from your code. The deploy stage executes Laravel Envoy script, which is a part of the deployment process. In this configuration, an error on one of the stages means that the code won’t be deployed and previous version of application will be kept online.

image: <path-to-your-image>

services:
  - mysql:8.0

variables:
  MYSQL_DATABASE: <mysql_database>
  MYSQL_ROOT_PASSWORD: <mysql_root_password>
  DB_HOST: <db_host>
  DB_USERNAME: <db_username>

stages:
  - test
  - deploy

unit_test:
  stage: test
  script:
    - cp .env.testing .env
    - composer install
    - php artisan key:generate
    - php artisan config:cache
    - php artisan migrate
    - vendor/bin/phpunit
  only:
    - <production-branch-name>

deploy_production:
  stage: deploy
  script:
    - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
    - eval $(ssh-agent -s)
    - ssh-add <(echo "$SSH_PRIVATE_KEY")
    - mkdir -p ~/.ssh
    - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
    - ~/.composer/vendor/bin/envoy run deploy --commit="$CI_COMMIT_SHA" --branch=<production-branch-name>
  environment:
    name: production
    url: <url-to-production-environment>
  only:
    - <production-branch-name>

In “unit_test” stage, in “only” key, you can provide on which branches unit tests should be executed. Adding another branch is as easy as providing another value in that list.

Adding a new environment to the configuration can be done by simply copying and pasting “deploy_production”. But provide new values for your variables to match other environment.

Executing scripts on server with GitLab CI/CD

GitLab CI/CD can execute prepared scripts on your server. But to do that, GitLab must be identified on the server as one of the users. In case of the VPS we can create a dedicated user for an SSH connection between VPS and GitLab. It allows to separate logic and responsibility from GitLab to the server user. And from there, the logic of these scripts can be as big as you need them to be. But be sure to provide only minimum privileges for security measurements.