A monorepo pipeline that runs every job on every push spends most of its minutes proving that unchanged code still works.
frontend:tests:
stage: test
script: [npm ci, npm test]
rules:
- changes:
- resources/js/**/*
- package-lock.json
api:tests:
stage: test
script: [composer install, vendor/bin/phpunit]
rules:
- changes: [app/**/*, composer.lock, tests/**/*]
The trap is that changes compares against the previous commit on a branch and against the target on a merge request, so a job can be skipped on a push and run on the merge — which is usually the safe direction and is worth knowing before someone reports it as a bug. Anything that gates a deploy should not use this: a skipped job counts as successful, so a required check that never ran passes. Keeping the rule on test jobs and off deployment jobs is the line.