Graphic showing the GitLab logo, a stylised fox head

GitLab CI’s Variables system lets you inject data into your CI job environments. You can use variables to supply config values, create reusable pipelines, and avoid hardcoding sensitive information into your .gitlab-ci.yml files.

In this guide we’ll look at how you can set and use variables within your own CI system. There are several options available depending on where you want values to be surfaced and how regularly you’ll want to change them.

The Basics

At their simplest variables are key-value pairs which are injected as environment variables into your pipeline’s execution context. You can reference them within your .gitlab-ci.yml file as standard environment variables:

test:
  script:
    - echo "$EXAMPLE_VARIABLE"

You can escape the $ character using the $$VARIABLE syntax:

test:
  script:
    - echo "$$EXAMPLE_VARIABLE"

This example would cause $EXAMPLE_VARIABLE to be logged, instead of the value of the EXAMPLE_VARIABLE variable as shown above.

Variables are available within the job’s environment. They can also be interpolated into the values of other fields in your .gitlab-ci.yml file, enabling dynamic pipeline configuration:

build:
  image: $CI_REGISTRY_IMAGE/build-utils:latest

GitLab CI defines several built-in variables that are always available. These include details of the commit, branch, and merge request that the pipeline’s running against. The predefined variables also provide access to per-job credentials for accessing other GitLab features such as the Container Registry and Dependency Proxy.

Beyond these built-in variables, you can set your own values in multiple places. Variables are supported at the instance, group, project, and pipeline level, giving you flexibility when setting fallback values, defaults, and overrides. You can set variables using the GitLab UI or the API; we’re concentrating on the UI in this guide.

Defining a Variable

Variables are created on the Settings > CI/CD > Variables screen of the scope you want them to be available in. For a project-level variable, that means going to Settings > CI/CD from GitLab’s left sidebar while viewing a page within the project. Similarly, for group-level variables, navigate to the group and use the sidebar to reach its CI settings. Instance-level variables are located via the same route in the GitLab Admin Area.

Expand the “Variables” section to view any variables that have already been defined. Click the blue “Add variable” button to begin adding a new item to the list.

Each variable needs a unique Key; this is how you’ll reference the variable within your pipeline and its scripts. The name you choose must be compatible with the shell that’ll run your job – if you pick a reserved keyword, your job could fail. All variables should be a valid string containing only alphanumeric characters and underscores.

Next set the value of your variable. When the “Type” dropdown is left at “Variable,” this value will be injected as-is each time you reference the variable in your pipeline. Changing the type to “File” will inject the value as a temporary file in your build environment; the value of the environment variable will be the path to that temporary file. This can be a safer way to inject sensitive data if your application is prepared to read the final value from the specified file.

Once you’re done, click the green “Add variable” button to complete the process. You can now reference your variable in pipelines that execute within the scope you defined it in. For a project variable, it’ll be defined for pipelines inside that project, whereas instance-level variables will be available to every pipeline on your GitLab server.

Variables can be managed at any time by returning to the settings screen of the scope they’re set in. Click the Edit button (pencil icon) next to any variable to display the editing dialog and change the variable’s properties. This dialog also provides a way to delete redundant variables.

Protected Variables

Variables can be marked as “protected” by selecting the checkbox in the “add variable” dialog. This option means the variable will only be defined in pipelines running against protected branches or tags.

Protected variables are ideal in circumstances where you’re exposing a sensitive value such as a deployment key that won’t be used in every pipeline. Limiting that value to only the pipelines that actually need it (like deployment jobs running against your protected release branch) lowers the risk of accidental leakage.

Masked Variables

The “Mask variable” option is another way to enhance the safety of your variables. When this checkbox is enabled, GitLab will automatically filter the variable’s value out of collected job logs. Any unintentional echo $SECRET_VALUE will be cleaned up, reducing the risk of a user seeing a sensitive token value as they inspect the job logs using the GitLab web UI.

Successful masking requires variable values to be reliably detectable within the logs. Consequently it only works for values that meet specific formatting requirements. Most common authentication token formats, as well as all Base64-encoded data, will be compatible. Masking only works for values up to 4 KiB in size.

Environment-Level Variables

Variables can be assigned to specific environments. This feature lets your pipelines operate with different configuration depending on the environment they’re deploying to.

Use the “Environment scope” dropdown in the “Add variable” dialog to select an environment for your variable. The variable will only be defined in pipelines which reference the selected environment via the environment field in the .gitlab-ci.yml file.

Setting Variables In .gitlab-ci.yml

Variables can be defined within your .gitlab-ci.yml file using a variables block. Variables listed here will be created for the job if they don’t already exist; otherwise, they’ll override the value set at the project-level or higher.

Variables can be set at the pipeline level with a global variables section. Individual jobs can have their own variables too. Both approaches are shown below where the staging job overrides the value of a pipeline-level variable and sets a unique job-specific variable in addition.

variables:
  DEPLOY_URL: example.com

deploy_staging:
  variables:
    DEPLOY_URL: staging.example.com
    DEPLOY_IS_STAGING_ENV: true
  script:
    - ./deploy.sh

deploy_production:
  script:
    - ./deploy.sh

Variables defined in .gitlab-ci.yml files can sometimes be used in different ways to those set within the GitLab UI or API. You might use a variable to avoid repeating sections of the file, even if those values aren’t likely to change or be overridden in the future. Hence variables sections can feel closer to the variables of programming languages than the config-like keys commonly found at the project level and higher.

Overriding Variables

GitLab’s variable system gives you multiple points at which you can override a variable’s value before it’s fixed for a pipeline or job. The precedence order is relatively complex but can be summarized as the following:

  • GitLab’s predefined variables are always set first.
  • Variables defined within .gitlab-ci.yml are set next (job variables are more specific than pipeline variables).
  • The variables set at the instance, group, and project level are layered in.
  • Variables from the specific pipeline trigger override everything that comes before.

You can always run a pipeline with a specific variable value by using manual execution. Head to your project’s CI/CD > Pipelines page and click the blue “Run pipeline” button in the top-right.

Use the dropdown menu to select the branch or tag to run the pipeline against. Next use the “Variables” table to define variables to add to this pipeline run. These will become the most specific values, applied as the final stage in the variable precedence order. Variables set here won’t be saved or reused with any future pipeline.

Summary

GitLab’s CI variables implementation is a powerful and flexible mechanism for configuring your pipelines. There are so many places that variables can be defined that it can be tricky to work out where a value should be located.

In general, it’s usually most effective to place as many values as you can at the group-level so you don’t have to repeat yourself within your projects. You can always override a variable later in specific projects that need a different value. Self-hosted GitLab administrators can use instance variables to expose common shared values, although this could cause unintentional information exposure if not carefully managed.


Source link