CI configuration performance
Interruptible pipelines
By default, all jobs are interruptible, except the
dont-interrupt-me
job which runs automatically on main
, and is manual
otherwise.
If you want a running pipeline to finish even if you push new commits to a merge
request, be sure to start the dont-interrupt-me
job before pushing.
Git fetch caching
Because GitLab.com uses the pack-objects cache, concurrent Git fetches of the same pipeline ref are deduplicated on the Gitaly server (always) and served from cache (when available).
This works well for the following reasons:
- The pack-objects cache is enabled on all Gitaly servers on GitLab.com.
- The CI/CD Git strategy setting for
gitlab-org/gitlab
is Git clone, causing all jobs to fetch the same data, which maximizes the cache hit ratio. - We use shallow clone to avoid downloading the full Git history for every job.
Caching strategy
- All jobs must only pull caches by default.
- All jobs must be able to pass with an empty cache. In other words, caches are only there to speed up jobs.
- We currently have several different cache definitions defined in
.gitlab/ci/global.gitlab-ci.yml
, with fixed keys:.setup-test-env-cache
.ruby-cache
.static-analysis-cache
.rubocop-cache
.ruby-gems-coverage-cache
.ruby-node-cache
.qa-cache
.yarn-cache
-
.assets-compile-cache
(the key includes${NODE_ENV}
so it’s actually two different caches).
- These cache definitions are composed of multiple atomic caches.
- Only the following jobs, running in 2-hourly
maintenance
scheduled pipelines, are pushing (that is, updating) to the caches:-
update-setup-test-env-cache
, defined in.gitlab/ci/rails.gitlab-ci.yml
. -
update-gitaly-binaries-cache
, defined in.gitlab/ci/rails.gitlab-ci.yml
. -
update-rubocop-cache
, defined in.gitlab/ci/rails.gitlab-ci.yml
. -
update-qa-cache
, defined in.gitlab/ci/qa.gitlab-ci.yml
. -
update-assets-compile-production-cache
, defined in.gitlab/ci/frontend.gitlab-ci.yml
. -
update-assets-compile-test-cache
, defined in.gitlab/ci/frontend.gitlab-ci.yml
. -
update-storybook-yarn-cache
, defined in.gitlab/ci/frontend.gitlab-ci.yml
.
-
- These jobs can also be forced to run in merge requests with the
pipeline:update-cache
label (this can be useful to warm the caches in a MR that updates the cache keys).
Artifacts strategy
We limit the artifacts that are saved and retrieved by jobs to the minimum to reduce the upload/download time and costs, as well as the artifacts storage.
Components caching
Some external components (GitLab Workhorse and frontend assets) of GitLab need to be built from source as a preliminary step for running tests.
cache-workhorse
In this MR, and then
this MR,
we introduced a new cache-workhorse
job that:
- runs automatically for all GitLab.com
gitlab-org/gitlab
scheduled pipelines - runs automatically for any
master
commit that touches theworkhorse/
folder - is manual for GitLab.com’s
gitlab-org
’s MRs that touches caching-related files
This job tries to download a generic package that contains GitLab Workhorse binaries needed in the GitLab test suite (under tmp/tests/gitlab-workhorse
).
- If the package URL returns a 404:
- It runs
scripts/setup-test-env
, so that the GitLab Workhorse binaries are built. - It then creates an archive which contains the binaries and upload it as a generic package.
- It runs
- Otherwise, if the package already exists, it exits the job successfully.
We also changed the setup-test-env
job to:
- First download the GitLab Workhorse generic package build and uploaded by
cache-workhorse
. - If the package is retrieved successfully, its content is placed in the right folder (for example,
tmp/tests/gitlab-workhorse
), preventing the building of the binaries whenscripts/setup-test-env
is run later on. - If the package URL returns a 404, the behavior doesn’t change compared to the current one: the GitLab Workhorse binaries are built as part of
scripts/setup-test-env
.
git rev-parse HEAD:workhorse
).
cache-assets
In this MR,
we introduced three new cache-assets:test
, cache-assets:test as-if-foss
,
and cache-assets:production
jobs that:
- never run unless
$CACHE_ASSETS_AS_PACKAGE == "true"
- runs automatically for all GitLab.com
gitlab-org/gitlab
scheduled pipelines - runs automatically for any
master
commit that touches the assets-related folders - is manual for GitLab.com’s
gitlab-org
’s MRs that touches caching-related files
This job tries to download a generic package that contains GitLab compiled assets
needed in the GitLab test suite (under app/assets/javascripts/locale/**/app.js
,
and public/assets
).
- If the package URL returns a 404:
- It runs
bin/rake gitlab:assets:compile
, so that the GitLab assets are compiled. - It then creates an archive which contains the assets and uploads it as a generic package. The package version is set to the assets folders’ hash sum.
- It runs
- Otherwise, if the package already exists, it exits the job successfully.
compile-*-assets
We also changed the compile-test-assets
, compile-test-assets as-if-foss
,
and compile-production-assets
jobs to:
- First download the “native” cache assets, which contain:
- The compiled assets.
-
A
cached-assets-hash.txt
file containing theSHA256
hexdigest of all the source files on which the assets depend on. This list of files is a pessimistic list and the assets might not depend on some of these files. At worst we compile the assets more often, which is better than using outdated assets.The file is created after assets are compiled.
- We then we compute the
SHA256
hexdigest of all the source files the assets depend on, for the current checked out branch. We store the hexdigest in theGITLAB_ASSETS_HASH
variable. - If
$CACHE_ASSETS_AS_PACKAGE == "true"
, we download the generic package built and uploaded bycache-assets:*
.- If the cache is up-to-date for the checked out branch, we download the native cache and the cache package. We could optimize that by not downloading the genetic package but the native cache is actually very often outdated because it’s rebuilt only every 2 hours.
-
We run the
assets_compile_script
function, which itself runs theassets:compile
Rake task.This task is responsible for deciding if assets need to be compiled or not. It compares the
HEAD
SHA256
hexdigest from$GITLAB_ASSETS_HASH
with themaster
hexdigest fromcached-assets-hash.txt
. - If the hashes are the same, we don’t compile anything. If they’re different, we compile the assets.