Skip to content

Gitlab CI fails to parse .gitlab-ci.yml when it is a symlink

Summary

When .gitlab-ci.yml is a symlink to another file (for example, a version in a subdirectory which is a subrepo), Gitlab CI fails to parse it and on the pipelines page it gets tagged with "yaml invalid" ("Invalid configuration format").

Steps to reproduce

  1. Create a basic .gitlab-ci.yml, commit it, and push to a gitlab project (an example is available publicly at: wtsi-hgi/test-gitlab-ci-symlink@6f31d227)
echo 'stages:
  - test
test:
  stage: test
  script:
    - echo "hello world"' > .gitlab-ci.yml
git add .gitlab-ci.yml
git commit
git push
  1. Verify that the pipeline succeeded (see: https://gitlab.com/wtsi-hgi/test-gitlab-ci-symlink/builds/9729805)

  2. Move the .gitlab-ci.yml to gitlab-ci.yml, create a symlink to it, commit, and push to gitlab:

git mv .gitlab-ci.yml gitlab-ci.yml
ln -s gitlab-ci.yml .gitlab-ci.yml
git add .gitlab-ci.yml
git commit
git push

(example commit at: wtsi-hgi/test-gitlab-ci-symlink@469d23da)

  1. Observe that Gitlab CI fails to even attempt to run CI: https://gitlab.com/wtsi-hgi/test-gitlab-ci-symlink/pipelines

Expected behavior

Gitlab CI should follow symlink(s) when loading .gitlab-ci.yml so that it is possible to symlink this file to another location in the repository.

Actual behavior

Gitlab CI fails with a "yaml invalid" tag, which is also a confusing error (I spent some time trying to figure out where my syntax was wrong before I realized it wasn't even trying to read the YAML).

Output of checks

This bug happens on GitLab.com

Possible fixes

This may be related to Issue 26677, in that apparently symlinks are also not followed when parsing README.md for display on the web.

I'm not very familiar with Ruby, but the issue seems like it might be with https://gitlab.com/gitlab-org/gitlab-ce/blob/master/app/models/ci/pipeline.rb#L286-289 - the code there seems to be responsible for returning the ci_yaml_file data, and it does so by simply fetching the blob named .gitlab-ci.yml, which in the test case is going to just contain the name of the link target. There should be a loop which tests the mode of the git object to see if it is a symbolic link (mode 120000) and if so, retrieve the object at the link target and test the new object mode. To avoid problems, the loop would need to detect and avoid loops by recording the paths to objects already visited and refusing to visit them again. Once an object is reached with mode != 120000, return its data.

Edited by 🤖 GitLab Bot 🤖