What Is GitLab CI/CD?
GitLab CI/CD is a built-in continuous integration and delivery platform that's part of GitLab β both the SaaS version at gitlab.com and self-hosted GitLab instances. Unlike GitHub Actions (which launched in 2019), GitLab has had CI/CD since 2015, making it one of the most mature pipeline systems available.
Everything is configured via a single file: .gitlab-ci.yml in the root of your repository. When you push a commit, GitLab reads this file and orchestrates the pipeline automatically β no external service, no webhook setup.
GitLab vs GitHub: GitLab is a complete DevOps platform β it includes source control, CI/CD, container registry, package registry, security scanning, and project management in one product. GitHub achieves similar coverage through integrations and Actions marketplace.
The .gitlab-ci.yml File
The .gitlab-ci.yml file defines your entire pipeline. A minimal working example:
image: node:20-alpine # default Docker image for all jobs stages: - test - build - deploy test:unit: stage: test script: - npm ci - npm test build:app: stage: build script: - npm ci - npm run build artifacts: paths: - dist/ deploy:production: stage: deploy script: - ./deploy.sh only: - main
Stages and Jobs
GitLab pipelines are organised into stages. All jobs in the same stage run in parallel. Stages run sequentially β the next stage only begins if all jobs in the previous stage pass.
A job is the basic unit of work. Each job defines:
stage:which stage it belongs toscript:the shell commands to runimage:the Docker image to use (can override the global default)rules:oronly:/except:to control when the job runsneeds:to create a directed acyclic graph (DAG) for parallel execution without waiting for full stages
DAG pipelines: The needs: keyword lets jobs start as soon as their specific dependencies complete, rather than waiting for an entire stage. For large pipelines this can dramatically reduce total pipeline time.
GitLab Runners
GitLab Runners are agents that pick up and execute jobs. GitLab.com provides shared runners (Linux, Windows, macOS) that are available for all projects. For self-hosted GitLab instances you must provide your own runners.
Runner types:
- Shared runners: Available to all projects in a GitLab instance. Good for most workloads.
- Group runners: Available to all projects within a group.
- Project-specific runners: Registered to a single project. Used for workloads that need specific hardware, environments, or security isolation.
Runners execute jobs in executors β the most common is the Docker executor, which spins up a container for each job using the specified image:. The Shell executor runs commands directly on the runner host, which is faster but less isolated.
Self-hosted runner security: Self-hosted runners that pick up jobs from public repositories are a supply chain risk. A malicious merge request could run arbitrary code on your runner. Always register separate runners for public repositories and never give them production credentials.
Artifacts and Caching
Artifacts are files generated by a job that you want to pass to later jobs or download after the pipeline. They're uploaded to GitLab at the end of the job and downloaded by jobs that depend on them.
Caching stores directories between pipeline runs to speed up dependency installation. Unlike artifacts, cache is not guaranteed to be available β it's a performance optimisation.
test:unit: stage: test cache: key: files: - package-lock.json paths: - node_modules/ script: - npm ci - npm test artifacts: reports: junit: junit.xml # shows test results in MR UI expire_in: 1 week
Environments and Deployments
GitLab tracks deployments through the environment: keyword. This creates a deployment history, enables rollbacks, and allows you to require manual approval before deploying to production:
deploy:staging: stage: deploy environment: name: staging url: https://staging.example.com script: ./deploy.sh staging deploy:production: stage: deploy environment: name: production url: https://example.com when: manual # requires manual click to deploy script: ./deploy.sh production only: - main
Variables and Secrets
GitLab CI/CD variables can be defined at the project, group, or instance level. Masked variables are hidden in job logs. Protected variables are only available to jobs running on protected branches or tags.
For secrets (API keys, tokens, passwords), use masked and protected CI/CD variables. Never commit them to .gitlab-ci.yml. Reference them as $VARIABLE_NAME in your scripts.
Variable inheritance risk: Group-level variables are inherited by all subgroups and projects. Review your group variable scope carefully β a token with broad permissions at the group level is exposed to every project in that group.
Real-World Pipeline Example
A complete pipeline for a Python web application with security scanning:
image: python:3.12-slim stages: - test - security - build - deploy test:pytest: stage: test cache: paths: [.venv/] script: - pip install -r requirements.txt - pytest --junitxml=report.xml artifacts: reports: junit: report.xml security:sast: stage: security image: aquilax/scanner:latest script: - aquilax scan --fail-on critical allow_failure: false # block pipeline on critical findings build:docker: stage: build image: docker:24 services: [docker:dind] script: - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA . - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
GitLab CI/CD vs GitHub Actions
- Configuration: GitLab uses a single
.gitlab-ci.yml; GitHub Actions uses multiple files in.github/workflows/ - Runners: GitLab requires runner registration; GitHub provides hosted runners automatically
- Security scanning: GitLab Ultimate includes built-in SAST, DAST, SCA, and secret detection; GitHub requires Actions or third-party tools
- Self-hosting: GitLab Community Edition is free and self-hostable; GitHub Enterprise requires a paid licence
- Marketplace: GitHub has a larger Actions marketplace; GitLab uses reusable CI/CD components and templates
Both are excellent: The right choice depends on your broader tooling. If you're all-in on GitHub for source control and project management, GitHub Actions is the natural choice. If you want a single integrated DevOps platform with built-in security, GitLab is hard to beat.
Add Security to Your GitLab Pipelines
AquilaX integrates with GitLab CI/CD to scan every commit for vulnerabilities, secrets, and misconfigurations β with AI-assisted fix suggestions delivered directly in your MRs.
Start Free Scan