doc/ci/inputs/_index.md
{{< details >}}
{{< /details >}}
{{< history >}}
{{< /history >}}
Use CI/CD inputs to increase the flexibility of CI/CD configuration. Inputs and CI/CD variables can be used in similar ways, but have different benefits:
rules
for dynamic pipeline configuration.Inputs:
.gitlab-ci.yml) and assigned values
when a pipeline is triggered, allowing consumers to customize reusable CI configurations..gitlab-ci.yml or a file
being included. You can pass them explicitly to other files - using include:inputs - or pipeline
using trigger:inputs.CI/CD Variables:
spec:inputsUse spec:inputs in the CI/CD configuration header to define input parameters that
can be passed to the configuration file.
Use the $[[ inputs.input-id ]] interpolation format outside the header section to declare where to use
the inputs.
For example:
spec:
inputs:
job-stage:
default: test
environment:
default: production
---
scan-website:
stage: $[[ inputs.job-stage ]]
script: ./scan-website $[[ inputs.environment ]]
In this example, the inputs are job-stage and environment.
With spec:inputs:
default is not specified.include keyword.spec:inputs also contains job definitions, add a YAML document
separator (---) after the header.Then you set the values for the inputs when you:
include. Otherwise the pipeline could fail to start
if a new pipeline triggers automatically, including in:
include:inputs section, and are used
every time the configuration is included.To configure inputs, use:
spec:inputs:default to define default values for inputs
when not specified. When you specify a default, the inputs are no longer mandatory.spec:inputs:description to give a description to
a specific input. The description does not affect the input, but can help people
understand the input details or expected values.spec:inputs:options to specify a list of allowed values
for an input.spec:inputs:regex to specify a regular expression
that the input must match.spec:inputs:type to force a specific input type, which
can be string (default when not specified), array, number, or boolean.spec:inputs:rules to define conditional options
and default values based on the values of other inputs.You can define multiple inputs per CI/CD configuration file, and each input can have multiple configuration parameters.
For example, in a file named scan-website-job.yml:
spec:
inputs:
job-prefix: # Mandatory string input
description: "Define a prefix for the job name"
job-stage: # Optional string input with a default value when not provided
default: test
environment: # Mandatory input that must match one of the options
options: ['test', 'staging', 'production']
concurrency:
type: number # Optional numeric input with a default value when not provided
default: 1
version: # Mandatory string input that must match the regular expression
type: string
regex: ^v\d\.\d+(\.\d+)$
export_results: # Optional boolean input with a default value when not provided
type: boolean
default: true
---
"$[[ inputs.job-prefix ]]-scan-website":
stage: $[[ inputs.job-stage ]]
script:
- echo "scanning website -e $[[ inputs.environment ]] -c $[[ inputs.concurrency ]] -v $[[ inputs.version ]]"
- if $[[ inputs.export_results ]]; then echo "export results"; fi
In this example:
job-prefix is a mandatory string input and must be defined.job-stage is optional. If not defined, the value is test.environment is a mandatory string input that must match one of the defined options.concurrency is an optional numeric input. When not specified, it defaults to 1.version is a mandatory string input that must match the specified regular expression.export_results is an optional boolean input. When not specified, it defaults to true.You can specify that an input must use a specific type with the optional spec:inputs:type keyword.
The input types are:
arraybooleannumberstring (default when not specified)When an input replaces an entire YAML value in the CI/CD configuration, it is interpolated into the configuration as its specified type. For example:
spec:
inputs:
array_input:
type: array
boolean_input:
type: boolean
number_input:
type: number
string_input:
type: string
---
test_job:
allow_failure: $[[ inputs.boolean_input ]]
needs: $[[ inputs.array_input ]]
parallel: $[[ inputs.number_input ]]
script: $[[ inputs.string_input ]]
When an input is inserted into a YAML value as part of a larger string, the input is always interpolated as a string. For example:
spec:
inputs:
port:
type: number
---
test_job:
script: curl "https://gitlab.com:$[[ inputs.port ]]"
{{< history >}}
{{< /history >}}
The content of the items in an array type can be any valid YAML map, sequence, or scalar. More complex YAML features
like !reference cannot be used. When using the value of an array
input in a string (for example echo "My rules: $[[ inputs.rules-config ]]" in your script: section), you might
see unexpected results. The array input is converted to its string representation, which might not match your
expectations for complex YAML structures such as maps.
spec:
inputs:
rules-config:
type: array
default:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
when: manual
- if: $CI_PIPELINE_SOURCE == "schedule"
---
test_job:
rules: $[[ inputs.rules-config ]]
script: ls
Array inputs must be formatted as JSON, for example ["array-input-1", "array-input-2"],
when manually passing inputs for:
{{< history >}}
ci_inputs_array_index_operator. Disabled by default.ci_inputs_array_index_operator removed.{{< /history >}}
Use bracket notation with an index number to access individual elements of an array input.
Array items are indexed in the order they are defined in the YAML array,
with positive numbers, and the [0] index item is the first item in the array.
For example:
spec:
inputs:
supported_versions:
type: array
default:
- '2.0'
- '1.0'
- '0.1'
---
job:
script:
# Outputs: 'Latest version is 2.0'
- echo 'Latest version is $[[ inputs.supported_versions[0] ]]'
You can chain array indexing with dot notation to access nested values:
spec:
inputs:
servers:
type: array
default:
- host: server1.example.com
port: 8080
---
job:
script:
- curl "https://$[[ inputs.servers[0].host ]]:$[[ inputs.servers[0].port ]]"
For multi-dimensional arrays, use multiple indices in a row. For example, you can use [0][1] for a 2-dimensional array:
spec:
inputs:
matrix:
type: array
default:
- ['a', 'b']
- ['c', 'd']
---
job:
script:
# Outputs: 'b'
- echo $[[ inputs.matrix[0][1] ]]
You can chain together a maximum of 5 indices per segment, for example arr[0][1][2][3][4].
Inputs support different value types. You can pass multi-string values using the following format:
spec:
inputs:
closed_message:
description: Message to announce when an issue is closed.
default: 'Hi {{author}} :wave:,
Based on the policy for inactive issues, this is now being closed.
If this issue requires further attention, reopen this issue.'
---
spec:inputs:rules{{< history >}}
{{< /history >}}
Use spec:inputs:rules to define different options and default values for an input
based on the values of other inputs. You can use this configuration when one input should have different
allowed values depending on the context provided by other inputs.
Each rule in the rules list can have:
if: An expression that checks the values of one or more inputs to determine when this rule applies. Uses the same syntax as
$[[ inputs.input-id ]] interpolation.options: A list of allowed values for the input when this rule matches.default: The default value to use when this rule matches.Rules are evaluated in order. The first rule with a matching if condition is used.
The last rule without an if condition acts as a fallback when no other rules match.
For example, to define instance types that vary based on cloud provider and environment:
spec:
inputs:
cloud_provider:
options: ['aws', 'gcp', 'azure']
default: 'aws'
description: 'Cloud provider'
environment:
options: ['development', 'staging', 'production']
default: 'development'
description: 'Target environment'
instance_type:
description: 'VM instance type'
rules:
- if: $[[ inputs.cloud_provider ]] == 'aws' && $[[ inputs.environment ]] == 'development'
options: ['t3.micro', 't3.small']
default: 't3.micro'
- if: $[[ inputs.cloud_provider ]] == 'aws' && $[[ inputs.environment ]] == 'production'
options: ['t3.xlarge', 't3.2xlarge', 'm5.xlarge']
default: 't3.xlarge'
- if: $[[ inputs.cloud_provider ]] == 'gcp'
options: ['e2-micro', 'e2-small', 'e2-standard-4']
default: 'e2-micro'
- if: $[[ inputs.cloud_provider ]] == 'azure'
options: ['Standard_B1s', 'Standard_B2s', 'Standard_D2s_v3']
default: 'Standard_B1s'
- options: ['small', 'medium', 'large'] # Fallback for any other case
default: 'small'
---
deploy:
script: |
echo "Deploying to $[[ inputs.cloud_provider ]]"
echo "Environment: $[[ inputs.environment ]]"
echo "Instance: $[[ inputs.instance_type ]]"
In this example:
cloud_provider is aws and environment is development, the user can select
from t3.micro or t3.small instance types, with t3.micro as the default.cloud_provider is aws and environment is production, different instance
types are available (t3.xlarge, t3.2xlarge, m5.xlarge).cloud_provider is gcp, GCP-specific instance types are available regardless
of the environment.You can also use the || (OR) operator to match multiple conditions. For example:
spec:
inputs:
deployment_type:
options: ['canary', 'blue-green', 'rolling', 'recreate']
default: 'rolling'
requires_approval:
description: 'Whether deployment requires manual approval'
rules:
- if: $[[ inputs.deployment_type ]] == 'canary' || $[[ inputs.deployment_type ]] == 'blue-green'
options: ['true']
default: 'true'
- options: ['true', 'false']
default: 'false'
---
deploy:
script: echo "Deploying with $[[ inputs.deployment_type ]] strategy"
In this example, the requires_approval input is set to true when deployment_type is either
canary or blue-green. In all other cases, the default is false and both true or false are allowed options.
default: null{{< history >}}
{{< /history >}}
Use spec:inputs:rules with default: null and without options to allow users to enter
their own value for an input. This is useful for workflow-specific values like environment names
or test configurations.
For example:
spec:
inputs:
deployment_type:
options: ['standard', 'custom']
default: 'standard'
custom_config:
description: 'Custom configuration value'
rules:
- if: $[[ inputs.deployment_type ]] == 'custom'
default: null
---
deploy:
script: echo "Config: $[[ inputs.custom_config ]]"
In this example, when deployment_type is custom, the custom_config input is listed on the run pipeline page
and users must enter a value for the input.
spec:inputs:rulesYou can use boolean inputs in rule conditions. Boolean values can be compared using boolean literals (true/false):
spec:
inputs:
publish:
type: boolean
default: true
publish_stage:
rules:
- if: $[[ inputs.publish ]] == true
default: 'publish'
- if: $[[ inputs.publish ]] == false
default: 'test'
---
job:
stage: $[[ inputs.publish_stage ]]
script: echo "Publishing is $[[ inputs.publish ]]"
In this example, when publish is true, publish_stage defaults to publish. When publish is false,
it defaults to test.
include{{< history >}}
include:with renamed to include:inputs in GitLab 16.0.{{< /history >}}
Use include:inputs to set the values for inputs
when the included configuration is added to the pipeline, including for:
include.For example, to include and set the input values for scan-website-job.yml from the
input configuration example:
include:
- local: 'scan-website-job.yml'
inputs:
job-prefix: 'some-service-'
environment: 'staging'
concurrency: 2
version: 'v1.3.2'
export_results: false
In this example, the inputs for the included configuration are:
| Input | Value | Details |
|---|---|---|
job-prefix | some-service- | Must be explicitly defined. |
job-stage | test | Not defined in include:inputs, so the value comes from spec:inputs:default in the included configuration. |
environment | staging | Must be explicitly defined, and must match one of the values in spec:inputs:options in the included configuration. |
concurrency | 2 | Must be a numeric value to match the spec:inputs:type set to number in the included configuration. Overrides the default value. |
version | v1.3.2 | Must be explicitly defined, and must match the regular expression in the spec:inputs:regex in the included configuration. |
export_results | false | Must be either true or false to match the spec:inputs:type set to boolean in the included configuration. Overrides the default value. |
include entriesInputs must be specified separately for each include entry. For example:
include:
- component: $CI_SERVER_FQDN/the-namespace/the-project/[email protected]
inputs:
stage: my-stage
- local: path/to/file.yml
inputs:
stage: my-stage
{{< history >}}
{{< /history >}}
Inputs provide advantages over variables including type checking, validation and a clear contract.
Unexpected inputs are rejected.
Inputs for pipelines must be defined in the spec:inputs header
of the main .gitlab-ci.yml file. You cannot use inputs defined in included files for pipeline-level configuration.
[!note] In GitLab 17.7 and later, pipeline inputs are recommended over passing pipeline variables. For enhanced security, you should disable pipeline variables when using inputs.
You should always set default values when defining inputs for pipelines. Otherwise the pipeline could fail to start if a new pipeline triggers automatically. For example, merge request pipelines can trigger for changes to a merge request's source branch. You cannot manually set inputs for merge request pipelines, so if any input is missing a default, the pipeline fails to create. This can also happen for branch pipelines, tag pipelines, and other automatically triggered pipelines.
You can set input values with:
trigger keywordA pipeline can take up to 20 inputs.
Feedback is welcome on this issue.
You can pass inputs to downstream pipelines,
if the downstream pipeline's configuration file uses spec:inputs.
For example, with trigger:inputs:
{{< tabs >}}
{{< tab title="Parent-child pipeline" >}}
trigger-job:
trigger:
strategy: mirror
include:
- local: path/to/child-pipeline.yml
inputs:
job-name: "defined"
rules:
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
{{< /tab >}}
{{< tab title="Multi-project pipeline" >}}
trigger-job:
trigger:
strategy: mirror
project: project-group/my-downstream-project
inputs:
job-name: "defined"
rules:
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
{{< /tab >}}
{{< /tabs >}}
{{< history >}}
ci_file_inputs. Disabled by default.ci_file_inputs removed.{{< /history >}}
You can reuse pipeline input definitions across multiple CI/CD configurations by defining them in
external files and including them a project's pipeline configuration with spec:include.
Create a file with input definitions, for example in a file named shared-inputs.yml:
inputs:
environment:
description: "Deployment environment"
options: ['staging', 'production']
region:
default: 'us-east-1'
Then you can include the external inputs in your .gitlab-ci.yml with local:
spec:
include:
- local: /shared-inputs.yml
---
deploy:
script: echo "Deploying to $[[ inputs.environment ]] in $[[ inputs.region ]]"
If the file is stored outside your project, you can use:
project for files in another GitLab project. Use the full project path and define the filename with file.
You can optionally also define the ref to fetch the file from.remote for file on another server. Use the full URL to the file.You can also include multiple input files at the same time, for example:
spec:
include:
- local: /shared-inputs.yml
- project: 'my-group/shared-configs'
ref: main
file: '/ci/common-inputs.yml'
- remote: 'https://example.com/ci/shared-inputs.yml'
---
[!note] You cannot use
spec:includefor CI/CD component inputs.
{{< history >}}
{{< /history >}}
Input keys must be unique across all included files and inline specifications.
If you define an input with the same key in multiple included files, or in both
an included file and the inputs: section in the .gitlab-ci.yml configuration,
the following error is returned:
Duplicate input keys found: environment. Input keys must be unique across all included files and inline specifications.
To fix this error, ensure each input key is defined only once, either in an included
file or in the inline inputs: section, but not both.
{{< history >}}
{{< /history >}}
You can specify predefined functions in the interpolation block to manipulate the input value. The format supported is the following:
$[[ input.input-id | <function1> | <function2> | ... <functionN> ]]
With functions:
spec:
inputs:
test:
default: 'test $MY_VAR'
---
test-job:
script: echo $[[ inputs.test | expand_vars | truncate(5,8) ]]
In this example, assuming the input uses the default value and $MY_VAR is an unmasked project variable with value my value:
expand_vars expands the value to test my value.truncate applies to test my value with a character offset of 5 and length 8.script would be echo my value.expand_vars{{< history >}}
{{< /history >}}
Use expand_vars to expand CI/CD variables in the input value.
Only variables you can use with the include keyword and which are
not masked can be expanded.
Nested variable expansion is not supported.
Example:
spec:
inputs:
test:
default: 'test $MY_VAR'
---
test-job:
script: echo $[[ inputs.test | expand_vars ]]
In this example, if $MY_VAR is unmasked (exposed in job logs) with a value of my value, then the input
would expand to test my value.
truncate{{< history >}}
{{< /history >}}
Use truncate to shorten the interpolated value. For example:
truncate(<offset>,<length>)| Name | Type | Description |
|---|---|---|
offset | Integer | Number of characters to offset by. |
length | Integer | Number of characters to return after the offset. |
Example:
$[[ inputs.test | truncate(3,5) ]]
Assuming the value of inputs.test is 0123456789, then the output would be 34567.
posix_escape{{< history >}}
{{< /history >}}
Use posix_escape to escape any POSIX Bourne shell control or meta characters in input values.
posix_escape escapes the characters by inserting \ before relevant characters in the input.
Example:
spec:
inputs:
test:
default: |
A string with single ' and double " quotes and blanks
---
test-job:
script: printf '%s\n' $[[ inputs.test | posix_escape ]]
In this example, posix_escape escapes characters that could be shell control or metadata characters:
$ printf '%s\n' A\ string\ with\ single\ \'\ and\ double\ \"\ quotes\ and\ \ \ blanks
A string with single ' and double " quotes and blanks
The escaped input preserves special characters and spacing as provided.
[!warning] Do not rely on
posix_escapefor security purposes with untrusted input values.
posix_escape makes a best-effort attempt to preserve the input value exactly, but some
character combinations could still cause undesired results. Even when using posix_escape, it is possible that:
For security purposes you should ensure that your inputs are trusted. You can use:
spec:input:type number or boolean, which cannot contain problematic characters.spec:input:regex keyword to prevent problematic inputs.spec:input:options keyword to define a predefined list of input options.If you combine posix_escape with expand_vars, you must set expand_vars first.
Otherwise posix_escape would escape the $ in the variable, preventing expansion.
For example:
test-job:
script: echo $[[ inputs.test | expand_vars | posix_escape ]]
inputs in rulesWhen you use input to modify rules:if expressions, you might get one of
a variety of syntax errors.
These errors are often related to how strings are handled in CI/CD variable expressions.
Expressions in rules:if expect a CI/CD variable compared to a quoted string (' or ") or another variable.
When input values are inserted into the rules configuration at pipeline runtime,
the resulting value might not be a quoted string or variable, which causes the error.
For example, in the configuration to include:
spec:
inputs:
branch:
default: $CI_DEFAULT_BRANCH
branch2:
default: $CI_DEFAULT_BRANCH
---
job-name:
rules:
- if: $CI_COMMIT_REF_NAME == $[[ inputs.branch ]]
- if: $CI_COMMIT_REF_NAME == $[[ inputs.branch2 ]]
Then, in the main configuration file:
include:
inputs:
branch: $CI_DEFAULT_BRANCH # Valid
branch2: main # Invalid
In this example:
branch: $CI_DEFAULT_BRANCH is valid. The if: clause evaluates to
if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH, which is a valid variable expression.
The variable does not need to be quoted.branch2: main is invalid. The if: clause evaluates to
if: $CI_COMMIT_REF_NAME == main, which is invalid because main is a string but is not quoted.To resolve this issue, make sure expressions remain properly formatted after input values are inserted into the configuration. This might require additional quote characters. For example, add quotes to the rules that use string values:
rules:
if: $CI_COMMIT_REF_NAME == "$[[ inputs.branch2 ]]"
For interpolation functions like expand_vars,
you might also need to quote the entire if: expression. For example:
spec:
inputs:
environment:
default: "$ENVIRONMENT"
---
$[[ inputs.environment | expand_vars ]] job:
script: echo
rules:
- if: '"$[[ inputs.environment | expand_vars ]]" == "production"'
In this example, quoting both the input and the entire if: expression ensures valid
syntax after the input is evaluated. When quotes are nested, use " for the inner
quotes and ' for the outer quotes, or the inverse.
Jobs names do not need to be quoted.