Pipeline Inputs

For pipelines using spec: inputs:, pass values via CLI flags or a YAML file.

Usage#

glci run --input force_build=true --input runner_version=17.6.0
glci run --inputs-file inputs.yml
glci run --inputs-file defaults.yml --input force_build=true  # CLI overrides file
glci show --input force_build=true                            # works with show too
glci merged --input force_build=true                          # and with merged

Input types#

TypeAccepted valuesNormalization
stringAny valueNone
booleantrue, false, yes, no, 1, 0Normalized to true/false
numberAny valid numberNone
arrayAny valueFormatted as YAML flow sequence

Inputs file format#

# inputs.yml
force_build: true
runner_version: "17.6.0"
environment: staging

Conditional defaults with rules:#

An input can take its options and default from a rules: list instead of declaring them directly. Rules are evaluated in order and the first match wins; an entry with no if: is the fallback.

spec:
  inputs:
    environment:
      options: ['development', 'production']
      default: 'development'
    instance_type:
      rules:
        - if: $[[ inputs.environment ]] == 'development'
          options: ['small', 'medium']
          default: 'small'
        - if: $[[ inputs.environment ]] == 'production'
          options: ['large', 'xlarge']
          default: 'large'

A rule’s if: can only reference other inputs. CI/CD variables are not in scope, so a $CI_COMMIT_TAG written in an input rule is undefined whatever triggered the pipeline. Comparing an undefined value against "" is false, so a rule written that way never matches — and $CI_COMMIT_TAG == null is always true, so a rule written that way always matches. This is GitLab’s behaviour, which evaluates these rules with the inputs alone.

Inputs resolve in declaration order. A rule may reference another input, but only one declared before it will have a value — a reference to an input declared later sees nothing, not that input’s default, unless the caller supplied a value for it explicitly. That is how GitLab resolves them, and it is worth knowing because it looks like a bug:

spec:
  inputs:
    image:                          # declared first
      rules:
        - if: $[[ inputs.flavor ]] == 'slim'
          default: 'alpine'
        - default: 'debian'         # always taken: flavor has no value yet
    flavor:
      default: 'slim'

Swap the two entries and image resolves to alpine.

A rule may also name an input that does not exist, or two inputs may read each other. Neither is an error — GitLab accepts both, and so does glci: an unknown name is simply undefined, and a cycle cannot loop because each input resolves exactly once. The practical consequence is that a typo in an input reference is silent: the rule never matches and the fallback wins, with nothing reported. Check the resolved value with glci merged if a rule is not behaving.

Further rules, all matching GitLab:

Validation#

glci validates inputs before starting the pipeline:

An included file or component whose inputs do not resolve fails the parse, naming the include it came from:

CI configuration is invalid: parsing CI config: resolving includes: include local "/ci/comp.yml": resolving inputs: required input "env" not provided

An include’s inputs come only from that include entry’s own inputs: map. --input and --inputs-file reach the root file’s spec: and nothing else, which is also how GitLab behaves.

Interactive TUI#

The TUI (glci with no subcommand) shows an input form with descriptions and defaults pre-filled. Required inputs are highlighted and validated before submission.

An input whose default/options come from rules: is shown blank and unmarked: the form does not evaluate the rules, so nothing is pre-filled and the matching rule’s options: are not enforced there. They are still enforced when the pipeline is resolved, so a value the rule forbids fails the run rather than the form.

Esc