I have the following rules for a job. However, only the first rule is applied. Why?
testing:
rules:
- if: ($CI_PIPELINE_SOURCE == "schedule")
- if: ($PRODUCT_TYPE == "cloud")
variables:
TEST_CONFIG_DIRECTORY: "cloud_tests"
stage: test
variables:
TEST_CONFIG_DIRECTORY: default_tests
script:
- echo "PRODUCT TYPE -> $PRODUCT_TYPE"
- echo "Run script with $TEST_CONFIG_DIRECTORY as test config directory"
Running an schedule with RODUCT_TYPE=cloud, the output is:
PRODUCT TYPE -> cloud
Run script with default_tests as test config directory
I have deleted the first rule and leaving only the second one and the rule to overwrite the variable worked.
Output:
PRODUCT TYPE -> cloud
Run script with cloud_tests as test config directory
Related
I am trying to trigger a release job on master branch using slack slash commands, the job is triggered but i can't seem to get or read the passed argument.
Per the docs of gitlab we can pass arguments to run a job but how to read the argument is not specified.
Here's the slack slash command:
/gitlab projectX run slack:chatops hello
Here's the job in the gitlab-ci.yml
slack:chatops:
stage: chatops
rules:
- if: $CI_PIPELINE_SOURCE == "chat"
script:
- echo "Hello World, job argument: "$1
Anyone already tried using job arguments?
SOLUTION
I found the solution after carefully re-reading the ChatOps docs for Gitlab where there's a CHAT_INPUT variable that contains all arguments as a string and the previous job becomes:
slack:chatops:
stage: chatops
rules:
- if: $CI_PIPELINE_SOURCE == "chat"
script:
- echo "Hello World, job argument: $CHAT_INPUT"
A different page in the docs mention some variables that become available. https://docs.gitlab.com/ee/ci/chatops/index.html
ChatOps passes the following CI/CD variables to the job:
CHAT_INPUT contains any additional arguments.
CHAT_CHANNEL is set to the name of channel the action was triggered in.
CHAT_USER_ID is set to the chat service’s user ID of the user who triggered the slash command.
I am trying to run my test suit using GitLab with annotations so suppose i have 4 Scenario defined out of which two are for regression and 2 are sanity but when pass tag named regression it run my regression hook now, I want a solution if I don't pass any tag it should run sanity hook
stages:
- build
cucumber_test:
stage: build
tags: [regression , sanity]
allow_failure: false
script:
- mvn "clean" "test" "-Dcucumber.filter.tags=#%Tag%"
rules:
- if: '$Tag == "reg"'
allow_failure: true
artifacts:
paths:
- Report
when: always
enter image description here
Because your only rule requires a specific value for Tag, the job will only be present in that circumstance.
I want a solution if I don't pass any tag it should run sanity hook
What you probably want to do here is set a default value defined in variables:. Additionally, you need to add a default rule to make sure the job runs even when the Tag value is not reg.
variables:
Tag: "sanity" # the default if none is provided manually
rules:
- if: '$Tag == "reg"'
allow_failure: true
- when: on_success # run this job normally, even when $Tag is not "reg"
I want a step in the build process only to run on the master branch, if there where changes to the src folder.
My .gitlab-ci.yml file thus contains:
build:php:
stage: build
image: alpine
interruptible: true
needs: [ "test:php" ]
script:
- do stuff // abreviated for simplicity
rules:
- if: $LANGUAGE_RELEASE
when: never
- if: '$CI_COMMIT_REF_SLUG == "master"' # run for production test branch
- changes:
- src/*
However, the issue here is, that it also runs on the dev branch, when I change anything.
Question: Is the a way to have this step only run, both conditions (the branch and the changes) are met?
When using the rules keyword, the rules:if clause may be used, with the variable $CI_COMMIT_BRANCH.
Thus, something like below to specify master as the only branch to run the job:
build:php:
stage: build
# ...
rules:
- if: '$CI_COMMIT_BRANCH == "master"'
# ...
(Rules are applied in order)
The documentation reference for common if clauses available is here.
Now to combine an if and changes rule, you'll need to use
build:php:
stage: build
# ...
rules:
- if: '$CI_COMMIT_BRANCH == "master"'
changes:
- file1 # single file
- folder/**/* # folder including all files and subfolders
# ...
You can read more about changes used in rules here and read the full changes specification here.
With the initial setup there where two issues:
the changes where seen as a new rule (since they had a - in front)
src/* only takes the src folder in consideration, not sub folders, for that you'll need src/**/*
It is also possible to use the only keyword to specify master as the only branch to run the job. Despite being simple, this is no longer encouraged and it cannot be used together with rules (only/except reference).
Example:
build:php:
stage: build
# ...
only:
- master
# ...
There is no way to run rules:changes on the master branch.
Gitlab docs says:
You should use rules: changes only with branch pipelines or merge
request pipelines. You can use rules: changes with other pipeline
types, but rules: changes always evaluates to true when there is no
Git push event. Tag pipelines, scheduled pipelines, manual pipelines,
and so on do not have a Git push event associated with them.
It means changes gives always true if there is different type than branches or merge_requests
It seems rules replaces only/except functionality in the latests GitLab versions.
Before, specifying that a job had to be executed only for master branch, for example, was very straightforward.
How would that be done with rules?
I'm guessing GitLab provides some variable that specifies the current branch's name, but I cannot find that. The only examples I see are regarding merge requests.
In other words, if I have the following job, how to restrict it to run only in potato branch?
unit_tests:
stage: test
script: dotnet vstest test/*UnitTests/bin/Release/**/*UnitTests.dll --Blame
rules:
- exists:
- test/*UnitTests/*UnitTests.csproj
I guess this would be it:
unit_tests:
stage: test
script: dotnet vstest test/*UnitTests/bin/Release/**/*UnitTests.dll --Blame
rules:
- if: $CI_COMMIT_BRANCH == "potato"
Here are the variable references:
https://docs.gitlab.com/ee/ci/variables/predefined_variables.html
Here is an example from gitlab-runner project source code itself
https://gitlab.com/gitlab-org/gitlab-runner/-/blob/main/.gitlab/ci/test.gitlab-ci.yml
job-name:
script:
- echo "i am potato"
rules:
- if: '$CI_COMMIT_BRANCH == "potato"'
How to set gitlab-ci varibales through script not just in "varibales" section in .gitlab-ci.yaml?So that I can set variables in one job and use in different job
There is currently no way in GitLab to pass environment variable between stages or jobs.
But there is a request for that: https://gitlab.com/gitlab-org/gitlab/-/issues/22638
Current workaround is to use artifacts - basically pass files.
We had a similar use case - get Java app version from pom.xml and pass it to various jobs later in the pipeline.
How we did it in .gitlab-ci.yml:
stages:
- prepare
- package
variables:
VARIABLES_FILE: ./variables.txt # "." is required for image that have sh not bash
get-version:
stage: build
script:
- APP_VERSION=...
- echo "export APP_VERSION=$APP_VERSION" > $VARIABLES_FILE
artifacts:
paths:
- $VARIABLES_FILE
package:
stage: package
script:
- source $VARIABLES_FILE
- echo "Use env var APP_VERSION here as you like ..."
If you run a script you can set an environment variable
export MY_VAR=the-value
once the environment variable is set it should persist in the current environment.
Now for why you do not want to do that.
A tool like Gitlab CI is meant to achieve repeatability in your
artifacts. Consistency is the matter here. What happens if a second job
has to pick up a variable from the first? Then you have multiple paths!
# CI is a sequence
first -> second -> third -> fourth -> ...
# not a graph
first -> second A -> third ...
\> second B />
How did you get to third? Now if you had to debug third which path do you test? If the build in third is broken who is responsible second A or second B?
If you need a variable use it now, not later in another job/script. Whenever you
want to write a longer sequence of commands make it a script and execute the script!
You can use either Artifact or Cache to achieve this, see the official documentation for more information around Artifact and Cache:
https://docs.gitlab.com/ee/ci/caching/#how-cache-is-different-from-artifacts