CI_PROJECT_DIR not respected in gitlab CI rules - gitlab

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?

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

Gitlab-ci: Getting error when I use rules and downstream pipeline trigger in the same stage

I would like to trigger downstream pipeline but before that I need to eliminate the branches with rule method and I just want to trigger it only with specific branches. But I'm getting this error when I run the pipeline downstream pipeline cannot be created reference not found Did I miss something or can't I use rule and trigger methods in the same stage?
My stage:
test:
stage: test
variables:
branch: $CI_COMMIT_BRANCH
trigger:
project: test/project
strategy: depend
branch: $branch
allow_failure: false
rules:
- if: $CI_COMMIT_BRANCH == 'main' || $CI_COMMIT_BRANCH == 'test'
- when: never
Looks like the dash on the last line is not needed. Probably you meant this:
rules:
- if: $CI_COMMIT_BRANCH == 'main' || $CI_COMMIT_BRANCH == 'test'
when: never
I also recommend to check documentation for $CI_COMMIT_BRANCH:
The commit branch name. Available in branch pipelines, including
pipelines for the default branch. Not available in merge request
pipelines or tag pipelines.
You could try to use $CI_COMMIT_REF_NAME variable instead which is available in merge request or tag pipelines. You could try to debug this adding some echo commands (like - echo $CI_COMMIT_REF_NAME and - echo $branch to be sure that the branch really exists in the downstream project and variable are properly expanded.
But first of all you need to fix the syntax (that extra dash).

How to except the branch in gitlab.ci?

Ran into a problem in gitlab.ci. I have a main branch and a test branch. The remaining branches are release branches and serve as a workspace for developers. What needs to be written in gitlab.ci so that the build-to-dev and deploy-to-dev stages run on all branches except the test branch?
The ".gitlab-ci.yml keyword reference" includes a only/except keyword which should help.
job2:
script: echo
except:
- test
Besides the only/except Keyword, the rules keyword can also be used and offers additional functionality than only/except.
jobs:
rules:
- if: '$CI_COMMIT_BRANCH == main'
when: never
script:
- echo hello
But only/expect cant be combined with rules on one job

GitLab Ci CD - rules not working with variables (on the same key nesting)

I try to trigger another repo only if in current repo I add TAG to commit. Unfortunately when I want to pass variable as well, this job not starting, if i comment out variable key - its working.
test:
stage: build
trigger:
project: php/project-to-run
branch: develop
rules:
- if: $CI_COMMIT_TAG == 'tst'
variables:
CI_COMMIT_TAG: "$CI_COMMIT_TAG"
Instead of rules i also tried "only" and it works ONLY without passing variable
only:
refs:
- tags
variables:
- $CI_COMMIT_TAG =~ /^stage_[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/

Stuggling to Create GitLab-CI Pipeline that includes 'schedules' and 'changes' declarations

I have a GitLab-CI pipeline in place with my Katalon Studio automation tests that I would like to have the following functionality:
Various nightly schedules that run based on scheduled variables being present.
Changes declaration so pushes to the repo only trigger a pipeline run if certain files have been touched.
I have the scheduled portion running as expected, but I am struggling on pairing that with the 'changes' declaration to only run the pipeline IF someone pushes after changing certain files. Can someone help? I am guessing this is an issue with my YAML formatting.
Here is an example snippet from my current GitLab-CI.yaml
Example Tests:
stage: Example
tags:
- aws-medium-runner
script:
- MY_SCRIPT
rules:
- if: $SCHEDULE_A == "true" # tied to schedule A in scheduler tool
when: always
- if: '$CI_PIPELINE_SOURCE == "push"'
changes: # Only run on pushes if changes have been made to certain directories
- Test\ Cases/Example/*
- Object\ Repository/Example/*
- Test\ Suites/Example/*
- Scripts/Example/*
when: always
dependencies:
- Set Release Version
You are missing 2 spaces on the changes: part.
It should work when you add those. (see the example below)
And in case you want to combine the 2 rules with the same conditions, you can combine them into one rule:
Example Tests:
stage: Example
tags:
- aws-medium-runner
script:
- MY_SCRIPT
rules:
- if: '$CI_PIPELINE_SOURCE == "push" || $SCHEDULE_A == "true"'
changes: # Only run on pushes if changes have been made to certain directories
- Test Cases/Example/*
- Object Repository/Example/*
- Test Suites/Example/*
- Scripts/Example/*
when: always
dependencies:
- Set Release Version

Gitlab-CI run Stage conditionally

As you see below I have two stages.
1- Build
2- Deploy
And I have 3 kind of branches
1- master
2- test
3- Other branches which created by developers. (Development)
I want to run build for all branches but I have a condition for deploy
1- If branch is test run deploy.
2- If branch is other branches don't run deploy.
3- if branch is master run deploy only manual.
But this three condition doesn't works properly with my gitlab-ci.yml
stages:
- build
- deploy
default:
image: node:latest
before_script:
- |
if [ "$CI_BUILD_REF_NAME" == "master" ]; then
ENV="prod"
elif [ "$CI_BUILD_REF_NAME" == "test" ]; then
ENV="test"
else
ENV="dev"
fi
- npm install
build:
stage: build
script:
- cp ./src/env-${ENV}.js ./src/env.js
- npm run build-compressed
deploy:
stage: deploy
rules: //this section doesn't work properly
- if: '$ENV == "test"'
when: always
- if: '$ENV == "prod"'
when: manual
- when: never
script:
- cp ./src/env-${ENV}.js ./src/env.js
- npm run build-compressed
- npm run publish:${ENV}
I recommend doing such a differentiation via Rules. As you can easily override variables with rules, see GitLab CI Doc.
Below you can find a short example
rules
- if: $CI_COMMIT_BRANCH =~ /test/
variables: # Override ENV defined
ENV: "test" # at the job level.
- if: $CI_COMMIT_BRANCH =~ /master/
variables: # Override ENV defined
ENV: "prod" # at the job level.
- variables: # not 100% sure about this one, as when can stand without a if clause, i assume variables can too :D
ENV: "dev"
Furthermore i would also do the rule check based on the branch within the deploy stage. - as it is easier to verify the branch, than to ensure at a later stage, that the Env variable is still set properly.
Also important to notice is the order of evaluation. Just because there is a before_script in the default section, does not mean it is evaluated just once for the whole. The before_script is evaluated once per Job.
Additionally the rules are evaluated, before the JOB runs, as it needs to determine if the job should be executed or not. This means you are not able to reference the variable from the before_script.
If you want to pass on the variable from the first job to the second job, you need to persist it in a dotenv-artifact - this way, the variables are available before the second stage start. (I am still not sure if you can use them for evaluation in rules, that is something you need to check)
I hope my additional clarifications, based on your comments, help you to find the best way.

Resources