< Home

Configuring GitLab CI

The config file

GitLab continuous integration is controlled by the .gitlab-ci.yml file, which should exist in the root of the project’s file structure. When the presence of this file is detected in response to a commit, the GitLab CI runner will kick off the relevant stages as defined in the yml file.

Structure

The file has three main sections:

Variables

These should be listed underneath the variables key, e.g:

variables:
  PROD_S3_BUCKET_NAME: "myblog.cc"
  STAGING_S3_BUCKET_NAME: "staging.myblog.cc"
  PROD_BLOG_URL: "https://myblog.cc/"
  STAGING_BLOG_URL: "https://staging.myblog.cc/"

Stages

The stages key lists all the stages that will run as part of a job. They run sequentially as listed, but where there are multiple jobs in a stage, these will run in parallel.

stages:
  - stage_build
  - prod_build
  - stage_deploy
  - prod_deploy

Here there are four stages, broken into two types - stage, which targets the staging environment and prod which targets the live environment.

Job definitions

This is an example of a job definition:

build_production:
  stage: prod_build
  image: jguyomard/hugo-builder:latest
  script:
  - git submodule update --init --recursive
  - hugo --destination public_html --baseURL "${PROD_BLOG_URL}"
  cache:
    paths:
    - public_html
  artifacts:
    paths:
    - public_html
  only:
  - master

Breaking this down line by line:

build_production:

this is the name of the job, which should be unique

stage: prod_build

the name of the stage to which this job belongs. Where a stage has more than one job, all jobs will run in parallel

image: jguyomard/hugo-builder:latest

The Docker image that will be built and used to run this job - in this case, it’s a minimum viable Hugo installation used to build the static site assets.

script:
- git submodule update --init --recursive
- hugo --destination public_html --baseURL "${PROD_BLOG_URL}"

The Bash script(s) that will run once the Docker image has been spun up. Variables can be substituted using the ${VARIABLE_NAME} syntax.

cache:
  paths:
  - public_html

The paths that should be cached internally during the job. Caches don’t get persisted outside of the lifespan of the job itself.

artifacts:
  paths:
  - public_html

Paths that should be persisted between jobs, so can be accessed by other jobs after this one has completed. In this case, Hugo will write the site assets to the public_html directory, and these files will be transferred to S3 in the next deployment stage.

only:
- master

Git branches where commits will trigger this job - any commit to the master branch will trigger this job.

The opposite of only: is except:, so

except:
- staging

will run the job on all branches except staging.

The full sample .gitlab-ci.yml

variables:
  PROD_S3_BUCKET_NAME: "trashpanda.cc"
  STAGING_S3_BUCKET_NAME: "staging.trashpanda.cc"
  PROD_BLOG_URL: "https://trashpanda.cc/"
  STAGING_BLOG_URL: "https://staging.trashpanda.cc/"

stages:
  - stage_build
  - prod_build
  - stage_deploy
  - prod_deploy

prod_build:
  stage: prod_build
  image: jguyomard/hugo-builder:latest
  script:
  - git submodule update --init --recursive
  - hugo --destination public_html --baseURL "${PROD_BLOG_URL}"
  cache:
    paths:
    - public_html
  artifacts:
    paths:
    - public_html
  only:
  - master

stage_build:
  stage: stage_build
  image: jguyomard/hugo-builder:latest
  script:
  - git submodule update --init --recursive
  - hugo --buildDrafts --destination staging_html --baseURL "${STAGING_BLOG_URL}" --environment staging
  cache:
    paths:
    - staging_html
  artifacts:
    paths:
    - staging_html
  except:
  - master

prod_deploy:
  stage: prod_deploy
  image: python:latest
  script:
  - pip install awscli
  - aws s3 cp ./public_html s3://$PROD_S3_BUCKET_NAME/ --recursive --acl public-read
  only:
  - master

stage_deploy:
  stage: stage_deploy
  image: python:latest
  script:
  - pip install awscli
  - aws s3 cp ./staging_html s3://$STAGING_S3_BUCKET_NAME/ --recursive --acl public-read
  except:
  - master