Flatten YAML anchor aliases that expand to arrays in script fields

What

Anchor aliases used inside script: / before_script: / after_script: (the documented GitLab "YAML anchors for scripts" optimization) expand to a nested []any element after YAML parsing. toStringList kept only string elements, so every aliased step was silently dropped from the compiled job script.

This broke the Drupal contrib templates (project/gitlab_templates): the *get-utility-files step that downloads get-file-via-curl.sh vanished, so the job later failed with get-file-via-curl.sh: No such file or directory — while the same pipeline passed on git.drupalcode.org.

How

Add toScriptList/getScriptList that recursively flatten nested arrays, mirroring GitLab's Entry::Commands (Array(@config).flatten in lib/gitlab/ci/config/entry/commands.rb).

Scoping: flattening is applied to exactly the Entry::Commands fields — script, before_script, after_script, hooks:pre_get_sources_script, and services:command. toStringList stays string-only for tags / dependencies / paths / entrypoint / etc., because GitLab validates those as array_of_strings and errors on nested input rather than flattening it. (The plan left "shared vs scoped" open; scoped is the higher-fidelity match.)

Non-string scalars in a script list are still dropped, matching the previous behavior.

Tests

  • Unit: toScriptList (flatten incl. deep nesting + scalar drop) and toStringList (locks in no-flatten).
  • Integration (ParseMergedYAML): anchor aliases in script/before_script, hooks:pre_get_sources_script, both service-command paths, and a negative test proving tags is not flattened.

Verification

  • go build ./..., go vet ./..., make test, make test-e2e-parse, make test-e2e-golden — all pass.
  • Real reproduction: glci run composer on a Drupal module checkout (clean daemon + cleared include cache). The *get-utility-files step now executes, the job gets past source $CI_PROJECT_DIR/get-file-via-curl.sh scripts/expand_composer_json.php, and the pipeline passes.

Notes

  • The comprehensive e2e fixture was intentionally not extended: the golden comparison checks pipeline structure (names/stages/needs/when), not script content, so an anchor job there would not guard this fix. The unit/integration tests and the real Drupal run are the meaningful coverage.
  • A related secondary issue (inspection commands glci show/jobs/variables resolving includes before loading .glci.env, causing a 404) is left for a separate follow-up MR.

Closes #103 (closed)

Merge request reports

Loading
Loading