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 except keyword in a job definition specifies a blacklist of conditions under which that job should not be created and run. If any of the conditions defined in except are met for a given pipeline trigger (like a push to a specific branch, a tag creation, etc.), the job will be skipped. If none of the except conditions are met, the job will be considered for creation (and will run if no only clause prevents it, or if it has no only clause).
Important Note: Just like with only, while except still functions, GitLab’s current best practice and strong recommendation is to use the rules: keyword instead. rules: offer significantly more power, flexibility, and clarity for controlling when jobs run or don’t run. This example is provided because you specifically asked about except. Please consider using rules: for your future and more complex pipeline configurations.
Example .gitlab-ci.yml with except:
YAML
# .gitlab-ci.yml
stages:
- build
- test
- deploy
- cleanup
default:
image: alpine:latest
# Job 1: Runs on all branches EXCEPT 'main'
build_on_feature_branches:
stage: build
except:
- main # Can also be written as refs: - main
script:
- echo "--- Building on a feature branch (not main) ---"
- echo "Current branch: $CI_COMMIT_REF_NAME"
# Job 2: Runs for all pipeline triggers EXCEPT when Git tags are pushed
test_everything_but_tags:
stage: test
except:
- tags # Special keyword for any tag
script:
- echo "--- Running tests (not for a tag) ---"
- echo "Pipeline source: $CI_PIPELINE_SOURCE"
- echo "This job does NOT run when a tag is pushed."
# Job 3: Runs for all pipeline triggers EXCEPT for merge request events
deploy_to_staging_not_for_mr:
stage: deploy
except:
- merge_requests # Special keyword for merge request pipelines
script:
- echo "--- Deploying to Staging (not for an MR) ---"
- echo "This job runs for direct pushes, tags, schedules, etc., but NOT for merge requests."
# Job 4: Runs for all pipeline triggers EXCEPT for scheduled pipelines
manual_cleanup_only:
stage: cleanup
except:
- schedules # Special keyword for scheduled pipelines
script:
- echo "--- Manual Cleanup Task (not for schedules) ---"
- echo "This job does NOT run for scheduled pipelines."
# Job 5: Excludes multiple specific branches
# This job runs unless the branch is 'develop' OR 'release/v1.0'
build_except_specific_branches:
stage: build
except:
- develop
- release/v1.0
script:
- echo "--- Building (excluding develop and release/v1.0) ---"
- echo "Current branch is $CI_COMMIT_REF_NAME."
# Job 6: Runs always (no 'only' or 'except' clause)
# This job is included to show the default behavior.
always_run_job_default:
stage: test
script:
- echo "--- Always Run Job (Default Behavior) ---"
- echo "This job has no 'only' or 'except', so it runs for any pipeline trigger by default"
- echo "(unless workflow:rules prevent the pipeline itself, or a more specific 'only' restricts it)."
# Job 7: Using 'refs' with 'except' (though 'rules' is better for this)
# This job does NOT run for branches starting with 'legacy-' OR for the 'archive' branch.
# Note: For complex logic, 'rules' is much clearer.
advanced_except_example:
stage: cleanup
except:
refs:
- /^legacy-.*$/ # Regex for branches starting with legacy-
- archive
script:
- echo "--- Advanced Except Example ---"
- echo "Running because this is not a legacy or archive branch."
- echo "Branch: $CI_COMMIT_BRANCH"
Code language: PHP (php)
Explanation:
except:Keyword:- Used within a job definition to specify conditions under which the job should not run. It acts as a blacklist.
- The job will be skipped if any of the conditions listed under
exceptare met for the event that triggered the pipeline.
build_on_feature_branchesJob:except: - main: This job will be created and run for any branch push, unless the push is to themainbranch.
test_everything_but_tagsJob:except: - tags: This job will run for any pipeline trigger (branch pushes, merge requests, schedules, etc.) except when a Git tag is pushed.
deploy_to_staging_not_for_mrJob:except: - merge_requests: This job will run for any pipeline trigger except for pipelines associated with merge request events.
manual_cleanup_onlyJob:except: - schedules: This job will run for any pipeline trigger except when the pipeline is triggered by a predefined schedule.
build_except_specific_branchesJob:except: - develop - release/v1.0: This job will be skipped if the pipeline is for thedevelopbranch OR for therelease/v1.0branch. For all other branches/events, it will run.
always_run_job_defaultJob:- This job has no
except(oronlyorrules) clause. By default, such a job is included in all pipelines (unless a globalworkflow:rulesconfiguration prevents the pipeline itself from running).
- This job has no
advanced_except_exampleJob:- This demonstrates the
refskeyword withinexcept. refs: - /^legacy-.*$/ - archive: The job will be skipped if the ref is a branch starting with “legacy-” (regex match) OR if it’s thearchivebranch.- Complexity Note: As with
only, when you start combining conditions or using regex withexcept, therules:syntax often provides a clearer and more maintainable way to express the logic.
- This demonstrates the
Key Concepts and Behavior:
- Blacklist:
exceptdefines when a job should not run. If any condition inexceptis met, the job is skipped. - Multiple Conditions: If you list multiple items in the
exceptarray (e.g.,except: [main, develop]), the job is skipped if the pipeline event matches any of those items (logical OR). - Precedence: Similar to
only, job-levelexceptis evaluated after globalworkflow:rules. - Counterpart
only:onlyis a whitelist. You can useonlyandexcepttogether in the same job definition, but this is strongly discouraged as it can lead to very complex and hard-to-understand logic.rules:handles these scenarios much better. - Special Keywords: The same special keywords available for
only(liketags,merge_requests,schedules,branches,web,api, etc.) can also be used withexcept.
Recommendation: Use rules: Instead
It’s worth reiterating: GitLab now strongly recommends using rules: for controlling job execution due to its superior clarity and power.
Here’s a quick example of how build_on_feature_branches might look with rules:
YAML
build_on_feature_branches_with_rules:
stage: build
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: never # Don't run if it's the main branch
- when: on_success # Run in all other cases (e.g., feature branches)
script:
- echo "Building on a feature branch (using rules)"
- echo "Current branch: $CI_COMMIT_REF_NAME"
Code language: PHP (php)
rules: allow for more complex if conditions using CI/CD variables, support when: manual, when: delayed, allow_failure, exists (for checking file existence), and generally make your pipeline’s conditional logic much more explicit and maintainable.
While understanding except is useful, especially if you encounter it in older GitLab CI configurations, aim to use rules: for any new CI/CD pipeline development or when refactoring existing ones.