CI_PROJECT_DIR not respected in gitlab CI rules

Viewed 46

Consider the following pipeline:

image: alpine

stages:
  - test

this-does-not-run:
  stage: test
  rules:
    - if: $CI_PROJECT_DIR == "/builds/test"
  script:
    - echo "It works!"

this-runs:
  stage: test
  rules:
    - if: $CI_PROJECT_DIR != "/builds/test"
  script:
    - echo "It doesn't work! CI_PROJECT_DIR- $CI_PROJECT_DIR"

And assume my repo is called test. The output of this CI will always be:

It doesn't work!  CI_PROJECT_DIR- /builds/test

Obviously $CI_PROJECT_DIR == /builds/test, so I would expect the output to be It works!. Am I missing something, or is $CI_PROJECT_DIR not respected in rules?

2 Answers

The problem here is that variables in rules: must be expanded (evaluated by) the GitLab server at pipeline creation time, but $CI_PROJECT_DIR is determined by the runner's builds_dir setting, which is only known by the runner at runtime when the job actually runs:

References to unavailable variables are left intact. In this case, the runner attempts to expand the variable value at runtime. For example, a variable like CI_BUILDS_DIR is known by the runner only at runtime.

That is to say, like CI_BUILDS_DIR, you can't use CI_PROJECT_DIR or other runtime-only variables in rules:if:. Instead, you should use a variable that is known to the gitlab server at pipeline creation time, such as CI_PROJECT_NAME CI_PROJECT_ID, CI_PROJECT_URL, CI_PROJECT_PATH_SLUG or similar.

Try to wrap the expression in quotes. Afaik this is an expression and you would need to wrap it.

Eg:

rules:
    - if: '$CI_PROJECT_DIR == "/builds/test"'

If you only have variables, then from experience you don't need to wrap it. Eg:

rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
Related