Fix !reference tag in maps in arrays
What does this MR do and why?
Currently, in Gitlab CI expressions such as this produce incorrect results:
a: "something"
b: [{ c: !reference [a] }]
d: !reference [b]
This is because !reference [b] takes the object at b, sees it's an Array, and tries to resolve every element of that Array. Hash, however, is not a tag one could resolve, so it's returned as is, with the reference remaining unresolved.
This tiny MR fixes that by making the yaml Resolver recursive. Also, it adds a test to check for this particular case.
As for the reason why it's important, consider my use case:
.predicates:
is_release: "$CI_COMMIT_TAG =~ /^v/"
is_from_mr: "$CI_PIPELINE_SOURCE == "merge_request_event"
.rules:
some_rule:
- if: !reference [.predicates, is_release]
- if: !reference [.predicates, is_from_mr]
a job in another file:
script: …
rules: !reference [.rules, some_rule]
This lets a downstream user override the predicates without having to modify all rules that use them, but doesn't work because of this bug. Besides, it's really counterintuitive that "!reference doesn't work in maps in arrays, but does everywhere else".
References
There have been issues reported about this behavior:
To the extent of my knowledge, this MR solves them.
Screenshots or screen recordings
Irrelevant, see the test above.
How to set up and validate locally
- Try running the test provided with this MR, or any of the examples in the issues linked above.
- See it fail
- Observe that it works after applying this MR
MR acceptance checklist
As far as I know, this MR does not meaningfully impact performance, security, observability, or other important concerns. The MR contains a test to ensure the bug doesn't come back. All relevant tests pass.