This guide covers GitLab CI/CD fundamentals using the .gitlab-ci.yml file. You'll learn how to define jobs, organize them into stages, use variables for configuration, and manage artifacts between jobs. By the end, you can create robust pipelines that build, test, and deploy your applications automatically.
What you'll learn
- Architecture — visual overview of pipeline flow and components.
- Jobs — individual tasks that run scripts and commands.
- Stages — organizing jobs into logical groups.
- Variables — dynamic configuration and secrets.
- Artifacts — passing files between jobs.
- Real examples — Node.js, Python, and Docker pipelines.
GitLab CI/CD Architecture
The diagram below shows the component architecture of GitLab CI/CD concepts and how they relate to each other:
Component relationships visualized:
- Pipeline contains Stages, which contain Jobs
- Jobs use Variables, Images, Rules, and Scripts
- Variables are available to all Script Commands
- Artifacts are created by Jobs and passed to other Jobs
- Cache is shared across Jobs for performance
- Rules control when Jobs execute
Jobs
Definition: A job is the smallest unit of work in GitLab CI/CD. It defines what to run (script), when to run (rules), and where to run (image/runner).
Why it matters: Jobs are the building blocks of your pipeline. Each job runs independently and can succeed or fail on its own.
Basic job structure
job_name:
script:
- echo "Hello, GitLab CI!"
- npm install
- npm test
image: node:16
stage: test
Common job keywords
script
: Commands to execute (required)image
: Docker image to usestage
: Which stage this job belongs torules
: When to run this jobartifacts
: Files to save for other jobsdependencies
: Which artifacts to download
Stages
Definition: Stages group jobs that run in parallel. Jobs in the same stage run simultaneously, while stages run sequentially.
Why it matters: Stages help organize your pipeline logically (build → test → deploy) and control execution flow.
Default stages
build
: Compile, package, or prepare your applicationtest
: Run unit tests, integration tests, lintingdeploy
: Deploy to staging, production, or other environments
Custom stages example
stages:
- build
- test
- security
- deploy
build_app:
stage: build
script:
- npm install
- npm run build
unit_tests:
stage: test
script:
- npm test
security_scan:
stage: security
script:
- npm audit
Variables
Definition: Variables store dynamic values used across your pipeline. They can be predefined, custom, or secret.
Why it matters: Variables make pipelines flexible and reusable. Use them for configuration, secrets, and environment-specific values.
Types of variables
- Predefined:
CI_COMMIT_SHA
,CI_PROJECT_NAME
,CI_PIPELINE_ID
- Custom: Defined in .gitlab-ci.yml or project settings
- Secret: Masked variables for passwords, API keys
- Group: Shared across all projects in a group
Using variables
variables:
NODE_VERSION: "16"
BUILD_DIR: "dist"
build:
script:
- echo "Building version $CI_COMMIT_SHA"
- npm run build -- --output-dir $BUILD_DIR
- echo "Build completed for $CI_PROJECT_NAME"
Tip: Use $
for variables in scripts, $$
to escape a literal $
.
Artifacts
Definition: Artifacts are files created by jobs that can be passed to other jobs or downloaded after pipeline completion.
Why it matters: Artifacts enable job dependencies. Build once, test multiple times, deploy the same artifact.
Basic artifacts
build:
script:
- npm run build
artifacts:
paths:
- dist/
expire_in: 1 week
test:
script:
- npm test
dependencies:
- build # Downloads artifacts from build job
Advanced artifacts
build:
script:
- npm run build
artifacts:
paths:
- dist/
- coverage/
reports:
junit: test-results.xml
coverage: coverage/cobertura-coverage.xml
expire_in: 1 week
when: always # Save even if job fails
Real Examples
Node.js Pipeline
stages:
- install
- test
- build
- deploy
variables:
NODE_VERSION: "16"
install_dependencies:
stage: install
image: node:${NODE_VERSION}
script:
- npm ci --cache .npm --prefer-offline
cache:
paths:
- .npm/
- node_modules/
unit_tests:
stage: test
image: node:${NODE_VERSION}
script:
- npm test
coverage: '/Lines\s*:\s*(\d+\.\d+)%/'
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xml
build_app:
stage: build
image: node:${NODE_VERSION}
script:
- npm run build
artifacts:
paths:
- dist/
expire_in: 1 week
deploy_staging:
stage: deploy
image: alpine:latest
script:
- echo "Deploying to staging..."
- # Add your deployment commands here
only:
- develop
Docker Pipeline
build_image:
stage: build
image: docker:latest
services:
- docker:dind
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
only:
- main
deploy_production:
stage: deploy
image: alpine:latest
script:
- echo "Deploying $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA to production"
only:
- main
Next Steps
- Set up Runners & Executors for different environments.
- Configure Pipeline Triggers & Schedules for automation.
- Enable Security Scanning in your pipelines.
Consider using include to reuse pipeline templates across projects.
0 Comments