Reject unresolved YAML tags in array CI/CD inputs
What does this MR do and why?
A !reference tag passed inside a type: array CI/CD input value is never resolved, so the internal Ruby object leaks into the generated configuration.
!reference tags and inputs are processed at different stages of config loading (Gitlab::Ci::Config#build_config):
- Input interpolation runs first.
!referencetags are resolved last (Config::Yaml::Tags::Resolver).
When a !reference is inside an array input value, it reaches interpolation as an unresolved Tags::Reference object. If that value is interpolated into a string, the array is stringified with to_s before the tag is ever resolved, dumping the object into the output:
echo '[#<Gitlab::Ci::Config::Yaml::Tags::Reference:0x... @data={...}>, my-specific]'This usage is already documented as unsupported (see Array type inputs). This MR detects an unresolved YAML tag in an array input value during input validation and returns a clear error instead of leaking the object. The error names the actual tag so it stays accurate if other YAML tags are added later.
Detection is recursive (tags nested in sub-arrays are caught) and applies to both provided values and default values.
Resolves #606739 (closed)
How to set up and validate locally
Given a template with a type: array input, and a parent .gitlab-ci.yml that passes a !reference inside that input:
# list.yml
.my-shared-list:
- value1
- value2
# template.yml
spec:
inputs:
a:
type: array
---
job:
script:
- echo '$[[ inputs.a ]]' > my_script.sh
# .gitlab-ci.yml
include:
- local: /list.yml
- local: /template.yml
inputs:
a:
- !reference [.my-shared-list]
- my-specificBefore this change, the Full Configuration tab (or CI Lint) showed a dumped Reference object. After this change, it shows a clear error.
Documentation
doc/ci/inputs/_index.md(Array type): removes the self-contradiction and states that YAML tags are rejected.doc/ci/yaml/yaml_optimization.md(!referencetags): replaces the misleading "references are evaluated before input interpolation" sentence with the accurate parse-time vs resolve-time distinction, covering both directions (input inside a reference path, and reference inside an array input).
MR acceptance checklist
- Unit tests for
Ci::Inputs::ArrayInput(top-level tag, nested tag, default value). - Integration test for
Interpolation::Interpolatorconfirming the error is surfaced instead of leaking the tag object. - RuboCop, markdownlint, and Vale passing on changed files.
- Technical Writer review of the documentation changes (can be post-merge).