Кэширование конвейера
Azure DevOps Services
Кэширование конвейера может помочь сократить время сборки, позволяя выходным данным или скачанным зависимостям из одного запуска повторно использоваться в последующих запусках, тем самым уменьшая или избегая затрат повторного создания или повторной загрузки одних и таких же файлов. Кэширование особенно полезно в сценариях, когда одни и те же зависимости скачиваются снова и снова в начале каждого запуска. Это часто много времени занимает много времени, включающего сотни или тысячи сетевых вызовов.
Кэширование может быть эффективным при улучшении времени сборки, если время восстановления и сохранения кэша меньше времени для повторного создания выходных данных с нуля. Из-за этого кэширование может оказаться не эффективным во всех сценариях и на самом деле может оказать негативное влияние на время сборки.
Примечание.
Кэширование конвейера поддерживается в заданиях пула агентов как для YAML, так и для классических конвейеров. Однако он не поддерживается в конвейерах классических выпусков.
Использование артефактов и кэширования
Кэширование конвейера и артефакты конвейера выполняют аналогичные функции, но предназначены для различных сценариев и не должны использоваться взаимозаменяемо.
Используйте артефакты конвейера , когда необходимо принимать определенные файлы, созданные в одном задании, и совместно использовать их с другими заданиями (и эти другие задания, скорее всего, завершаются сбоем без них).
Используйте кэширование конвейера, если вы хотите улучшить время сборки, повторно используя файлы из предыдущих запусков (и не имея этих файлов, не повлияют на возможность выполнения задания).
Примечание.
Кэширование конвейера и артефакты конвейера бесплатны для всех уровней (бесплатные и платные). Дополнительные сведения см. в разделе " Использование хранилища артефактов".
Задача кэша: как она работает
Кэширование добавляется в конвейер с помощью задачи "Кэш". Эта задача работает как любая другая задача и добавляется в steps
раздел задания.
При обнаружении шага кэша во время выполнения задача восстанавливает кэш на основе предоставленных входных данных. Если кэш не найден, шаг завершается и выполняется следующий шаг задания.
После выполнения всех шагов задания и при условии успешного состояния задания специальный шаг "Post-job: Cache" автоматически добавляется и активируется для каждого шага восстановления кэша, который не был пропущен. Этот шаг отвечает за сохранение кэша.
Примечание.
Кэши неизменяемы, что означает, что после создания кэша его содержимое невозможно изменить.
Настройка задачи кэша
Задача кэша имеет два обязательных аргумента: ключ и путь:
- путь: путь к папке для кэширования. Может быть абсолютным или относительным путем. Относительные пути разрешаются против
$(System.DefaultWorkingDirectory)
.
Примечание.
Вы можете использовать предопределенные переменные для хранения пути к папке, которую требуется кэшировать, однако подстановочные знаки не поддерживаются.
- ключ: необходимо задать идентификатор для кэша, который требуется восстановить или сохранить. Ключи состоят из сочетания строковых значений, путей к файлам или шаблонов файлов, где каждый сегмент отделен символом
|
.
Строки:
Фиксированное значение (например, имя кэша или имени средства) или взятое из переменной среды (например, текущее имя ОС или текущего задания).Пути к файлам:
Путь к определенному файлу, содержимое которого будет хэшировано. Этот файл должен существовать во время выполнения задачи. Помните, что любой сегмент ключа, который будет рассматриваться как путь к файлу, будет рассматриваться как путь к файлу. В частности, это включает сегменты, содержащие объект.
. Это может привести к сбою задачи, если этот файл не существует.Совет
Чтобы избежать обращения к сегменту строки типа пути, как путь к файлу, обтекайте его двойными кавычками, например:
"my.key" | $(Agent.OS) | key.file
Шаблоны файлов:
Разделенный запятыми список шаблонов подстановочных знаков в стиле с запятыми, который должен соответствовать по крайней мере одному файлу. Например:**/yarn.lock
: все файлы yarn.lock в каталоге источников*/asset.json, !bin/**
: все asset.json файлы, расположенные в каталоге источников, за исключением каталога bin
Содержимое любого файла, определяемого путем к файлу или шаблоном файла, хэшируется для создания ключа динамического кэша. Это полезно, если в проекте есть файлы, которые однозначно определяют, что кэшируется. Например, такие файлы, как package-lock.json
, Gemfile.lock
yarn.lock
или Pipfile.lock
обычно ссылаются на ключ кэша, так как все они представляют уникальный набор зависимостей.
Относительные пути к файлам или шаблоны файлов разрешаются для $(System.DefaultWorkingDirectory)
.
Пример:
Ниже приведен пример кэширования зависимостей, установленных Yarn:
variables:
YARN_CACHE_FOLDER: $(Pipeline.Workspace)/s/.yarn
steps:
- task: Cache@2
inputs:
key: '"yarn" | "$(Agent.OS)" | yarn.lock'
restoreKeys: |
"yarn" | "$(Agent.OS)"
"yarn"
path: $(YARN_CACHE_FOLDER)
displayName: Cache Yarn packages
- script: yarn --frozen-lockfile
В этом примере ключ кэша содержит три части: статическую строку (yarn), на которую выполняется задание, так как этот кэш является уникальным для каждой операционной системы, а хэш yarn.lock
файла, который однозначно определяет набор зависимостей в кэше.
При первом запуске после добавления задачи шаг кэша сообщит о "промахе кэша", так как кэш, определенный этим ключом, не существует. После последнего шага кэш будет создан из файлов $(Pipeline.Workspace)/s/.yarn
и отправлен. На следующем этапе кэша будет сообщаться о "попадании в кэш", а содержимое кэша будет загружено и восстановлено.
При использовании checkout: self
репозиторий извлекается $(Pipeline.Workspace)/s
и папка .yarn
обычно находится в самом репозитории.
Примечание.
Pipeline.Workspace
— это локальный путь к агенту, на котором выполняются конвейер, где создаются все каталоги. Эта переменная имеет то же значение, что Agent.BuildDirectory
и .
Убедитесь, что переменная YARN_CACHE_FOLDER
обновляется, если используется что-либо, отличное от checkout: self
этого, в репозитории, где .yarn
находится.
Восстановление ключей
restoreKeys
можно использовать, если требуется запросить несколько точных ключей или префиксов ключей. Это используется для возврата к другому ключу в случае, если не key
дает удара. Ключ восстановления выполняет поиск ключа по префиксу и дает последнюю созданную запись кэша в результате. Это полезно, если конвейер не может найти точное совпадение, но хочет использовать частичное попадание кэша. Чтобы вставить несколько ключей восстановления, разделите их с помощью новой строки, чтобы указать ключ восстановления (см. пример для получения дополнительных сведений). Порядок, в котором будут пытаться выполнить восстановление ключей, будут выполняться сверху вниз.
Обязательное программное обеспечение для локального агента
Архивное программное обеспечение / платформа | Windows | Linux | Mac |
---|---|---|---|
GNU Tar | Обязательное поле | Обязательное поле | No |
BSD Tar | No | Нет | Обязательное поле |
7-Zip | Рекомендуемая конфигурация | No | No |
Приведенные выше исполняемые файлы должны находиться в папке, указанной в переменной среды PATH. Помните, что размещенные агенты поставляются с включенным программным обеспечением, это применимо только для локальных агентов.
Пример:
Ниже приведен пример использования ключей восстановления Yarn:
variables:
YARN_CACHE_FOLDER: $(Pipeline.Workspace)/.yarn
steps:
- task: Cache@2
inputs:
key: '"yarn" | "$(Agent.OS)" | yarn.lock'
restoreKeys: |
yarn | "$(Agent.OS)"
yarn
path: $(YARN_CACHE_FOLDER)
displayName: Cache Yarn packages
- script: yarn --frozen-lockfile
В этом примере задача кэша пытается найти, существует ли ключ в кэше. Если ключ не существует в кэше, он пытается использовать первый ключ yarn | $(Agent.OS)
восстановления.
При этом выполняется поиск всех ключей, которые точно соответствуют этому ключу или имеют этот ключ в качестве префикса. При наличии другого yarn.lock
хэш-сегмента может произойти попадание префикса.
Например, если следующий ключ был в кэше, где old-yarn.lock
получен хэш, отличный от хэшаyarn.lock
, ключ yarn | $(Agent.OS) | old-yarn.lock
восстановления даст частичный удар.
Если на первом ключе восстановления отсутствует, он будет использовать следующий ключ восстановления, который попытается найти любой ключ yarn
, который начинается с yarn
. В случае попаданий префикса результат возвращает последний созданный ключ кэша в результате.
Примечание.
Конвейер может иметь одну или несколько задач кэширования. Нет ограничений на емкость хранилища кэширования, а задания и задачи из одного конвейера могут получить доступ к одному кэшу и предоставить общий доступ к ним.
Изоляция кэша и безопасность
Чтобы обеспечить изоляцию между кэшами из разных конвейеров и разных ветвей, каждый кэш принадлежит логическому контейнеру, называемому областью. Области предоставляют границу безопасности, которая гарантирует, что задание из одного конвейера не может получить доступ к кэшам из другого конвейера, а задание, создающее PR, имеет доступ на чтение к кэшам целевой ветви PR (для одного конвейера), но не может записывать (создать) кэши в области целевой ветви.
При обнаружении шага кэша во время выполнения кэш, кэш, определенный ключом, запрашивается с сервера. Затем сервер ищет кэш с этим ключом из областей, видимых для задания, и возвращает кэш (если он доступен). При сохранении кэша (в конце задания) кэш записывается в область, представляющую конвейер и ветвь. Дополнительные сведения см. ниже.
CI, вручную и запланированные запуски
Область | Читать | Запись |
---|---|---|
Исходная ветвь | Да | Да |
main ветка |
Да | Нет |
master ветка |
Да | Нет |
Запуски запроса на вытягивание
Область | Читать | Запись |
---|---|---|
Исходная ветвь | Да | Нет |
Целевая ветвь | Да | Нет |
Промежуточная ветвь (например refs/pull/1/merge ) |
Да | Да |
main ветка |
Да | Нет |
master ветка |
Да | Нет |
Запуски запросов на вытягивание
Ветвь | Читать | Запись |
---|---|---|
Целевая ветвь | Да | Нет |
Промежуточная ветвь (например refs/pull/1/merge ) |
Да | Да |
main ветка |
Да | Нет |
master ветка |
Да | Нет |
Совет
Так как кэши уже ограничены проектом, конвейером и ветвью, в ключ кэша не требуется включать идентификаторы проекта, конвейера или ветви.
Кондиционирование при восстановлении кэша
В некоторых сценариях успешное восстановление кэша должно привести к выполнению другого набора шагов. Например, шаг установки зависимостей можно пропустить, если кэш был восстановлен. Это возможно с помощью входных cacheHitVar
данных задачи. Установка этого входного значения в имя переменной среды приводит к тому, что true
переменная будет задана при попадании в кэш кэша восстановления, inexact
в противном случае оно имеет значение false
. Затем эту переменную можно ссылаться в условии шага или из скрипта.
В следующем примере install-deps.sh
шаг пропускается при восстановлении кэша:
steps:
- task: Cache@2
inputs:
key: mykey | mylockfile
restoreKeys: mykey
path: $(Pipeline.Workspace)/mycache
cacheHitVar: CACHE_RESTORED
- script: install-deps.sh
condition: ne(variables.CACHE_RESTORED, 'true')
- script: build.sh
Средство увязки программ в пакеты
Для проектов Ruby с помощью Bundler переопределите BUNDLE_PATH
переменную среды, используемую Пакетировщиком, чтобы задать путь Для поиска драгоценных камней.
Пример:
variables:
BUNDLE_PATH: $(Pipeline.Workspace)/.bundle
steps:
- task: Cache@2
displayName: Bundler caching
inputs:
key: 'gems | "$(Agent.OS)" | Gemfile.lock'
path: $(BUNDLE_PATH)
restoreKeys: |
gems | "$(Agent.OS)"
gems
Ccache (C/C++)
Ccache — это кэш компилятора для C/C++. Чтобы использовать Ccache в конвейере, убедитесь, что Ccache
установлен и дополнительно добавлен в ваш PATH
(см . режимы выполнения Ccache). Задайте для переменной CCACHE_DIR
среды путь и $(Pipeline.Workspace)
кэшируйте этот каталог.
Пример:
variables:
CCACHE_DIR: $(Pipeline.Workspace)/ccache
steps:
- bash: |
sudo apt-get install ccache -y
echo "##vso[task.prependpath]/usr/lib/ccache"
displayName: Install ccache and update PATH to use linked versions of gcc, cc, etc
- task: Cache@2
displayName: Ccache caching
inputs:
key: 'ccache | "$(Agent.OS)" | $(Build.SourceVersion)'
path: $(CCACHE_DIR)
restoreKeys: |
ccache | "$(Agent.OS)"
Дополнительные сведения см . в параметрах конфигурации Ccache.
Образы Docker
Кэширование образов Docker значительно сокращает время, необходимое для запуска конвейера.
variables:
repository: 'myDockerImage'
dockerfilePath: '$(Build.SourcesDirectory)/app/Dockerfile'
tag: '$(Build.BuildId)'
pool:
vmImage: 'ubuntu-latest'
steps:
- task: Cache@2
displayName: Cache task
inputs:
key: 'docker | "$(Agent.OS)" | cache'
path: $(Pipeline.Workspace)/docker
cacheHitVar: CACHE_RESTORED #Variable to set to 'true' when the cache is restored
- script: |
docker load -i $(Pipeline.Workspace)/docker/cache.tar
displayName: Docker restore
condition: and(not(canceled()), eq(variables.CACHE_RESTORED, 'true'))
- task: Docker@2
displayName: 'Build Docker'
inputs:
command: 'build'
repository: '$(repository)'
dockerfile: '$(dockerfilePath)'
tags: |
'$(tag)'
- script: |
mkdir -p $(Pipeline.Workspace)/docker
docker save -o $(Pipeline.Workspace)/docker/cache.tar $(repository):$(tag)
displayName: Docker save
condition: and(not(canceled()), not(failed()), ne(variables.CACHE_RESTORED, 'true'))
- key: (обязательно) — уникальный идентификатор кэша.
- path: (обязательно) — путь к папке или файлу, который требуется кэшировать.
Golang
Для проектов Golang можно указать пакеты, которые нужно скачать в файле go.mod . GOCACHE
Если переменная еще не задана, задайте для нее место загрузки кэша.
Пример:
variables:
GO_CACHE_DIR: $(Pipeline.Workspace)/.cache/go-build/
steps:
- task: Cache@2
inputs:
key: 'go | "$(Agent.OS)" | go.mod'
restoreKeys: |
go | "$(Agent.OS)"
path: $(GO_CACHE_DIR)
displayName: Cache GO packages
Gradle
Использование встроенной поддержки кэширования Gradle может оказать значительное влияние на время сборки. Чтобы включить кэш сборки, установите GRADLE_USER_HOME
переменную среды в путь $(Pipeline.Workspace)
и запустите сборку или --build-cache
добавьте org.gradle.caching=true
в gradle.properties
файл.
Пример:
variables:
GRADLE_USER_HOME: $(Pipeline.Workspace)/.gradle
steps:
- task: Cache@2
inputs:
key: 'gradle | "$(Agent.OS)" | **/build.gradle.kts' # Swap build.gradle.kts for build.gradle when using Groovy
restoreKeys: |
gradle | "$(Agent.OS)"
gradle
path: $(GRADLE_USER_HOME)
displayName: Configure gradle caching
- task: Gradle@2
inputs:
gradleWrapperFile: 'gradlew'
tasks: 'build'
options: '--build-cache'
displayName: Build
- script: |
# stop the Gradle daemon to ensure no files are left open (impacting the save cache operation later)
./gradlew --stop
displayName: Gradlew stop
- restoreKeys: резервные ключи, если первичный ключ завершается сбоем (необязательно)
Примечание.
Кэши неизменяемы, когда кэш с определенным ключом создается для определенной области (ветви), кэш нельзя обновить. Это означает, что если ключ является фиксированным значением, все последующие сборки для одной ветви не смогут обновить кэш, даже если содержимое кэша изменилось. Если вы хотите использовать фиксированное значение ключа, необходимо использовать restoreKeys
аргумент в качестве резервного варианта.
Maven
Maven имеет локальный репозиторий, в котором хранятся скачивающие и созданные артефакты. Чтобы включить, задайте maven.repo.local
для параметра путь в $(Pipeline.Workspace)
папку и кэшируйте эту папку.
Пример:
variables:
MAVEN_CACHE_FOLDER: $(Pipeline.Workspace)/.m2/repository
MAVEN_OPTS: '-Dmaven.repo.local=$(MAVEN_CACHE_FOLDER)'
steps:
- task: Cache@2
inputs:
key: 'maven | "$(Agent.OS)" | **/pom.xml'
restoreKeys: |
maven | "$(Agent.OS)"
maven
path: $(MAVEN_CACHE_FOLDER)
displayName: Cache Maven local repo
- script: mvn install -B -e
Если вы используете задачу Maven, обязательно передайте MAVEN_OPTS
переменную, так как она перезаписывается в противном случае:
- task: Maven@4
inputs:
mavenPomFile: 'pom.xml'
mavenOptions: '-Xmx3072m $(MAVEN_OPTS)'
.NET/NuGet
Если вы используете PackageReferences
для управления зависимостями NuGet непосредственно в файле проекта и имеете packages.lock.json
файл, можно включить кэширование, задав NUGET_PACKAGES
переменную среды в путь $(UserProfile)
и кэширование этого каталога. Дополнительные сведения о блокировке зависимостей см . в справочнике по пакетам в файлах проекта.
Если вы хотите использовать несколько packages.lock.json, вы по-прежнему можете использовать следующий пример без внесения изменений. Содержимое всех файлов packages.lock.json будет хэшировано и при изменении одного из файлов создается новый ключ кэша.
Пример:
variables:
NUGET_PACKAGES: $(Pipeline.Workspace)/.nuget/packages
steps:
- task: Cache@2
inputs:
key: 'nuget | "$(Agent.OS)" | $(Build.SourcesDirectory)/**/packages.lock.json'
restoreKeys: |
nuget | "$(Agent.OS)"
nuget
path: $(NUGET_PACKAGES)
displayName: Cache NuGet packages
Node.js/npm
Существуют различные способы включения кэширования в проекте Node.js, но рекомендуется кэшировать общий каталог кэша npm. Этот каталог управляется npm и содержит кэшированную версию всех загруженных модулей. Во время установки npm сначала проверяет этот каталог (по умолчанию) для модулей, которые могут уменьшить или устранить сетевые вызовы к общедоступному реестру npm или к частному реестру.
Так как путь по умолчанию к каталогу общего кэша npm не совпадает на всех платформах, рекомендуется переопределить npm_config_cache
переменную среды на путь.$(Pipeline.Workspace)
Это также гарантирует, что кэш доступен из заданий контейнера и неконтейнеров.
Пример:
variables:
npm_config_cache: $(Pipeline.Workspace)/.npm
steps:
- task: Cache@2
inputs:
key: 'npm | "$(Agent.OS)" | package-lock.json'
restoreKeys: |
npm | "$(Agent.OS)"
path: $(npm_config_cache)
displayName: Cache npm
- script: npm ci
Если в проекте нет package-lock.json
файла, обратитесь package.json
к файлу в входных данных ключа кэша.
Совет
Так как npm ci
удаляет node_modules
папку, чтобы обеспечить согласованное использование повторяемого набора модулей, следует избегать кэширования node_modules
при вызове npm ci
.
Node.js/Yarn
Как и в npm, существуют различные способы кэширования пакетов, установленных с помощью Yarn. Рекомендуется кэшировать общую папку кэша Yarn. Этот каталог управляется Yarn и содержит кэшированную версию всех загруженных пакетов. Во время установки Yarn сначала проверяет этот каталог (по умолчанию) для модулей, что может уменьшить или исключить сетевые вызовы к общедоступным или частным реестрам.
Пример:
variables:
YARN_CACHE_FOLDER: $(Pipeline.Workspace)/.yarn
steps:
- task: Cache@2
inputs:
key: 'yarn | "$(Agent.OS)" | yarn.lock'
restoreKeys: |
yarn | "$(Agent.OS)"
yarn
path: $(YARN_CACHE_FOLDER)
displayName: Cache Yarn packages
- script: yarn --frozen-lockfile
Python/Anaconda
Настройте кэширование конвейера с помощью сред Anaconda:
Пример
variables:
CONDA_CACHE_DIR: /usr/share/miniconda/envs
# Add conda to system path
steps:
- script: echo "##vso[task.prependpath]$CONDA/bin"
displayName: Add conda to PATH
- bash: |
sudo chown -R $(whoami):$(id -ng) $(CONDA_CACHE_DIR)
displayName: Fix CONDA_CACHE_DIR directory permissions
- task: Cache@2
displayName: Use cached Anaconda environment
inputs:
key: 'conda | "$(Agent.OS)" | environment.yml'
restoreKeys: |
python | "$(Agent.OS)"
python
path: $(CONDA_CACHE_DIR)
cacheHitVar: CONDA_CACHE_RESTORED
- script: conda env create --quiet --file environment.yml
displayName: Create Anaconda environment
condition: eq(variables.CONDA_CACHE_RESTORED, 'false')
Windows
- task: Cache@2 displayName: Cache Anaconda inputs: key: 'conda | "$(Agent.OS)" | environment.yml' restoreKeys: | python | "$(Agent.OS)" python path: $(CONDA)/envs cacheHitVar: CONDA_CACHE_RESTORED - script: conda env create --quiet --file environment.yml displayName: Create environment condition: eq(variables.CONDA_CACHE_RESTORED, 'false')
PHP/Composer
Для проектов PHP с помощью Composer переопределите переменную среды, используемую COMPOSER_CACHE_DIR
composer.
Пример:
variables:
COMPOSER_CACHE_DIR: $(Pipeline.Workspace)/.composer
steps:
- task: Cache@2
inputs:
key: 'composer | "$(Agent.OS)" | composer.lock'
restoreKeys: |
composer | "$(Agent.OS)"
composer
path: $(COMPOSER_CACHE_DIR)
displayName: Cache composer
- script: composer install
Известные проблемы и отзывы
Если у вас возникли проблемы с настройкой кэширования для конвейера, проверьте список открытых проблем в репозитории microsoft/azure-pipelines-tasks . Если вашей проблемы нет в списке, создайте новую проблему и предоставьте необходимые сведения о сценарии.
Q&A
Вопрос. Можно ли очистить кэш?
Ответ. Очистка кэша в настоящее время не поддерживается. Однако можно добавить строковый литерал (например version2
) в существующий ключ кэша, чтобы изменить ключ таким образом, чтобы избежать попаданий в существующие кэши. Например, измените следующий ключ кэша из этого:
key: 'yarn | "$(Agent.OS)" | yarn.lock'
На эту:
key: 'version2 | yarn | "$(Agent.OS)" | yarn.lock'
Вопрос. Когда истекает срок действия кэша?
Ответ. Срок действия кэша истекает через семь дней без действия.
Вопрос. Когда кэш отправляется?
Ответ. После последнего шага конвейера кэш будет создан из кэша path
и отправлен. Дополнительные сведения см. в примере .
Вопрос. Существует ли ограничение на размер кэша?
Ответ. Нет принудительного ограничения на размер отдельных кэшей или общий размер всех кэшей в организации.