Gitlab CI is it possible to run a job based on previous job that may or may not run? - gitlab

I have a job that will run on these condition
if it is on schedule or develop branch, also run this automatically
if it is a merge request with file change under docker directory, run this automatically
if it is s merge request without file change under docker directory, manual run
it_build:
stage: build
rules:
- if: $CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "develop"
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
changes:
- docker/*
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
when: manual
This job will build images and push to registry. There will be a schedule run every day to update images. If there is some change in docker script, that merge request will also run this job too, or developer can run it manually as well if needed. With this assume that images always in registry and ready to be pulled. So this job is not need to run in merge request.
Then I have another job that will pull these images publish by the above job (it_build). Is it possible to have condition like
(if it_build is being run automatically because some file change under docker directory, wait for it to finish to update images before run another job) && (if it_build is not run, go ahead and run another job. This job will pull image store in registry)
Basically I'm just asking that is there a way to add needs statement inside rules as another condition for the other job.

Related

Job doesn't appear in the pipeline jobs list after adding multiple merge request conditions

What I wanted to achieve, was launching deployment job automatically after all these conditions are met together:
merge request points to target branch named dev,
commit branch is dev,
merge request is accepted.
And I wrote the following code (backslashes are added for better view; they're not in the original .gitlab-ci.yml file):
deploy_te_test:
extends: .job-template
stage: deploy_test
rules:
- if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "dev" \
&& $CI_COMMIT_BRANCH == "dev" \
&& $CI_MERGE_REQUEST_APPROVED'
when: always
After merging that to dev branch, the job didn't even appear on the list of jobs. So I thought, that maybe the 2nd condition, the commit branch set to dev isn't treated as a commit branch in terms of merge request, so I left just these two conditions: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "dev" && $CI_MERGE_REQUEST_APPROVED', to see no success again: the job didn't appear in the list of pipeline jobs.
How to configure the job to be always launched when a merge request to dev branch gets approved?

Splitting stages into multiple pipelines

Lets assume I have few stages
stages:
- mr:stage1
- mr:stage2
- mr:stage3
On all jobs I have rule:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
So I am getting pipeline like that
How can I split my 3 stages into 2 pipelines? For example I would like to have mr:stage1 and mr:stage2 in one pipeline and if this pipeline is successful, mr:stage3 will invoke in separate pipeline.
Thx for help
Each project or repository in GitLab has a single .gitlab-ci.yml file, and therefore a single pipeline. There is no way to have multiple pipelines like this.
You can include other yml files in your base .gitlab-ci.yml file, but this is solely for your convenience as the pipeline author. At runtime, the included files are copy and pasted into a single yml file, so there is still only ever a single pipeline.
However, that single pipeline can look drastically different depending on your use cases.
Let's say you have 3 jobs that only run on push events to a non-default branch. When you push to the default branch, these 3 jobs will not run. Let's say you have another 2 jobs that only run when there's a push event to the default branch. When you push here, these jobs will run, but if you push to a feature branch, they will not.
This scenario might look like this:
stages:
- build
- test
- deploy
Pull in Backend Dependencies nonprod:
stage: build
rules:
- if: $CI_PIPELINE_SOURCE === 'push' && $CI_COMMIT_REF_NAME !== $CI_DEFAULT_BRANCH
when: always
- when: never
script:
- # run your dependency manager to pull in backend dependencies, ie Composer for PHP, including dependencies only used in lower environments, like Unit Testing libraries, etc.
# ...
Pull in Frontend Dependencies nonprod:
stage: build
rules:
- if: $CI_PIPELINE_SOURCE === 'push' && $CI_COMMIT_REF_NAME !== $CI_DEFAULT_BRANCH
when: always
- when: never
script:
- # Run npm install, etc., including those only needed in lower environments
# ...
Pull in Backend Dependencies Prod:
stage: build
rules:
- if: $CI_PIPELINE_SOURCE === 'push' && ($CI_COMMIT_REF_NAME === $CI_DEFAULT_BRANCH || $CI_COMMIT_TAG !== '')
when: always
- when: never
script:
- # run your dependency manager to pull in backend dependencies, ie Composer for PHP, without dev dependencies
# ...
Run Unit Tests:
stage: tests
rules:
- if: $CI_PIPELINE_SOURCE === 'push' && $CI_COMMIT_REF_NAME !== $CI_DEFAULT_BRANCH
when: always
- when: never
script:
- # run our unit tests
Deploy to production:
stage: deploy
rules:
- if: $CI_PIPELINE_SOURCE === 'push' && $CI_COMMIT_REF_NAME === $CI_DEFAULT_BRANCH
when: always
- when: never
script:
- # deploy steps to prod
etc.
For the first two jobs, the rules say "If the event is a Push AND the branch isn't the default branch, always run this job. Otherwise, if any of these conditions isn't true, never run this job".
The Prod job's rules say "If the event is a Push AND the branch IS the default branch, OR it's a tag, run this job. Otherwise never run it."
Then we only run our unit test job for feature branches, and we only deploy to production for the default branch.
Therefore, depending on which branch/tag is pushed to, the pipeline instance will look very different. For a feature branch we'll have 2 build jobs, and a test job (2 stages). For the default branch, we'll have a single build job and a deploy job.
The same is true if you need to handle sources other than 'push'. For example, if you have a job that only runs when triggered via the API (or from another pipeline instance or another project's pipeline), you'd look to see if the $CI_PIPELINE_SOURCE variable holds the string trigger.

How to make one job only run after another job passes in a GitLab pipeline

From what I have just ran into, the "needs" line in a gitlab-ci.yml file only checks to see if the job that is defined in the "needs" line is being run - not if it passes or fails.
I ran the below code in my pipeline and the "build-latest" job runs even if the "test-
tag" job fails.
I only want the "build-latest" job to run if the "test-tag" job passes.
How is this achieved?
build-latest:
stage: publish
image:
name: gcr.io/go-containerregistry/crane:debug
entrypoint: [""]
rules:
#- if: $CI_COMMIT_TAG != null
- if: $CI_COMMIT_REF_NAME == "add-latest-tagging"
when: always
needs:
- test-tag
script:
- crane auth login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
The issue lies with the fact that you added
when: always
It is true that since you specified needs, the build-latest job will need the job test-tag to execute first.
After test-tag job concluded it will evaluate if it should execute the build-latest job.
By adding the always clause to the build-latest job will force it to execute, even if the test-tag fails. Provided test-tag job has at least concluded
Long story sort, you should remove the when always clause
If you want a job to run only when one or more previous jobs pass, then you want to put it in a separate stage.
Not sure how you've broken up the jobs without more of the CI file, but assuming:
test-tag job is in stage: test
stage: publish comes after test
Then it should work the way you want simply by removing the needs: option from your build-latest job.

How do I check how Gitlab CI rules are being evaluated?

I'm trying to ensure that my Gitlab CI only runs on a particular host, regardless of the Enable/Disable CI status in the GUI. I have this at the top of my .gitlab-ci.yml file, but CI now runs nowhere. I've confirmed that the host value is as expected by disabling my header and printing it from one of the script jobs.
workflow:
rules:
- if: '$CI_SERVER_HOST != "run-here.example.com"'
when: never
In other words, I'm sure that the value of CI_SERVER_HOST is run-here.example.com, and my pipelines still don't run anywhere. Removing the above header causes them to run everywhere.
You will also have to add an always to run it in other cases.
workflow:
rules:
- if: '$CI_SERVER_HOST != "run-here.example.com"'
when: never
- when: always
Could you check with this workflow.

Gitlab CI can trigger other project pipeline stage?

I have an A project and an E2E project. I want to deploy A project trigger E2E pipeline run test but I just want the trigger test stage. we don't need trigger E2E to build deploy ...etc
e2e_tests:
stage: test
trigger:
project: project/E2E
branch: master
strategy: depend
stage: test
I have tried to use the stage in config. but got error unknown keys: stage
have any suggestions?
In your E2E project, the one that receives the trigger, you can tell a job to only run when the pipeline source is a trigger using the rules syntax:
build-from-trigger:
stage: build
when: never
rules:
- if: "$CI_COMMIT_REF_NAME == 'master' && $CI_PIPELINE_SOURCE == 'trigger'
when: always
script:
- ./build.sh # this is just an example, you'd run whatever you normally would here
The first when statement, when: never sets the default for the job. By default, this job will never run. Then using the rule syntax, we set a condition that will allow the job to run. If the CI_COMMIT_REF_NAME variable (the branch or tag name) is master AND the CI_PIPELINE_SOURCE variable (whatever kicked off this pipeline) is a trigger, then we run this job.
You can read about the when keyword here: https://docs.gitlab.com/ee/ci/yaml/#when, and you can read the rules documentation here: https://docs.gitlab.com/ee/ci/yaml/#rules

Resources