GitLab CI Variables
A CI variable is a named value that a pipeline job can read while it runs. Variables keep passwords, server addresses, and settings out of your scripts. One change in a settings page updates every job that uses the value.
Think of a hotel key card. The room number changes for each guest, but the door reader works the same way. A variable lets the same script run with different values in different places.
Three Sources of Variables
┌────────────────────────┐ ┌────────────────────────┐ ┌────────────────────────┐
│ PREDEFINED │ │ YAML FILE │ │ SETTINGS PAGE │
│ GitLab supplies them │ │ Written in │ │ Stored in the project │
│ CI_COMMIT_BRANCH │ │ .gitlab-ci.yml │ │ or group, encrypted │
│ CI_PROJECT_NAME │ │ Visible to everyone │ │ Hidden from logs │
└───────────┬────────────┘ └───────────┬────────────┘ └───────────┬────────────┘
└──────────────────┬─────────┴─────────────────────────────┘
▼
Job script reads $VARIABLE_NAME
Predefined Variables
GitLab creates these values for every job. No setup is needed.
| Variable | Holds | Sample Value |
|---|---|---|
| CI_COMMIT_BRANCH | Branch that triggered the pipeline | main |
| CI_COMMIT_SHA | Full commit identifier | a1b2c3d4... |
| CI_COMMIT_SHORT_SHA | First eight characters of the commit | a1b2c3d4 |
| CI_PROJECT_NAME | Project name | my-app |
| CI_PIPELINE_ID | Pipeline number | 1204 |
| CI_JOB_NAME | Name of the running job | run-tests |
| CI_DEFAULT_BRANCH | Default branch of the project | main |
print-info:
script:
- echo "Building $CI_PROJECT_NAME from $CI_COMMIT_BRANCH"
- echo "Commit $CI_COMMIT_SHORT_SHA in pipeline $CI_PIPELINE_ID"
Variables Written in the YAML File
Place variables at the top of the file for global scope or inside a job for local scope.
variables:
APP_ENV: "staging" # global: every job sees it
build-app:
variables:
BUILD_MODE: "fast" # local: only this job sees it
script:
- echo "Mode is $BUILD_MODE in $APP_ENV"
Anyone with repository access reads these values. Store only harmless settings in the file.
Variables in the Settings Page
- Open your project and select Settings → CI/CD.
- Expand the Variables section.
- Select Add variable.
- Type a key such as DEPLOY_TOKEN.
- Paste the value.
- Choose the visibility and protection options.
- Select Add variable to save.
Option Reference
| Option | Effect |
|---|---|
| Protect variable | Exposes the value only to protected branches and tags |
| Mask variable | Replaces the value with asterisks in job logs |
| Hidden visibility | Hides the value in the settings page after saving |
| Type: Variable | Passes the value as plain text |
| Type: File | Saves the value in a temporary file and passes the file path |
| Environment scope | Limits the value to one environment such as production |
A masked value needs at least eight characters on a single line. Longer secrets such as certificates fit the File type.
Scope by Environment
The same key can hold different values for different environments.
Key: DATABASE_URL Scope: staging → postgres://staging-db.example.com Scope: production → postgres://prod-db.example.com
A deploy job tied to the production environment receives the production value automatically.
Variable Priority
When two sources define the same key, the higher source wins.
1. Values typed during a manual pipeline run (highest) 2. Project settings variables 3. Group settings variables 4. Instance settings variables 5. Job-level variables in the YAML file 6. Global variables in the YAML file (lowest)
Use Variables in Rules
Rules read variables to decide whether a job runs.
deploy-production:
script:
- ./deploy.sh
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
Run a Pipeline with Custom Values
Open Build → Pipelines and select New pipeline. Add a key and value in the form. The pipeline starts with those values at the top of the priority list.
Security Habits
- Store passwords and tokens in the settings page.
- Mask every secret.
- Protect production secrets so feature branches cannot read them.
- Avoid printing variables with echo or env commands.
- Rotate a token the moment it appears in a log.
Debug a Missing Variable
| Symptom | Likely Cause |
|---|---|
| Value is empty on a feature branch | The variable is protected |
| Value shows asterisks in the log | The mask is working as designed |
| Wrong value in production | Another source with higher priority overrides it |
| Dollar sign inside the value disappears | Variable expansion is active; turn off expansion for that key |
