- Workflow rules
- Default image
- Default variables
- Stages
- Dependency Proxy
- Common job definitions
- 
rules,if:conditions andchanges:patterns
- Best Practices
CI configuration internals
Workflow rules
Pipelines for the GitLab project are created using the workflow:rules keyword
feature of the GitLab CI/CD.
Pipelines are always created for the following scenarios:
- 
mainbranch, including on schedules, pushes, merges, and so on.
- Merge requests.
- Tags.
- Stable, auto-deploy, and security branches.
Pipeline creation is also affected by the following CI/CD variables:
- If $FORCE_GITLAB_CIis set, pipelines are created.
- If $GITLAB_INTERNALis not set, pipelines are not created.
No pipeline is created in any other cases (for example, when pushing a branch with no MR for it).
The source of truth for these workflow rules is defined in .gitlab-ci.yml.
Default image
The default image is defined in .gitlab-ci.yml.
It includes Ruby, Go, Git, Git LFS, Chrome, Node, Yarn, PostgreSQL, and Graphics Magick.
The images used in our pipelines are configured in the
gitlab-org/gitlab-build-images
project, which is push-mirrored to gitlab/gitlab-build-images
for redundancy.
The current version of the build images can be found in the “Used by GitLab section”.
Default variables
In addition to the predefined CI/CD variables,
each pipeline includes default variables defined in
.gitlab-ci.yml.
Stages
The current stages are:
- 
sync: This stage is used to synchronize changes fromgitlab-org/gitlabtogitlab-org/gitlab-foss.
- 
prepare: This stage includes jobs that prepare artifacts that are needed by jobs in subsequent stages.
- 
build-images: This stage includes jobs that prepare Docker images that are needed by jobs in subsequent stages or downstream pipelines.
- 
fixtures: This stage includes jobs that prepare fixtures needed by frontend tests.
- 
lint: This stage includes linting and static analysis jobs.
- 
test: This stage includes most of the tests, and DB/migration jobs.
- 
post-test: This stage includes jobs that build reports or gather data from theteststage’s jobs (for example, coverage, Knapsack metadata, and so on).
- 
review: This stage includes jobs that build the CNG images, deploy them, and run end-to-end tests against Review Apps (see Review Apps for details). It also includes Docs Review App jobs.
- 
qa: This stage includes jobs that perform QA tasks against the Review App that is deployed in stagereview.
- 
post-qa: This stage includes jobs that build reports or gather data from theqastage’s jobs (for example, Review App performance report).
- 
pages: This stage includes a job that deploys the various reports as GitLab Pages (for example,coverage-ruby, andwebpack-report(found athttps://gitlab-org.gitlab.io/gitlab/webpack-report/, but there is an issue with the deployment).
- 
notify: This stage includes jobs that notify various failures to Slack.
Dependency Proxy
Some of the jobs are using images from Docker Hub, where we also use
${GITLAB_DEPENDENCY_PROXY_ADDRESS} as a prefix to the image path, so that we pull
images from our Dependency Proxy.
By default, this variable is set from the value of ${GITLAB_DEPENDENCY_PROXY}.
${GITLAB_DEPENDENCY_PROXY} is a group CI/CD variable defined in
gitlab-org as
${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/. This means when we use an image
defined as:
image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}alpine:edge
Projects in the gitlab-org group pull from the Dependency Proxy, while
forks that reside on any other personal namespaces or groups fall back to
Docker Hub unless ${GITLAB_DEPENDENCY_PROXY} is also defined there.
Work around for when a pipeline is started by a Project access token user
When a pipeline is started by a Project access token user (e.g. the release-tools approver bot user which
automatically updates the Gitaly version used in the main project),
the Dependency proxy isn’t accessible
and the job fails at the Preparing the "docker+machine" executor step.
To work around that, we have a special workflow rule, that overrides the
${GITLAB_DEPENDENCY_PROXY_ADDRESS} variable so that Dependency proxy isn’t used in that case:
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $GITLAB_USER_LOGIN =~ /project_\d+_bot\d*/'
  variables:
    GITLAB_DEPENDENCY_PROXY_ADDRESS: ""
${GITLAB_DEPENDENCY_PROXY} variable because group-level
variables have higher precedence over .gitlab-ci.yml variables.Common job definitions
Most of the jobs extend from a few CI definitions
defined in .gitlab/ci/global.gitlab-ci.yml
that are scoped to a single configuration keyword.
| Job definitions | Description | 
|---|---|
| .default-retry | Allows a job to retry upon unknown_failure,api_failure,runner_system_failure,job_execution_timeout, orstuck_or_timeout_failure. | 
| .default-before_script | Allows a job to use a default before_scriptdefinition suitable for Ruby/Rails tasks that may need a database running (for example, tests). | 
| .setup-test-env-cache | Allows a job to use a default cachedefinition suitable for setting up test environment for subsequent Ruby/Rails tasks. | 
| .rails-cache | Allows a job to use a default cachedefinition suitable for Ruby/Rails tasks. | 
| .static-analysis-cache | Allows a job to use a default cachedefinition suitable for static analysis tasks. | 
| .coverage-cache | Allows a job to use a default cachedefinition suitable for coverage tasks. | 
| .qa-cache | Allows a job to use a default cachedefinition suitable for QA tasks. | 
| .yarn-cache | Allows a job to use a default cachedefinition suitable for frontend jobs that do ayarn install. | 
| .assets-compile-cache | Allows a job to use a default cachedefinition suitable for frontend jobs that compile assets. | 
| .use-pg11 | Allows a job to run the postgres11 andredisservices (see.gitlab/ci/global.gitlab-ci.ymlfor the specific versions of the services). | 
| .use-pg11-ee | Same as .use-pg11but also use anelasticsearchservice (see.gitlab/ci/global.gitlab-ci.ymlfor the specific version of the service). | 
| .use-pg12 | Allows a job to use the postgres12 andredisservices (see.gitlab/ci/global.gitlab-ci.ymlfor the specific versions of the services). | 
| .use-pg12-ee | Same as .use-pg12but also use anelasticsearchservice (see.gitlab/ci/global.gitlab-ci.ymlfor the specific version of the service). | 
| .use-pg13 | Allows a job to use the postgres13 andredisservices (see.gitlab/ci/global.gitlab-ci.ymlfor the specific versions of the services). | 
| .use-pg13-ee | Same as .use-pg13but also use anelasticsearchservice (see.gitlab/ci/global.gitlab-ci.ymlfor the specific version of the service). | 
| .use-kaniko | Allows a job to use the kanikotool to build Docker images. | 
| .as-if-foss | Simulate the FOSS project by setting the FOSS_ONLY='1'CI/CD variable. | 
| .use-docker-in-docker | Allows a job to use Docker in Docker. | 
rules, if: conditions and changes: patterns
We’re using the rules keyword extensively.
All rules definitions are defined in
rules.gitlab-ci.yml,
then included in individual jobs via extends.
The rules definitions are composed of if: conditions and changes: patterns,
which are also defined in
rules.gitlab-ci.yml
and included in rules definitions via YAML anchors
if: conditions
| if:conditions | Description | Notes | 
|---|---|---|
| if-not-canonical-namespace | Matches if the project isn’t in the canonical ( gitlab-org/) or security (gitlab-org/security) namespace. | Use to create a job for forks (by using when: on_successorwhen: manual), or not create a job for forks (by usingwhen: never). | 
| if-not-ee | Matches if the project isn’t EE (that is, project name isn’t gitlaborgitlab-ee). | Use to create a job only in the FOSS project (by using when: on_successorwhen: manual), or not create a job if the project is EE (by usingwhen: never). | 
| if-not-foss | Matches if the project isn’t FOSS (that is, project name isn’t gitlab-foss,gitlab-ce, orgitlabhq). | Use to create a job only in the EE project (by using when: on_successorwhen: manual), or not create a job if the project is FOSS (by usingwhen: never). | 
| if-default-refs | Matches if the pipeline is for master,main,/^[\d-]+-stable(-ee)?$/(stable branches),/^\d+-\d+-auto-deploy-\d+$/(auto-deploy branches),/^security\//(security branches), merge requests, and tags. | Note that jobs aren’t created for branches with this default configuration. | 
| if-master-refs | Matches if the current branch is masterormain. | |
| if-master-push | Matches if the current branch is masterormainand pipeline source ispush. | |
| if-master-schedule-maintenance | Matches if the current branch is masterormainand pipeline runs on a 2-hourly schedule. | |
| if-master-schedule-nightly | Matches if the current branch is masterormainand pipeline runs on a nightly schedule. | |
| if-auto-deploy-branches | Matches if the current branch is an auto-deploy one. | |
| if-master-or-tag | Matches if the pipeline is for the masterormainbranch or for a tag. | |
| if-merge-request | Matches if the pipeline is for a merge request. | |
| if-merge-request-title-as-if-foss | Matches if the pipeline is for a merge request and the MR has label ~"pipeline:run-as-if-foss" | |
| if-merge-request-title-update-caches | Matches if the pipeline is for a merge request and the MR has label ~"pipeline:update-cache". | |
| if-merge-request-title-run-all-rspec | Matches if the pipeline is for a merge request and the MR has label ~"pipeline:run-all-rspec". | |
| if-security-merge-request | Matches if the pipeline is for a security merge request. | |
| if-security-schedule | Matches if the pipeline is for a security scheduled pipeline. | |
| if-nightly-master-schedule | Matches if the pipeline is for a masterscheduled pipeline with$NIGHTLYset. | |
| if-dot-com-gitlab-org-schedule | Limits jobs creation to scheduled pipelines for the gitlab-orggroup on GitLab.com. | |
| if-dot-com-gitlab-org-master | Limits jobs creation to the masterormainbranch for thegitlab-orggroup on GitLab.com. | |
| if-dot-com-gitlab-org-merge-request | Limits jobs creation to merge requests for the gitlab-orggroup on GitLab.com. | |
| if-dot-com-gitlab-org-and-security-tag | Limits job creation to tags for the gitlab-organdgitlab-org/securitygroups on GitLab.com. | |
| if-dot-com-gitlab-org-and-security-merge-request | Limit jobs creation to merge requests for the gitlab-organdgitlab-org/securitygroups on GitLab.com. | |
| if-dot-com-gitlab-org-and-security-tag | Limit jobs creation to tags for the gitlab-organdgitlab-org/securitygroups on GitLab.com. | |
| if-dot-com-ee-schedule | Limits jobs to scheduled pipelines for the gitlab-org/gitlabproject on GitLab.com. | |
| if-security-pipeline-merge-result | Matches if the pipeline is for a security merge request triggered by @gitlab-release-tools-bot. | 
changes: patterns
| changes:patterns | Description | 
|---|---|
| ci-patterns | Only create job for CI configuration-related changes. | 
| ci-build-images-patterns | Only create job for CI configuration-related changes related to the build-imagesstage. | 
| ci-review-patterns | Only create job for CI configuration-related changes related to the reviewstage. | 
| ci-qa-patterns | Only create job for CI configuration-related changes related to the qastage. | 
| yaml-lint-patterns | Only create job for YAML-related changes. | 
| docs-patterns | Only create job for docs-related changes. | 
| frontend-dependency-patterns | Only create job when frontend dependencies are updated (for example, package.json, andyarn.lock) changes. | 
| frontend-patterns-for-as-if-foss | Only create job for frontend-related changes that have impact on FOSS. | 
| backend-patterns | Only create job for backend-related changes. | 
| db-patterns | Only create job for DB-related changes. | 
| backstage-patterns | Only create job for backstage-related changes (that is, Danger, fixtures, RuboCop, specs). | 
| code-patterns | Only create job for code-related changes. | 
| qa-patterns | Only create job for QA-related changes. | 
| code-backstage-patterns | Combination of code-patternsandbackstage-patterns. | 
| code-qa-patterns | Combination of code-patternsandqa-patterns. | 
| code-backstage-qa-patterns | Combination of code-patterns,backstage-patterns, andqa-patterns. | 
| static-analysis-patterns | Only create jobs for Static Analytics configuration-related changes. | 
Best Practices
When to use extends:, <<: *xyz (YAML anchors), or !reference
Key takeaways
- If you need to extend a hash, you should use extends
- If you need to extend an array, you’ll need to use !reference, orYAML anchorsas last resort
- For more complex cases (e.g. extend hash inside array, extend array inside hash, …), you’ll have to use !referenceorYAML anchors
What can extends and YAML anchors do?
extends
- Deep merge for hashes
- NO merge for arrays. It overwrites (source)
YAML anchors
- NO deep merge for hashes, BUT it can be used to extend a hash (see the example below)
- NO merge for arrays, BUT it can be used to extend an array (see the example below)
A great example
This example shows how to extend complex YAML data structures with !reference and YAML anchors:
.strict-ee-only-rules:
  # `rules` is an array of hashes
  rules:
    - if: '$CI_PROJECT_NAME !~ /^gitlab(-ee)?$/ '
      when: never
# `if-security-merge-request` is a hash
.if-security-merge-request: &if-security-merge-request
  if: '$CI_PROJECT_NAMESPACE == "gitlab-org/security"'
# `code-qa-patterns` is an array
.code-qa-patterns: &code-qa-patterns
  - "{package.json,yarn.lock}"
  - ".browserslistrc"
  - "babel.config.js"
  - "jest.config.{base,integration,unit}.js"
.qa:rules:as-if-foss:
  rules:
    # We extend the `rules` array with an array of hashes directly
    - !reference [".strict-ee-only-rules", rules]
    # We extend a single array entry with a hash
    - <<: *if-security-merge-request
      # `changes` is an array, so we pass it an entire array
      changes: *code-qa-patterns
qa:selectors-as-if-foss:
  # We include the rules from .qa:rules:as-if-foss in this job
  extends:
    - .qa:rules:as-if-foss