CI/CD pipeline - stage that decide to continue or skip other stages

I have three stages:

  • check
    check if there is change on a specific external project (run as schedule).
  • test
    run a script.
  • report
    render a report from the script results.

I need to run test and report only of check found a change for example if check found the the external commit id was changed it will save this new id in a file but only after the report it will push it back to the repo.

I know about 3 ways to do it:

  1. return exit code that will fail the test, but I would like to set this test as a success.
  2. to create file artifact and check with before_script that this file a exists on every stage using extend not to repeat the code…
  3. to create child pipeline from the result of the check stage then it will go to other stages when there is a change on the external project.

I’m searching for the best solution for my problem, one that will not fail the test if it didn’t really fail. and will be the easiest to maintain. I don’t think child pipeline is the best solution here although it’s a generic way to solve the issue.
maintaining extension of before_script on every stage is slower (because it needs to run the container and the script) before it even knows the file exists and its repetitive.
If I could set VARIABLE in runtime and check this variable in the next stage or just check artifacts with rules or needs or dependencies instead of in before_script it would be also a solution.

I need your help to check that I’m not missing a proper solution to my problem.


I’ve discovered an improved approach.
I’m generating a .ignore file and treating it as an artifact.
The subsequent stage verifies the presence of this file; if found, the process proceeds. If not, the job is terminated via the API, causing all subsequent jobs to be skipped.


  - stage-1
  - stage-2
  - stage-3

  stage: stage-1
    - echo "Stage 1"
    - |-
      if [ $((RANDOM % 2)) -eq 0 ]; then
          echo "Nothing changed, no need to continue!"
          touch ./.ignore
      - ./.ignore

    - |
      if [[ -f ./.ignore ]]; then
          echo "Nothing changed, no need to continue!"
          curl --request POST --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/jobs/${CI_JOB_ID}/cancel"
          exit 0

# Will Cancel Stage 2 if .ignore file exists
  stage: stage-2
  extends: [ .check-ignore ]
    - echo "Stage 2"

# Will Skip Stage 3 if .ignore file exists
  stage: stage-3
    - echo "Stage 3"