Understanding GitLab CI/CD Variables for pipelines
GitLab CI/CD uses various types of variables to make pipelines dynamic, adaptable, and secure. Variables can store values such as paths, URLs, or secret credentials. You can create more flexible and reusable pipelines by utilizing predefined, global, and local variables. In this article, we will explore different types of GitLab CI/CD variables, how they are defined, and their use cases in a typical pipeline.
1. Global Variables
Global variables are defined at the top level of the .gitlab-ci.yml
file and are accessible throughout the entire pipeline, across all stages and jobs. These variables can store common values that need to be used in multiple jobs, ensuring consistency and reducing redundancy.
Example:
variables:
GLOBAL_VARIABLE: "This is a global variable"
COMMON_URL: "https://example.com"
- GLOBAL_VARIABLE: This variable is available across all stages and jobs.
- COMMON_URL: A URL that could be used across different jobs, for instance, for making API requests.
2. Predefined Variables
GitLab CI provides a rich set of predefined variables that give information about the pipeline, project, or job. These variables are automatically set and can be accessed directly in the pipeline.
Example:
test-variables:
stage: predefined-variables
script:
- echo "CI_COMMIT_SHA=$CI_COMMIT_SHA"
- echo "CI_JOB_ID=$CI_JOB_ID"
- echo "CI_PROJECT_NAME=$CI_PROJECT_NAME"
Some commonly used predefined variables:
- CI_COMMIT_SHA: The commit hash of the current commit.
- CI_JOB_ID: The unique ID of the current job.
- CI_PROJECT_NAME: The name of the project.
Predefined variables are useful for retrieving metadata about the pipeline without manually defining them. They can be used in scripts, logging, or reporting.
3. Merge Request Variables
When a pipeline runs in response to a merge request (MR), special variables are available to give information about the MR itself. These variables allow access to MR-specific data, such as the branch names, project IDs, and labels.
Example:
print-ci-merge-request-variables:
stage: merge-request-variables
script:
- echo "CI_MERGE_REQUEST_ID=$CI_MERGE_REQUEST_ID"
- echo "CI_MERGE_REQUEST_TITLE=$CI_MERGE_REQUEST_TITLE
Common merge request variables include:
- CI_MERGE_REQUEST_ID: The ID of the merge request.
- CI_MERGE_REQUEST_TITLE: The title of the merge request.
These variables can be handy when you want to customize your pipeline behavior based on the context of the merge request.
4. Local Variables (Job-Specific Variables)
Local variables are defined at the job level and are only available within that specific job. This allows for customizing job behavior without affecting the entire pipeline.
Example:
test-job:
stage: test
script:
- echo "Global Variable= $GLOBAL_VARIABLE"
- echo "Local Variable= $LOCAL_VARIABLE"
variables:
LOCAL_VARIABLE: "This is a local variable for test-job"
In this example:
- LOCAL_VARIABLE is defined only for the
test-job
and is not accessible in other jobs. - GLOBAL_VARIABLE, however, is accessible because it was defined at the global level.
5. Environment-Specific Variables (Job-Specific)
You can define variables that are specific to certain environments, such as deployment environments. This is useful when you want to tailor your job for a specific environment, for example, using different URLs for staging and production.
Example:
deploy-job:
stage: deploy
script:
- echo "Deploy-specific Variable= $DEPLOY_URL"
variables:
DEPLOY_URL: "https://deploy.example.com"
Here, DEPLOY_URL is specific to the deploy-job
and can contain deployment-related URLs or credentials.
6. Variable Precedence
GitLab CI/CD variables have a clear precedence order, which dictates which variable value will be used if there are conflicts. From highest to lowest priority:
- Trigger variables: Variables passed when triggering a pipeline.
- Pipeline variables: Variables defined when running a pipeline manually.
- Job-specific variables: Variables defined at the job level.
- Global variables: Variables defined at the top level in
.gitlab-ci.yml
. - Environment variables: Variables defined in GitLab project settings or in the group.
- Predefined variables: Automatically provided by GitLab.
Here is the data which I have tested with the gitlab job to validate most of the variables
variables:
GLOBAL_VARIABLE: "This is a global variable"
COMMON_URL: "https://example.com"
stages:
- predefined-variables
- merge-request-variables
- test
- deploy
test-variables:
stage: predefined-variables
script:
- echo "CHAT_CHANNEL=$CHAT_CHANNEL"
- echo "CHAT_INPUT=$CHAT_INPUT"
- echo "CHAT_USER_ID=$CHAT_USER_ID"
- echo "CI=$CI"
- echo "CI_API_V4_URL=$CI_API_V4_URL"
- echo "CI_API_GRAPHQL_URL=$CI_API_GRAPHQL_URL"
- echo "CI_BUILDS_DIR=$CI_BUILDS_DIR"
- echo "CI_COMMIT_AUTHOR=$CI_COMMIT_AUTHOR"
- echo "CI_COMMIT_BEFORE_SHA=$CI_COMMIT_BEFORE_SHA"
- echo "CI_COMMIT_BRANCH=$CI_COMMIT_BRANCH"
- echo "CI_COMMIT_DESCRIPTION=$CI_COMMIT_DESCRIPTION"
- echo "CI_COMMIT_MESSAGE=$CI_COMMIT_MESSAGE"
- echo "CI_COMMIT_REF_NAME=$CI_COMMIT_REF_NAME"
- echo "CI_COMMIT_REF_PROTECTED=$CI_COMMIT_REF_PROTECTED"
- echo "CI_COMMIT_REF_SLUG=$CI_COMMIT_REF_SLUG"
- echo "CI_COMMIT_SHA=$CI_COMMIT_SHA"
- echo "CI_COMMIT_SHORT_SHA=$CI_COMMIT_SHORT_SHA"
- echo "CI_COMMIT_TAG=$CI_COMMIT_TAG"
- echo "CI_COMMIT_TAG_MESSAGE=$CI_COMMIT_TAG_MESSAGE"
- echo "CI_COMMIT_TIMESTAMP=$CI_COMMIT_TIMESTAMP"
- echo "CI_COMMIT_TITLE=$CI_COMMIT_TITLE"
- echo "CI_CONCURRENT_ID=$CI_CONCURRENT_ID"
- echo "CI_CONCURRENT_PROJECT_ID=$CI_CONCURRENT_PROJECT_ID"
- echo "CI_CONFIG_PATH=$CI_CONFIG_PATH"
- echo "CI_DEBUG_TRACE=$CI_DEBUG_TRACE"
- echo "CI_DEBUG_SERVICES=$CI_DEBUG_SERVICES"
- echo "CI_DEFAULT_BRANCH=$CI_DEFAULT_BRANCH"
- echo "CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX=$CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX"
- echo "CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX=$CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX"
- echo "CI_DEPENDENCY_PROXY_PASSWORD=$CI_DEPENDENCY_PROXY_PASSWORD"
- echo "CI_DEPENDENCY_PROXY_SERVER=$CI_DEPENDENCY_PROXY_SERVER"
- echo "CI_DEPENDENCY_PROXY_USER=$CI_DEPENDENCY_PROXY_USER"
- echo "CI_DEPLOY_FREEZE=$CI_DEPLOY_FREEZE"
- echo "CI_DEPLOY_PASSWORD=$CI_DEPLOY_PASSWORD"
- echo "CI_DEPLOY_USER=$CI_DEPLOY_USER"
- echo "CI_DISPOSABLE_ENVIRONMENT=$CI_DISPOSABLE_ENVIRONMENT"
- echo "CI_ENVIRONMENT_NAME=$CI_ENVIRONMENT_NAME"
- echo "CI_ENVIRONMENT_SLUG=$CI_ENVIRONMENT_SLUG"
- echo "CI_ENVIRONMENT_URL=$CI_ENVIRONMENT_URL"
- echo "CI_ENVIRONMENT_ACTION=$CI_ENVIRONMENT_ACTION"
- echo "CI_ENVIRONMENT_TIER=$CI_ENVIRONMENT_TIER"
- echo "CI_GITLAB_FIPS_MODE=$CI_GITLAB_FIPS_MODE"
- echo "CI_HAS_OPEN_REQUIREMENTS=$CI_HAS_OPEN_REQUIREMENTS"
- echo "CI_JOB_ID=$CI_JOB_ID"
- echo "CI_JOB_IMAGE=$CI_JOB_IMAGE"
- echo "CI_JOB_JWT=$CI_JOB_JWT"
- echo "CI_JOB_JWT_V1=$CI_JOB_JWT_V1"
- echo "CI_JOB_JWT_V2=$CI_JOB_JWT_V2"
- echo "CI_JOB_MANUAL=$CI_JOB_MANUAL"
- echo "CI_JOB_NAME=$CI_JOB_NAME"
- echo "CI_JOB_NAME_SLUG=$CI_JOB_NAME_SLUG"
- echo "CI_JOB_STAGE=$CI_JOB_STAGE"
- echo "CI_JOB_STATUS=$CI_JOB_STATUS"
- echo "CI_JOB_TIMEOUT=$CI_JOB_TIMEOUT"
- echo "CI_JOB_TOKEN=$CI_JOB_TOKEN"
- echo "CI_JOB_URL=$CI_JOB_URL"
- echo "CI_JOB_STARTED_AT=$CI_JOB_STARTED_AT"
- echo "CI_KUBERNETES_ACTIVE=$CI_KUBERNETES_ACTIVE"
- echo "CI_NODE_INDEX=$CI_NODE_INDEX"
- echo "CI_NODE_TOTAL=$CI_NODE_TOTAL"
- echo "CI_OPEN_MERGE_REQUESTS=$CI_OPEN_MERGE_REQUESTS"
- echo "CI_PAGES_DOMAIN=$CI_PAGES_DOMAIN"
- echo "CI_PAGES_URL=$CI_PAGES_URL"
- echo "CI_PIPELINE_ID=$CI_PIPELINE_ID"
- echo "CI_PIPELINE_IID=$CI_PIPELINE_IID"
- echo "CI_PIPELINE_SOURCE=$CI_PIPELINE_SOURCE"
- echo "CI_PIPELINE_TRIGGERED=$CI_PIPELINE_TRIGGERED"
- echo "CI_PIPELINE_URL=$CI_PIPELINE_URL"
- echo "CI_PIPELINE_CREATED_AT=$CI_PIPELINE_CREATED_AT"
- echo "CI_PIPELINE_NAME=$CI_PIPELINE_NAME"
- echo "CI_PROJECT_DIR=$CI_PROJECT_DIR"
- echo "CI_PROJECT_ID=$CI_PROJECT_ID"
- echo "CI_PROJECT_NAME=$CI_PROJECT_NAME"
- echo "CI_PROJECT_NAMESPACE=$CI_PROJECT_NAMESPACE"
- echo "CI_PROJECT_NAMESPACE_ID=$CI_PROJECT_NAMESPACE_ID"
- echo "CI_PROJECT_PATH_SLUG=$CI_PROJECT_PATH_SLUG"
- echo "CI_PROJECT_PATH=$CI_PROJECT_PATH"
- echo "CI_PROJECT_REPOSITORY_LANGUAGES=$CI_PROJECT_REPOSITORY_LANGUAGES"
- echo "CI_PROJECT_ROOT_NAMESPACE=$CI_PROJECT_ROOT_NAMESPACE"
- echo "CI_PROJECT_TITLE=$CI_PROJECT_TITLE"
- echo "CI_PROJECT_DESCRIPTION=$CI_PROJECT_DESCRIPTION"
- echo "CI_PROJECT_URL=$CI_PROJECT_URL"
- echo "CI_PROJECT_VISIBILITY=$CI_PROJECT_VISIBILITY"
- echo "CI_PROJECT_CLASSIFICATION_LABEL=$CI_PROJECT_CLASSIFICATION_LABEL"
- echo "CI_REGISTRY=$CI_REGISTRY"
- echo "CI_REGISTRY_IMAGE=$CI_REGISTRY_IMAGE"
- echo "CI_REGISTRY_PASSWORD=$CI_REGISTRY_PASSWORD"
- echo "CI_REGISTRY_USER=$CI_REGISTRY_USER"
- echo "CI_RELEASE_DESCRIPTION=$CI_RELEASE_DESCRIPTION"
- echo "CI_REPOSITORY_URL=$CI_REPOSITORY_URL"
- echo "CI_RUNNER_DESCRIPTION=$CI_RUNNER_DESCRIPTION"
- echo "CI_RUNNER_EXECUTABLE_ARCH=$CI_RUNNER_EXECUTABLE_ARCH"
- echo "CI_RUNNER_ID=$CI_RUNNER_ID"
- echo "CI_RUNNER_REVISION=$CI_RUNNER_REVISION"
- echo "CI_RUNNER_SHORT_TOKEN=$CI_RUNNER_SHORT_TOKEN"
- echo "CI_RUNNER_TAGS=$CI_RUNNER_TAGS"
- echo "CI_RUNNER_VERSION=$CI_RUNNER_VERSION"
- echo "CI_SERVER_FQDN=$CI_SERVER_FQDN"
- echo "CI_SERVER_HOST=$CI_SERVER_HOST"
- echo "CI_SERVER_NAME=$CI_SERVER_NAME"
- echo "CI_SERVER_PORT=$CI_SERVER_PORT"
- echo "CI_SERVER_PROTOCOL=$CI_SERVER_PROTOCOL"
- echo "CI_SERVER_SHELL_SSH_HOST=$CI_SERVER_SHELL_SSH_HOST"
- echo "CI_SERVER_SHELL_SSH_PORT=$CI_SERVER_SHELL_SSH_PORT"
- echo "CI_SERVER_REVISION=$CI_SERVER_REVISION"
- echo "CI_SERVER_TLS_CA_FILE=$CI_SERVER_TLS_CA_FILE"
- echo "CI_SERVER_TLS_CERT_FILE=$CI_SERVER_TLS_CERT_FILE"
- echo "CI_SERVER_TLS_KEY_FILE=$CI_SERVER_TLS_KEY_FILE"
- echo "CI_SERVER_URL=$CI_SERVER_URL"
- echo "CI_SERVER_VERSION_MAJOR=$CI_SERVER_VERSION_MAJOR"
- echo "CI_SERVER_VERSION_MINOR=$CI_SERVER_VERSION_MINOR"
- echo "CI_SERVER_VERSION_PATCH=$CI_SERVER_VERSION_PATCH"
- echo "CI_SERVER_VERSION=$CI_SERVER_VERSION"
- echo "CI_SERVER=$CI_SERVER"
- echo "CI_SHARED_ENVIRONMENT=$CI_SHARED_ENVIRONMENT"
- echo "CI_TEMPLATE_REGISTRY_HOST=$CI_TEMPLATE_REGISTRY_HOST"
- echo "CI_TRIGGER_SHORT_TOKEN=$CI_TRIGGER_SHORT_TOKEN"
- echo "GITLAB_CI=$GITLAB_CI"
- echo "GITLAB_FEATURES=$GITLAB_FEATURES"
- echo "GITLAB_USER_EMAIL=$GITLAB_USER_EMAIL"
- echo "GITLAB_USER_ID=$GITLAB_USER_ID"
- echo "GITLAB_USER_LOGIN=$GITLAB_USER_LOGIN"
print-ci-merge-request-variables:
stage: merge-request-variables
script:
- echo "CI_MERGE_REQUEST_APPROVED= $CI_MERGE_REQUEST_APPROVED"
- echo "CI_MERGE_REQUEST_ASSIGNEES= $CI_MERGE_REQUEST_ASSIGNEES"
- echo "CI_MERGE_REQUEST_DIFF_BASE_SHA= $CI_MERGE_REQUEST_DIFF_BASE_SHA"
- echo "CI_MERGE_REQUEST_DIFF_ID= $CI_MERGE_REQUEST_DIFF_ID"
- echo "CI_MERGE_REQUEST_EVENT_TYPE= $CI_MERGE_REQUEST_EVENT_TYPE"
- echo "CI_MERGE_REQUEST_DESCRIPTION= $CI_MERGE_REQUEST_DESCRIPTION"
- echo "CI_MERGE_REQUEST_DESCRIPTION_IS_TRUNCATED= $CI_MERGE_REQUEST_DESCRIPTION_IS_TRUNCATED"
- echo "CI_MERGE_REQUEST_ID= $CI_MERGE_REQUEST_ID"
- echo "CI_MERGE_REQUEST_IID= $CI_MERGE_REQUEST_IID"
- echo "CI_MERGE_REQUEST_LABELS= $CI_MERGE_REQUEST_LABELS"
- echo "CI_MERGE_REQUEST_MILESTONE= $CI_MERGE_REQUEST_MILESTONE"
- echo "CI_MERGE_REQUEST_PROJECT_ID= $CI_MERGE_REQUEST_PROJECT_ID"
- echo "CI_MERGE_REQUEST_PROJECT_PATH= $CI_MERGE_REQUEST_PROJECT_PATH"
- echo "CI_MERGE_REQUEST_PROJECT_URL= $CI_MERGE_REQUEST_PROJECT_URL"
- echo "CI_MERGE_REQUEST_REF_PATH= $CI_MERGE_REQUEST_REF_PATH"
- echo "CI_MERGE_REQUEST_SOURCE_BRANCH_NAME= $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME"
- echo "CI_MERGE_REQUEST_SOURCE_BRANCH_PROTECTED= $CI_MERGE_REQUEST_SOURCE_BRANCH_PROTECTED"
- echo "CI_MERGE_REQUEST_SOURCE_BRANCH_SHA= $CI_MERGE_REQUEST_SOURCE_BRANCH_SHA"
- echo "CI_MERGE_REQUEST_SOURCE_PROJECT_ID= $CI_MERGE_REQUEST_SOURCE_PROJECT_ID"
- echo "CI_MERGE_REQUEST_SOURCE_PROJECT_PATH= $CI_MERGE_REQUEST_SOURCE_PROJECT_PATH"
- echo "CI_MERGE_REQUEST_SOURCE_PROJECT_URL= $CI_MERGE_REQUEST_SOURCE_PROJECT_URL"
- echo "CI_MERGE_REQUEST_SQUASH_ON_MERGE= $CI_MERGE_REQUEST_SQUASH_ON_MERGE"
- echo "CI_MERGE_REQUEST_TARGET_BRANCH_NAME= $CI_MERGE_REQUEST_TARGET_BRANCH_NAME"
- echo "CI_MERGE_REQUEST_TARGET_BRANCH_PROTECTED= $CI_MERGE_REQUEST_TARGET_BRANCH_PROTECTED"
- echo "CI_MERGE_REQUEST_TARGET_BRANCH_SHA= $CI_MERGE_REQUEST_TARGET_BRANCH_SHA"
- echo "CI_MERGE_REQUEST_TITLE= $CI_MERGE_REQUEST_TITLE"
test-job:
stage: test
script:
- echo "Global Variable= $GLOBAL_VARIABLE"
- echo "Common URL= $COMMON_URL"
- echo "Local Variable= $LOCAL_VARIABLE"
variables:
LOCAL_VARIABLE: "This is a local variable for test-job"
TEST_URL: "https://test.example.com"
deploy-job:
stage: deploy
script:
- echo "Global Variable= $GLOBAL_VARIABLE"
- echo "Common URL= $COMMON_URL"
- echo "Deploy-specific Variable= $DEPLOY_URL"
variables:
DEPLOY_URL: "https://deploy.example.com"
Conclusion
Using different types of GitLab CI variables enables you to create more dynamic, reusable, and flexible pipelines. By combining global variables for consistency, job-specific variables for custom behavior, and predefined or merge request variables for environment-specific tasks, you can ensure that your pipeline runs smoothly across different scenarios.
Understanding the various types of variables and how to use them effectively is key to mastering GitLab CI/CD and creating scalable, efficient pipelines.
I have created a project on Gitlab and added the code here.
Feel free to hit clap if you like the content. Happy Automation Testing :) Cheers. 👏