Gitlab CI/CD Crash Course

Beginner’s guide for integrating test, build and deploy to your Gitlab workflow

Avicenna Wisesa
Sep 8, 2019 · 6 min read

Disclaimer: This post will require prior knowledge about Gitlab, Docker, Version Control System, and Software Development in general.

Courtesy of Gitlab

What is CI/CD?

Continuous Integration (CI) is a term usually used to describe an automated process within software development, where developers can make sure that what they’re adding to the software does not break whatever is currently working.

While CD, also known as Continuous Delivery or Continuous Deployment, takes CI a step further. It aims for automated delivery of new features for the customer, acceleration feedback loop.

I see CI/CD as a part of the DevOps culture as described by Martin Fowler. It automates testing and deployments, freeing people’s time to focus on other things. It also promotes stronger collaboration as developers have to stick with small code changes and sync up frequently with the rest of the team.

Gitlab CI/CD

Gitlab as a complete DevOps lifecycle application provides its users with an integrated CI/CD feature which is managed through a single file placed at the repository’s root.

In a nutshell, the users will put the CI/CD configuration in a file named and every time a code change is pushed to the Gitlab repository, Gitlab with run the configured CI/CD script.

Gitlab Runner

Scripts configured for Gitlab CI/CD will be executed by the Gitlab runner. Gitlab runner is an open-source project with various features on how to run the CI/CD script. Gitlab runner has several executor options such as SSH, Docker, and VirtualBox, to fit the users' needs.


Pipelines are the top-level component of continuous integration, delivery, and deployment. A pipeline will be created when a new push is made to the Gitlab repository. The pipeline will immediately run when there is an idle Gitlab runner or be put in a queue if all available runners are being used by someone else.

Courtesy of Gitlab

A pipeline will consist of jobs and stages.


Jobs is something that defines what will be run. Below is an example of file with one job named test. We also specify that the job will run with docker image. By default, when running a job Gitlab will spawn a docker container (image can be specified as shown below), clone your repository inside the container, and run the specified script.

image: "ruby:2.6.3"test:
- gem install bundler
- bundle install
- bundle exec rails spec

The pipeline of with CI configuration shown above will look like this:

Pipeline with only one job


Stages serve as categorization of jobs. It defines when and how a job will be run. By default, a pipeline will have three stages: build, test, and deploy. Having default stages does not mean the users have to create a job for each stages, for stages with no jobs will simply be ignored. Below we show a configuration with build and test stages:

image: "ruby:2.6.3"before_script:
- gem install bundler
- bundle install
- bundle exec rails spec
stage: build
- bundle package

If we don’t specify a stage in a job, Gitlab will automatically put it under stage. Here we specify two jobs, which will run on the test stage and which will run on the build stage. We also use which specify commands that we want to run before each job. The pipeline of the configuration above will look like this:

Using build and test stages

As mentioned previously, Gitlab will have , , and stage and the unused stage (in the current case is deploy) will be ignored.

Gitlab CI/CD also support the creation of custom stages

- test
- pre-build
- build
- deploy
stage: test
stage: pre-build
stage: build
stage: deploy

Above we tried to switch the default order of and stage and we added stage. The pipeline will look like this:

Pipeline with customized stage

Does it always run after each other? By default, the next stage will run after the previous one has succeeded. So when the previous failed, the next stage will not run. What if we want to allow some jobs to fail? Gitlab will allow the next stage to run if the failing job is specified with .

What if I want a job not being run automatically? For that, Gitlab provides the option to specify when to run the job. Quoting from the docs, the options provided are , , , and .

Syntax Error

If you’re new at this, you might get frustrated when editing your , pushing it to Gitlab and see that there is actually a syntax error in your configuration. Forcing you to add dirty commits just to fix the syntax error. To evade this I can suggest some methods:


Downloading packages may be a process that takes a long time within your pipeline. To make it faster you can cache the files so that you don’t have to redownload everything everytime you pipeline runs. Additional note on caching, don’t forget to clear the cache when you update some things you’re caching and don’t use cache to pass files between separate jobs (read the next section for more about this). Another way to address the problem is to create your own docker image tailored for your own needs.

You might want to use Gitlab CI/CD to automate packaging and deployment for your application. In doing this, you might encounter the need to pass files generated in one job to another job. To do this learn you should learn how to use artifacts.

When using at a larger scale (maybe deploying Gitlab for your institution/company) you might expect a queue if you don’t configure your runner wisely, look more into shared, specific, and group runner to address that.


Gitlab CI/CD getting started:
Gitlab CI/CD configuration docs:

Hope this helps!
For inquiries or anything else, feel free to reach me through mail or Twitter.

Follow us on Twitter 🐦 and Facebook 👥 and join our Facebook Group 💬.

To join our community Slack 🗣️ and read our weekly Faun topics 🗞️, click here⬇

If this post was helpful, please click the clap 👏 button below a few times to show your support for the author! ⬇


The Must-Read Publication for Aspiring Developers & DevOps Enthusiasts. Medium’s largest DevOps publication.

Avicenna Wisesa

Written by



The Must-Read Publication for Aspiring Developers & DevOps Enthusiasts. Medium’s largest DevOps publication.

More From Medium

More from Faun

More from Faun

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade