Variables that reference file variables no longer work in GitLab Runner v18.6.0 with the shell executor

This appears to be a regression introduced by 50044b81:

To reproduce:

  1. Create a CI/CD variable named FILE_TEST with some value (hello-world).

  2. Define a job:

default:
  script:
    - echo $FILE_TEST
    - echo $MY_FILE_VAR
    - cat $FILE_TEST
    - cat $MY_FILE_VAR
  variables:
    MY_FILE_VAR: $FILE_TEST
  1. Run this job with a shell executor with GitLab Runner v18.6.0:

image

WIth GitLab Runner v18.5.0, I don't see $PWD:

image

This is causing numerous QA tests to fail and blocking deployments: gitlab-com/gl-infra/production#20874

Duo says:

The root cause: When you assign MY_FILE_VAR: $FILE_TEST, GitLab sends the literal string $FILE_TEST as the value. The shell executor's Variable() method then calls Absolute() on this string, which prepends $PWD/ to it, resulting in $PWD/$FILE_TEST instead of just $FILE_TEST.

This is happening in the Variable() method at lines 222-226 in v18.6.0:

} else {
    if b.isTmpFile(variable.Value) {
        variable.Value = b.cleanPath(variable.Value)
    }
    b.Linef("export %s=%s", b.escape(variable.Key), b.escape(variable.Value))
}

The issue is that $FILE_TEST doesn't match isTmpFile() check (which looks for the actual temp path prefix), so it goes through escape() which then gets processed by Absolute() somewhere in the chain, adding the $PWD/ prefix.

Recommendation: This appears to be a regression where variable expansion isn't happening correctly for file variables that reference other variables. The shell executor should either:

  1. Expand $FILE_TEST to its actual value before processing, or
  2. Recognize that values starting with $ are variable references and shouldn't have paths prepended
Edited by Stan Hu