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.
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:
when:Keyword:- Used directly within a job’s definition to specify the condition for its execution.
- Common
when:Values:on_success(Default):- If
whenis 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: trueand failed). build_projectandtest_feature_Aimplicitly use this.final_production_deployalso implicitly uses this.
- If
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: trueto the extent that it stops the pipeline progression foron_successjobs). cleanup_on_failurewill run becausetest_feature_B_failsis designed to fail. Even thoughtest_feature_B_failshasallow_failure: true, anon_failurejob in a later stage will still trigger if a failure occurred.
- 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
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
needsdependencies are met). notify_alwayswill run whethertest_feature_B_failsfails or if all test jobs had passed.
- 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
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_stagingdemonstrates this. It’s common for deployment to sensitive environments or for optional long-running tasks.- You can optionally add
allow_failure: trueto 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
needsdependencies are complete). delayed_report_generationusesstart_in: '1 minute'to specify the delay. Thestart_invalue can be a human-readable duration like'5 seconds','10 minutes','1 hour'.
- The job is executed automatically after a specified duration once its stage is ready (all previous stage jobs or
allow_failure:intest_feature_B_fails:- I’ve added
allow_failure: truetotest_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_alwaysandcleanup_on_failure) to run and demonstrate theirwhenconditions. on_failurejobs will still trigger based on the fact that a job did fail, even if that failure was “allowed.”
- I’ve added
How when Affects Pipeline Flow:
on_successjobs create a sequence where success in one stage gates entry into the next.on_failurejobs provide a way to run specific tasks (like cleanup or notifications) only when something goes wrong.alwaysjobs ensure certain actions (like logging or final notifications) happen no matter what.manualjobs introduce decision points or optional steps in the pipeline.delayedjobs 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.