Comprehensive toolkit for validating, linting, testing, and securing GitLab CI/CD pipeline configurations. Use this skill when working with GitLab CI/CD pipelines, validating pipeline syntax, debugging configuration issues, or implementing best practices.
Overall
score
100%
Does it follow best practices?
Validation for skill structure
GitLab CI/CD pipelines are defined in .gitlab-ci.yml files using YAML syntax. The file must be located at the root of your repository. The order of keywords is not important unless otherwise specified.
# Global configuration
default:
# Default settings for all jobs
include:
# Import external configurations
stages:
# Define pipeline stages
variables:
# Global variables
workflow:
# Pipeline execution rules
# Job definitions
job_name:
stage: stage_name
script:
- command1
- command2defaultEstablishes custom default values that are copied to jobs lacking specific keyword definitions.
Supported keywords:
image, services, before_script, after_scriptcache, artifacts, retry, timeout, interruptibletags, hooksExample:
default:
image: ruby:3.0
retry: 2
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- vendor/includeImports configuration from external YAML files.
Types:
local: Files in same repositoryproject: Files from other GitLab projectsremote: Files from external URLstemplate: GitLab-provided templatescomponent: CI/CD catalog componentsExample:
include:
- local: '/templates/.gitlab-ci-template.yml'
- template: 'Auto-DevOps.gitlab-ci.yml'
- project: 'my-group/my-project'
file: '/templates/.gitlab-ci.yml'
- remote: 'https://example.com/.gitlab-ci.yml'
- component: $CI_SERVER_FQDN/my-org/security/secret-detection@1.0stagesDefines the names and order of pipeline stages. Jobs in the same stage run in parallel.
Default stages (if not defined):
.prebuildtestdeploy.postExample:
stages:
- build
- test
- deploy
- cleanupvariablesSets CI/CD variables available to all jobs or specific jobs.
Example:
variables:
DATABASE_URL: "postgres://postgres@postgres/db"
DEPLOY_NOTE:
description: "The deployment note"
value: "Default deployment"
job_name:
variables:
DEPLOY_ENV: "production"workflowControls pipeline behavior and creation rules.
Example:
workflow:
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'scriptThe only required keyword. Defines shell commands executed by the runner.
Syntax:
job_name:
script: "single command"
# OR multi-line
job_name:
script:
- command1
- command2
- |
multi-line
command blockbefore_scriptCommands running before the script section.
Example:
job_name:
before_script:
- echo "Preparing environment"
- bundle install
script:
- bundle exec rspecafter_scriptCommands running after script completion. Executes in a separate shell context.
Example:
job_name:
script:
- ./deploy.sh
after_script:
- ./cleanup.shstageAssigns the job to a specific pipeline stage.
Example:
build_job:
stage: build
script:
- make buildwhenControls when jobs run.
Values:
on_success (default): Run when all previous jobs succeedon_failure: Run when at least one previous job failsalways: Always runmanual: Require manual actiondelayed: Delay job executionnever: Never runExample:
cleanup_job:
stage: cleanup
script:
- ./cleanup.sh
when: always
deploy_job:
stage: deploy
script:
- ./deploy.sh
when: manualartifactsSpecifies files and directories to save after job completion.
Sub-keywords:
paths: File locations to includeexclude: Patterns to excludeexpire_in: Retention duration (default: 30 days)name: Archive namewhen: Upload condition (on_success, on_failure, always)reports: Collect test/coverage/security reportsExample:
test_job:
script:
- npm test
artifacts:
paths:
- coverage/
- dist/
exclude:
- coverage/**/*.tmp
expire_in: 1 week
reports:
junit: test-results.xml
coverage_report:
coverage_format: cobertura
path: coverage/cobertura.xmlcacheDefines files cached between job runs for faster execution.
Sub-keywords:
paths: Items to cachekey: Cache identifierpolicy: Download/upload behavior (pull, push, pull-push)when: Cache condition (on_success, on_failure, always)untracked: Cache untracked filesExample:
build_job:
script:
- npm install
- npm run build
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
- .npm/
policy: pull-push
test_job:
script:
- npm test
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
policy: pulldependenciesRestricts artifact downloads to specified jobs only.
Example:
build_job:
stage: build
script:
- make build
artifacts:
paths:
- binaries/
test_job:
stage: test
script:
- ./test.sh
dependencies:
- build_jobneedsExecutes jobs earlier than stage ordering permits, creating a directed acyclic graph (DAG).
Example:
build_job:
stage: build
script:
- make build
test_job:
stage: test
script:
- make test
needs:
- build_job
deploy_job:
stage: deploy
script:
- make deploy
needs:
- test_jobrulesDetermines job creation based on conditions. Replaces only/except.
Example:
deploy_job:
script:
- echo "Deploy to production"
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: manual
- if: '$CI_COMMIT_BRANCH == "staging"'
when: on_success
- when: never
test_job:
script:
- npm test
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
- changes:
- src/**/*.js
- test/**/*.jsallow_failurePermits job failure without stopping the pipeline.
Example:
experimental_test:
script:
- experimental_command
allow_failure: true
# With exit codes
integration_test:
script:
- ./integration_tests.sh
allow_failure:
exit_codes: [137, 255]environmentSpecifies deployment target environment.
Sub-keywords:
name: Environment nameurl: Environment URLon_stop: Job to stop environmentauto_stop_in: Auto-stop durationaction: Deployment action (start, prepare, stop)Example:
deploy_staging:
stage: deploy
script:
- ./deploy.sh staging
environment:
name: staging
url: https://staging.example.com
on_stop: stop_staging
auto_stop_in: 1 day
deploy_review:
stage: deploy
script:
- ./deploy.sh review
environment:
name: review/$CI_COMMIT_REF_SLUG
url: https://$CI_ENVIRONMENT_SLUG.example.com
on_stop: stop_review
auto_stop_in: 1 week
stop_review:
stage: deploy
script:
- ./stop_review.sh
environment:
name: review/$CI_COMMIT_REF_SLUG
action: stop
when: manualimageSpecifies Docker container image for job execution.
Example:
test_job:
image: node:18-alpine
script:
- npm test
# With specific digest (recommended for security)
secure_job:
image: node@sha256:abc123...
script:
- npm run secure-testservicesDefines Docker service images (databases, cache servers, etc.).
Example:
integration_test:
image: node:18
services:
- name: postgres:14
alias: postgres
- name: redis:7-alpine
alias: cache
variables:
POSTGRES_DB: testdb
POSTGRES_USER: test
POSTGRES_PASSWORD: test
script:
- npm run integration-testtagsSelects runners by labels.
Example:
build_job:
tags:
- docker
- linux
deploy_job:
tags:
- kubernetes
- productiontimeoutSets job-level timeout, overriding project settings.
Example:
long_running_job:
script:
- ./long_process.sh
timeout: 3hresource_groupLimits job concurrency within a resource group.
Example:
deploy_production:
script:
- ./deploy.sh
resource_group: productionparallelRuns multiple job instances in parallel.
Example:
test_job:
script:
- npm test
parallel: 5
# With matrix
test_matrix:
script:
- bundle exec rspec
parallel:
matrix:
- RUBY_VERSION: ['2.7', '3.0', '3.1']
DATABASE: ['postgres', 'mysql']interruptibleAllows job cancellation when made redundant by newer runs.
Example:
test_job:
script:
- npm test
interruptible: trueextendsInherits configuration from other jobs or templates.
Example:
.default_retry:
retry:
max: 2
when:
- runner_system_failure
- stuck_or_timeout_failure
test_job:
extends: .default_retry
script:
- npm testretryAuto-retry configuration on failure.
Example:
test_job:
script:
- flaky_test.sh
retry:
max: 2
when:
- runner_system_failure
- stuck_or_timeout_failure
- unknown_failurecoverageExtracts code coverage metrics via regex.
Example:
test_job:
script:
- npm test
coverage: '/Coverage: \d+\.\d+/'secretsSpecifies required CI/CD secrets from external providers.
Example:
deploy_job:
script:
- ./deploy.sh
secrets:
DATABASE_PASSWORD:
vault: production/db/password@ops
file: false
API_KEY:
vault: production/api/key@opstriggerDefines downstream pipeline triggers.
Example:
trigger_downstream:
stage: deploy
trigger:
project: my-group/downstream-project
branch: mainreleaseGenerates release objects.
Example:
release_job:
stage: release
script:
- echo "Creating release"
release:
tag_name: '$CI_COMMIT_TAG'
name: 'Release $CI_COMMIT_TAG'
description: 'Release notes here'Common CI/CD variables available in all pipelines:
CI_COMMIT_BRANCH: Current branch nameCI_COMMIT_SHA: Current commit SHACI_COMMIT_REF_NAME: Branch or tag nameCI_COMMIT_REF_SLUG: Lowercased, shortened to 63 bytesCI_COMMIT_TAG: Commit tag nameCI_DEFAULT_BRANCH: Default branch nameCI_ENVIRONMENT_NAME: Environment nameCI_ENVIRONMENT_SLUG: Simplified environment nameCI_JOB_ID: Job IDCI_JOB_NAME: Job nameCI_JOB_STAGE: Job stageCI_PIPELINE_ID: Pipeline IDCI_PIPELINE_SOURCE: Pipeline trigger sourceCI_PROJECT_DIR: Repository clone directoryCI_PROJECT_ID: Project IDCI_PROJECT_NAME: Project nameCI_PROJECT_PATH: Project pathCI_PROJECT_URL: Project URLCI_REGISTRY: GitLab container registry URLCI_REGISTRY_IMAGE: Container registry image pathCI_RUNNER_ID: Runner IDCI_SERVER_URL: GitLab instance URLThe following keywords cannot be used as job names:
imageservicesstagestypesbefore_scriptafter_scriptvariablescacheincludepagesdefaultworkflowUse the GitLab CI Lint tool to validate your configuration:
/api/v4/ci/lint.default_cache: &default_cache
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
build_job:
<<: *default_cache
script:
- npm install
- npm run build.deploy_template:
script:
- ./deploy.sh
only:
- main
deploy_staging:
extends: .deploy_template
environment:
name: staging
deploy_production:
extends: .deploy_template
environment:
name: production
when: manualrules instead of only/except: More flexible and powerfulneeds for DAG pipelines: Faster executioninterruptible: Save resources on redundant jobsallow_failure appropriatelyInstall with Tessl CLI
npx tessl i pantheon-ai/gitlab-ci-validator@0.1.0