Gitlab Pipeline – when – What is when in GitLab CI/CD?

DevOps

MOTOSHARE 🚗🏍️
Turning Idle Vehicles into Shared Rides & Earnings

From Idle to Income. From Parked to Purpose.
Earn by Sharing, Ride by Renting.
Where Owners Earn, Riders Move.
Owners Earn. Riders Move. Motoshare Connects.

With Motoshare, every parked vehicle finds a purpose. Owners earn. Renters ride.
🚀 Everyone wins.

Start Your Journey with Motoshare

The when keyword in a GitLab CI/CD job definition controls the conditions under which a job is executed. It’s primarily used to handle scenarios like running jobs only on success, on failure, always, or requiring manual intervention.

Note: While when can be used as a top-level keyword within a job, it is also a crucial component of the more powerful and flexible rules: syntax. The rules: keyword is now the recommended way to control job execution for most complex scenarios. This example will focus on when as a top-level job attribute.


Example .gitlab-ci.yml with when:

YAML

# .gitlab-ci.yml

stages:
  - build
  - test
  - deploy
  - notify
  - cleanup

default:
  image: alpine:latest

# Job 1: Standard job, runs on success of previous stage (default behavior)
build_project:
  stage: build
  # when: on_success # This is the default, so it's often omitted
  script:
    - echo "--- Building Project ---"
    - sleep 5
    - echo "Build successful!"

# Job 2: Another standard job
test_feature_A:
  stage: test
  script:
    - echo "--- Testing Feature A ---"
    - sleep 3
    - echo "Feature A tests PASSED."

# Job 3: This job is designed to fail, to demonstrate 'on_failure' and 'always'
test_feature_B_fails:
  stage: test
  script:
    - echo "--- Testing Feature B (designed to fail) ---"
    - sleep 2
    - echo "Feature B encountered an error!"
    - exit 1 # Explicitly fail the job
  allow_failure: true # Allow this job to fail without failing the whole pipeline,
                      # so we can see 'on_failure' and 'always' jobs run.
                      # In a real scenario, you might not allow failure if it's a critical test.

# Job 4: Runs only if a previous job in the same pipeline (from an earlier stage) failed
cleanup_on_failure:
  stage: cleanup # Placed in a later stage to observe effect
  when: on_failure
  script:
    - echo "--- Cleanup on Failure ---"
    - echo "A previous critical job failed. Performing cleanup tasks."
    - echo "CI_PIPELINE_ID: $CI_PIPELINE_ID, Job that might have failed is in an earlier stage."

# Job 5: Runs regardless of the success or failure of jobs in previous stages
notify_always:
  stage: notify # Placed in a later stage
  when: always
  script:
    - echo "--- Notify Always ---"
    - echo "This notification runs regardless of previous job statuses (success or failure)."
    - echo "Pipeline finished processing up to this point."

# Job 6: Requires manual intervention to run
manual_deploy_to_staging:
  stage: deploy
  when: manual
  script:
    - echo "--- Manual Deploy to Staging ---"
    - echo "Deploying to staging environment after manual trigger..."
    - sleep 10
    - echo "Staging deployment complete."
  allow_failure: false # Optional: specify if this manual job failing should fail the pipeline

# Job 7: Runs after a delay once its stage is ready
delayed_report_generation:
  stage: notify
  when: delayed
  start_in: '1 minute' # Job will start 1 minute after the 'notify' stage is reached
                      # (and previous jobs in this stage, if any, are done)
  script:
    - echo "--- Delayed Report Generation ---"
    - echo "Generating report after a 1-minute delay..."
    - sleep 5
    - echo "Report generated."

# Job 8: Default 'on_success' behavior
final_production_deploy:
  stage: deploy
  # Relies on the default 'when: on_success'
  # This job will only run if 'build_project', 'test_feature_A', AND 'test_feature_B_fails'
  # (if 'allow_failure' was false for it) all succeeded.
  # Given 'test_feature_B_fails' has 'allow_failure: true', this job's execution
  # depends on whether the overall pipeline is considered successful up to its stage.
  # To make it clearly depend on 'test_feature_A' for this example, we could use 'needs'.
  # For simplicity here, we'll assume it runs if prior stages are "green enough".
  script:
    - echo "--- Final Production Deploy ---"
    - echo "All critical tests passed (or allowed to fail). Deploying to production."
Code language: PHP (php)

Explanation:

  1. when: Keyword:
    • Used directly within a job’s definition to specify the condition for its execution.
  2. Common when: Values:
    • on_success (Default):
      • If when is not specified, this is the default behavior.
      • The job runs only if all jobs from previous stages in the pipeline have completed successfully (or are marked with allow_failure: true and failed).
      • build_project and test_feature_A implicitly use this. final_production_deploy also implicitly uses this.
    • on_failure:
      • The job runs only if at least one job from a previous stage in the pipeline has failed (and that failing job was not marked with allow_failure: true to the extent that it stops the pipeline progression for on_success jobs).
      • cleanup_on_failure will run because test_feature_B_fails is designed to fail. Even though test_feature_B_fails has allow_failure: true, an on_failure job in a later stage will still trigger if a failure occurred.
    • always:
      • The job runs regardless of the success or failure status of jobs in previous stages, as long as the pipeline itself is running and the job’s stage is reached (or its needs dependencies are met).
      • notify_always will run whether test_feature_B_fails fails or if all test jobs had passed.
    • manual:
      • The job is added to the pipeline but is not executed automatically. It appears with a “play” icon in the GitLab UI, and a user with appropriate permissions must manually trigger it.
      • manual_deploy_to_staging demonstrates this. It’s common for deployment to sensitive environments or for optional long-running tasks.
      • You can optionally add allow_failure: true to manual jobs if their failure shouldn’t block the pipeline.
    • delayed:
      • The job is executed automatically after a specified duration once its stage is ready (all previous stage jobs or needs dependencies are complete).
      • delayed_report_generation uses start_in: '1 minute' to specify the delay. The start_in value can be a human-readable duration like '5 seconds', '10 minutes', '1 hour'.
  3. allow_failure: in test_feature_B_fails:
    • I’ve added allow_failure: true to test_feature_B_fails. This means even though this job fails:
      • The pipeline will still be considered “successful” overall if all other critical jobs pass.
      • It allows subsequent stages and jobs (like notify_always and cleanup_on_failure) to run and demonstrate their when conditions.
      • on_failure jobs will still trigger based on the fact that a job did fail, even if that failure was “allowed.”

How when Affects Pipeline Flow:

  • on_success jobs create a sequence where success in one stage gates entry into the next.
  • on_failure jobs provide a way to run specific tasks (like cleanup or notifications) only when something goes wrong.
  • always jobs ensure certain actions (like logging or final notifications) happen no matter what.
  • manual jobs introduce decision points or optional steps in the pipeline.
  • delayed jobs allow for non-critical tasks to be deferred slightly.

when within rules:

It’s important to note that when is also a key clause within the more modern rules: syntax. For example:

YAML

job_with_rules:
  script: echo "Running with rules"
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'
      when: always # This 'when' is part of the rule
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      when: manual
    - when: never # Default to not running if other rules don't match
Code language: PHP (php)

In this context, when (along with allow_failure, variables, etc.) is applied if the corresponding if, changes, or exists condition in that specific rule entry evaluates to true.

Understanding when is crucial for building pipelines that can react appropriately to different situations, manage optional steps, and handle failures gracefully.

Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x