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 rules: keyword is the recommended and most powerful way to control whether a job is added to a pipeline and under what conditions it should run. It allows for complex logic using CI/CD variables, file changes, and more, offering greater flexibility than the older only/except keywords.
A rules section is an array of individual rule objects. These rules are evaluated in order from top to bottom for each job. The first rule that matches determines the job’s behavior.
Example .gitlab-ci.yml with rules:
YAML
# .gitlab-ci.yml
stages:
- build
- test
- security
- deploy
- report
default:
image: alpine:latest
# Job 1: Runs only on pushes to the default branch (e.g., 'main' or 'master')
build_default_branch:
stage: build
script:
- echo "--- Building for default branch: $CI_DEFAULT_BRANCH ---"
- echo "Commit on branch: $CI_COMMIT_BRANCH"
rules:
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "push"'
# 'when: on_success' is implied if 'when' is not specified for an 'if' rule
# Job 2: Runs only when a Git tag is pushed
deploy_on_tag:
stage: deploy
script:
- echo "--- Deploying for tag: $CI_COMMIT_TAG ---"
rules:
- if: '$CI_COMMIT_TAG' # This condition is true if a tag is present
when: on_success # Explicitly stating the default when job should run
# Job 3: Manual job for merge requests, allows failure
test_on_merge_request:
stage: test
script:
- echo "--- Testing for Merge Request: $CI_MERGE_REQUEST_IID ---"
- echo "Source branch: $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME"
- echo "Target branch: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME"
# - exit 1 # Uncomment to simulate a failure
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
when: manual # Job will be created but needs to be started manually from the UI
allow_failure: true # If this job fails, it won't cause the whole pipeline to fail
# Job 4: Runs only if files in the 'docs/' directory have changed on a push event
build_docs:
stage: build
script:
- echo "--- Building documentation because files in 'docs/' changed ---"
rules:
- if: '$CI_PIPELINE_SOURCE == "push"' # Only consider push events for changes
changes:
- docs/**/* # Glob pattern for any file within the docs directory or its subdirectories
- README.md
# If 'changes' are detected and the 'if' condition is met, the job runs.
# Job 5: Runs only if a specific file (e.g., a Dockerfile) exists in the repository
docker_build_if_exists:
stage: build
script:
- echo "--- Dockerfile found, proceeding with Docker build ---"
# - docker build -t my-image . # Actual docker build command
rules:
- if: '$CI_COMMIT_BRANCH' # Ensure it runs for branch commits, not other events unless specified
exists:
- Dockerfile # Path to the file to check, relative to project root
# - another-required-file.txt
# If 'Dockerfile' exists and the 'if' condition is met, the job runs.
# Job 6: A job that is explicitly prevented from running in any 'push' pipeline, but could run for other types if rules were added
never_run_on_push:
stage: report
script:
- echo "This job should not run on push events."
rules:
- if: '$CI_PIPELINE_SOURCE == "push"'
when: never # Explicitly prevents the job from being added to the pipeline for push events
# - if: '$CI_PIPELINE_SOURCE == "schedule"' # Example: but it could run for schedules
# when: always
# Job 7: A job with a delayed execution for non-critical tasks
delayed_notification:
stage: report
script:
- echo "--- Sending a delayed notification ---"
rules:
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "push"'
when: delayed
start_in: '5 minutes' # Job will start 5 minutes after the pipeline completes this stage successfully
# Job 8: Catch-all rule if no other rules in this job match (optional)
# If a job has rules, and none of them match, the job is NOT added to the pipeline by default.
# To change this, you can add a final rule without an 'if' clause.
optional_job_always_manual:
stage: report
script:
- echo "This is an optional manual job."
rules:
- if: '$CI_COMMIT_BRANCH == "feature/special-feature"' # Runs normally for this specific branch
- when: manual # For all other cases where the above 'if' didn't match, make it manual
Code language: PHP (php)
Explanation:
rules:Keyword:- Used within a job definition. It takes an array of rule objects.
- Rules are evaluated in the order they are listed. The first rule that matches determines the job’s behavior.
- If no rules match for a job, the job is not added to the pipeline by default.
- Structure of a Rule:Each item in the rules array is an object that can contain several clauses:
if:: An expression that is evaluated. If true, this rule matches (unless other conditions likechangesorexistsare also present and don’t match). You use CI/CD predefined variables here.- Operators:
==(equals),!=(not equals),=~(regex match),!~(regex no match),&&(AND),||(OR – though multipleifclauses in separate rules act like OR for the job). Parentheses()can be used for grouping.
- Operators:
when:: Defines what to do if the rule matches.on_success(default ififis present andwhenis omitted): Run the job automatically if the stage is reached.manual: Add the job to the pipeline, but it requires manual action (clicking a play button) to start.delayed: Run the job automatically after a specified duration once its stage is reached and preceding jobs are complete. Requiresstart_in.never: Do not add the job to the pipeline if this rule matches.always: Run the job regardless of the status of earlier stage jobs (use with caution, often combined withallow_failure: true).
changes:: An array of file paths or glob patterns. The rule matches only if files matching these patterns have changed in the latest push (compared to the previous commit on the same branch, or for MRs, compared to the target branch).exists:: An array of file paths or glob patterns. The rule matches only if all specified files/paths exist in the repository at the commit being processed.allow_failure:: (boolean, defaults tofalse) Iftrue, the pipeline will continue to the next stage even if this job fails. This can be set per rule.variables:: Define job-specific variables if this rule matches.
build_default_branch(Job 1):if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "push"': This job runs only if the commit is on the default branch AND the pipeline was triggered by apushevent. Thewhen: on_successis implied.
deploy_on_tag(Job 2):if: '$CI_COMMIT_TAG': This job runs if the$CI_COMMIT_TAGvariable is set (meaning a Git tag was pushed).
test_on_merge_request(Job 3):if: '$CI_PIPELINE_SOURCE == "merge_request_event"': Runs for merge request events.when: manual: It will appear in the pipeline but won’t run automatically.allow_failure: true: If it fails after being run manually, the overall pipeline status won’t be marked as failed.
build_docs(Job 4):if: '$CI_PIPELINE_SOURCE == "push"': Condition based on pipeline source.changes: - docs/**/* - README.md: The job only runs if there are changes in thedocsdirectory or theREADME.mdfile for that push event.
docker_build_if_exists(Job 5):if: '$CI_COMMIT_BRANCH': A general condition to ensure it runs for branches.exists: - Dockerfile: The job runs only if aDockerfileexists at the root of the repository for the given commit.
never_run_on_push(Job 6):if: '$CI_PIPELINE_SOURCE == "push"'combined withwhen: never: This effectively blocks the job from running on any push event. You could add other rules below it to make it run for other events (e.g., schedules).
delayed_notification(Job 7):when: delayedandstart_in: '5 minutes': This job will automatically start 5 minutes after its stage (report) is reached and preceding jobs in that stage (if any) are complete, but only for pushes to the default branch.
optional_job_always_manual(Job 8):- The first rule
if: '$CI_COMMIT_BRANCH == "feature/special-feature"'makes the job run normally (auto) for this specific branch. - The second rule
when: manualhas noif. This acts as a catch-all. If the first rule didn’t match, this second rule will match, and the job will be added as a manual job.
- The first rule
Benefits of rules::
- Clarity: Conditions are often easier to read and understand than complex
only/exceptcombinations. - Power: Allows more complex conditions, including checks for file changes (
changes), file existence (exists), and variable comparisons with regex. - Control: Provides fine-grained control over
whena job runs (manual, delayed) andallow_failureon a per-rule basis. - Single Source of Truth: Replaces the need for both
onlyandexcept.
rules: is a fundamental concept for modern GitLab CI/CD, allowing you to build highly efficient and precise pipelines.