Tags: gitlab-ci, devops, cicd, docker, pipelines, yaml
Level: intermediate
TL;DR: Configuration via .gitlab-ci.yml defining stages, jobs, and runner execution rules. Key focus on caching, artifacts, and multi-stage pipeline orchestration.
Configuration is declared declaratively in a root .gitlab-ci.yml file.
Pipelines consist of sequential stages containing independent, parallel jobs.
GitLab Runner executes jobs using executors like Docker, Shell, or Kubernetes.
cache persists dependencies across pipelines to speed up recurring execution.
artifacts pass build outputs between consecutive stages within a single pipeline.
rules determines conditional job execution based on branch, variables, or changes.
needs creates a Directed Acyclic Graph (DAG) skipping stage ordering.
Masked and protected CI/CD variables protect secrets and production credentials.
include modularizes configurations across files, templates, or remote repositories.
Environments enable deployments tracking, rollbacks, and dynamic review apps.
Q: What is the fundamental difference between cache and artifacts in GitLab CI?R: Artifacts transfer generated outputs across stages in the same pipeline. Cache speeds up future runs by reusing unchanged dependencies across distinct pipelines.
Q: How do you speed up a large pipeline with long sequential stages?R: I use the needs keyword to establish a DAG, allowing independent jobs to run immediately without waiting for entire stages to finish.
Q: How do you secure deployment keys or access tokens in CI/CD?R: I store them as masked, protected variables in the project settings and restrict deployment jobs strictly to protected branches or manual approvals.
Q: What happens if a job fails in a stage?R: The pipeline halts and subsequent stages are skipped, unless subsequent jobs define when: always or the failing job has allow_failure: true.
Q: How do you handle database migrations safely within a pipeline?R: I define a dedicated pre-deployment job with manual trigger or controlled execution, verifying idempotency and capturing logs as artifacts.
Confusing cache with artifacts and losing build outputs across stages.
Using only/except syntax instead of the modern and flexible rules clause.
Omitting predefined variable checks, causing jobs to trigger on unrelated branch pushes.
Storing unmasked secrets directly in YAML files instead of CI/CD settings.
Missing cache keys, leading to cache collisions across different branches.
Defining heavyweight Docker images with unneeded packages, slowing runner pull times.
```stages:
default:
image: node:20-alpine
cache:
key:
files:
paths:
build_job:
stage: build
script:
artifacts:
paths:
expire_in: 1 day
test_job:
stage: test
needs: ["build_job"]
script:
deploy_prod:
stage: deploy
script:
rules:
when: manual
environment:
name: production
url: https://example.com
```
[ ] DAG execution via needs versus standard stage sequencing
[ ] Proper usage of rules:changes with merge request pipelines
[ ] Differences between Docker-in-Docker (dind) and Kaniko for container builds
[ ] Optimization of cache hit rates across feature branches
GitLab CI/CD Pipeline Configuration Reference
GitLab Runner Executors Documentation