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
- 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
-
Verify that the pipeline succeeded (see: https://gitlab.com/wtsi-hgi/test-gitlab-ci-symlink/builds/9729805)
-
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)
- 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.