# CI/CD pipeline Refer to [CI/CD pipelines] and [CI/CD pipeline templates].
Also check [Use CI/CD configuration from other files] and [Use extends to reuse configuration sections]. 1. [Specify when to run jobs](#specify-when-to-run-jobs) 1. [Specify when to run entire pipelines](#specify-when-to-run-entire-pipelines) 1. [External secrets](#external-secrets) 1. [API](#api) 1. [Git options](#git-options) 1. [Troubleshooting](#troubleshooting) 1. [Pipeline fails with error `You are not allowed to download code from this project`](#pipeline-fails-with-error-you-are-not-allowed-to-download-code-from-this-project) 1. [Further readings](#further-readings) 1. [Sources](#sources) ## Specify when to run jobs Refer [Specify when jobs run with `rules`][specify when jobs run with rules] and the [`rules` syntax reference](https://docs.gitlab.com/ee/ci/yaml/#rules). Use the `rules` key and specify the conditions the job needs. > The `only`/`except` keywords have been deprecated by the `rules` keyword, and cannot be used together.
> This means one might be forced to use `only`/`except` if one is including a pipeline that is already using them. Rules are evaluated when the pipeline is created, **in order**, until the first applies. The rest are ignored. The `rules`key accepts an array of rules.
Each rule: - Must have **at least one** of: - `if`, to run a job when specific conditions are met. - `changes`, to run a job when specific files changed. - `exists`, to run a job when certain files exist in the repository. - `when`, to run a job when exact conditions are met. - Can have **zero or more** of: - `allow_failure`, to allow a job to fail without stopping the pipeline.
Defaults to `false`. - `needs`, to specify conditions for the job to run. - `variables`, to define specific variables for the job. - `interruptible`, to cancel the current job should another pipeline start. Multiple keys from the above lists can be combined to create complex rules. `when` accepts the following: - `on_success` (default): run the job only when no jobs in earlier stages fail, or the failing ones are allowed to fail with `allow_failure: true`.
This is the default behavior when one combines `when` with `if`, `changes`, or `exists`. - `on_failure`: run the job only when at least one job in an earlier stage fails. - `never`: don't run the job regardless of the status of jobs in earlier stages. - `always`: run the job regardless of the status of jobs in earlier stages. - `manual`: add the job to the pipeline as a manual job. When this condition is used, `allow_failure`for the job defaults to `false`. - `delayed`: add the job to the pipeline as a delayed job. Jobs are **added** to the pipeline if: - An `if`, `changes`, or `exists` rule matches **and** the rule is configured with `when: on_success` (default if not defined), `when: delayed`, or `when: always`. - A rule is reached that only consists of `when: on_success`, `when: delayed`, or `when: always`. Jobs are **not** added to the pipeline if: - No rule matches. - A rule matches **and** the rule is configured with `when: never`. Gotchas: - Tag pipelines, scheduled pipelines, and manual pipelines do **not** have a Git push event associated with them. - `changes` always evaluates to true for new branch pipelines or when there is no Git push event.
This means it will try to run on tag, scheduled and manual pipelines. Use `changes.compare_to` to specify the branch to compare against. - `changes` and `exists` allow a maximum of 50 patterns or file paths. - Multiple entries in the `changes` condition are validated in an `OR` fashion. - Glob patterns in `changes` and `exists` are interpreted with Ruby's `File.fnmatch` function using the `File::FNM_PATHNAME | File::FNM_DOTMATCH | File::FNM_EXTGLOB` flag. - The [`push` pipeline source](https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#push-events) should™ limit jobs to code changes or deliberate pushes.
Scheduled pipelines should™ avoid triggering jobs with this condition as they present a `schedule` source instead. Using the `merge_request_event` source in place of `push` prevents the job to run should somebody push to the default branch, even though [the documentation clearly states it includes merges](https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#merge-request-events). [Linting](https://docs.gitlab.com/ee/ci/lint.html#check-cicd-syntax) and [simulations](https://docs.gitlab.com/ee/ci/lint.html#simulate-a-pipeline) seem to accept using other ways, but then the pipeline resulted to be **invalid** after committing those _"validated"_ changes: > 🛑 Unable to create pipeline > > Failed to parse rule for test-job: rules:changes:compare_to is not a valid ref Examples:
Run when some specific files change ```yaml docker-build: rules: - changes: - cmd/* - go.* - Dockerfile pulumi-update: rules: # This job should only be created for changes to the main branch, and only if any program-related file changed. - if: >- $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "push" changes: paths: - infra/*.ts - infra/packages.json - when: never ``` The condition above will make the job run only when a change occurs: - to any file in the `cmd` directory - to any file in the repository's root directory which name starts with `go` (like `go.mod` or `go.sum`) - to the `Dockerfile` in the repository's root directory
Run on schedules ```yaml docker-build: rules: - if: $CI_PIPELINE_SOURCE == "schedule" docker-run: only: - schedule ``` Refer [Using GitLab scheduled pipelines simplified 101] to configure and activate schedules.
Manually trigger scheduled pipelines from the UI or using the API: ```plaintext POST /projects/:id/pipeline_schedules/:pipeline_schedule_id/play ``` ```sh curl -X POST -H "PRIVATE-TOKEN: glpat-m-…" "https://gitlab.example.com/api/v4/projects/42/pipeline_schedules/1/play" ``` The triggered pipeline runs immediately.
The next scheduled run of the pipeline is **not** affected.
Only run on specific events ```yaml docker-build: rules: - if: $CI_PIPELINE_SOURCE == 'merge_request_event' - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH - # Disable for all other conditions when: never ```
Run on all conditions except specific ones ```yaml docker-build: rules: - if: $CI_PIPELINE_SOURCE == 'merge_request_event' when: never ```
## Specify when to run entire pipelines Refer the [`workflow.rules` syntax reference](https://docs.gitlab.com/ee/ci/yaml/#workflowrules). The `workflow.rules` keyword is similar to the `rules` keyword defined in jobs, but controls whether or not a whole pipeline is created.
When no rules evaluate to `true`, the pipeline as a whole will not run. ```yaml workflow: rules: - # Override the globally-defined DEPLOY_VARIABLE on commits on the default branch. if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH variables: DEPLOY_VARIABLE: "deploy-production" - # Add a new variable on commits containing 'feature'. if: $CI_COMMIT_REF_NAME =~ /feature/ variables: IS_A_FEATURE: "true" - # Skip on commits ending with '-draft'. if: $CI_COMMIT_TITLE =~ /-draft$/ when: never - # Run for merge requests where key files changed. if: $CI_PIPELINE_SOURCE == "merge_request_event" changes: - packages.json - when: always # Run the pipeline in other cases. ``` ## External secrets Refer [Using external secrets in CI]. ## API Refer [Pipeline schedules API]. ## Git options Refer [Push options]. ```sh # Skip *branch* pipelines for the latest push. # Does *not* skip merge request pipelines or pipelines for integrations. git push -o 'ci.skip' # Skip pipelines *for integrations* for the latest push. # Does *not* skip branch or merge request pipelines. git push -o 'integrations.skip_ci' # Provide variables to pipelines created due to the push. # Passes variables only to *branch* pipelines, and *not* to merge request pipelines. git push -o ci.variable="MAX_RETRIES=10" -o ci.variable="MAX_TIME=600" ``` ## Troubleshooting ### Pipeline fails with error `You are not allowed to download code from this project` Error message example: ```txt Getting source from Git repository 00:00 Fetching changes with git depth set to 20... Reinitialized existing Git repository in /builds/myProj/myRepo/.git/ remote: You are not allowed to download code from this project. fatal: unable to access 'https://gitlab.com/myProj/myRepo.git/': The requested URL returned error: 403 ``` Root cause: the user starting the pipeline does not have enough privileges to the repository. Solution: give that user _developer_ access or have somebody else with enough privileges run it. ## Further readings - [Gitlab] - [CI/CD pipelines] - [Customize pipeline configuration] - [Predefined CI/CD variables reference] - [Pipeline schedules API] - [Using external secrets in CI] ### Sources - [Specify when jobs run with `rules`][specify when jobs run with rules] - [Using GitLab scheduled pipelines simplified 101] - [Debugging CI/CD pipelines] - [Push options] - [Validate GitLab CI/CD configuration] [gitlab]: README.md [ci/cd pipeline templates]: https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates [ci/cd pipelines]: https://docs.gitlab.com/ee/ci/pipelines/ [customize pipeline configuration]: https://docs.gitlab.com/ee/ci/pipelines/settings.html [debugging ci/cd pipelines]: https://docs.gitlab.com/ee/ci/debugging.html [pipeline schedules api]: https://docs.gitlab.com/ee/api/pipeline_schedules.html [predefined ci/cd variables reference]: https://docs.gitlab.com/ee/ci/variables/predefined_variables.html [push options]: https://docs.gitlab.com/ee/user/project/push_options.html [specify when jobs run with rules]: https://docs.gitlab.com/ee/ci/jobs/job_rules.html [use ci/cd configuration from other files]: https://docs.gitlab.com/ee/ci/yaml/includes.html [use extends to reuse configuration sections]: https://docs.gitlab.com/ee/ci/yaml/yaml_optimization.html#use-extends-to-reuse-configuration-sections [using external secrets in ci]: https://docs.gitlab.com/ee/ci/secrets/index.html [validate gitlab ci/cd configuration]: https://docs.gitlab.com/ee/ci/lint.html [using gitlab scheduled pipelines simplified 101]: https://hevodata.com/learn/gitlab-scheduled-pipeline/