Кэш пакетов NuGet

Azure DevOps Services

Благодаря кэшированию конвейера можно сократить время сборки, кешируя зависимости, которые будут использоваться повторно в последующих запусках. В этой статье вы узнаете, как использовать задачу "Кэш" для кэширования и восстановления пакетов NuGet.

Блокировка зависимостей

Чтобы настроить задачу кэширования, необходимо сначала заблокировать зависимости проекта и создать файл package.lock.json . Мы будем использовать хэш содержимого этого файла, чтобы создать уникальный ключ для кэша.

Чтобы заблокировать зависимости проекта, задайте для свойства RestorePackagesWithLockFile в csproj-файле значение true. Восстановление NuGet создает файл блокировки packages.lock.json в корневом каталоге проекта. Убедитесь, что вы проверка файл packages.lock.json в исходный код.

<PropertyGroup>
  <RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
</PropertyGroup>

Кэш пакетов NuGet

Нам потребуется создать переменную конвейера, чтобы указать расположение пакетов в агенте, на котором выполняется конвейер.

В этом примере содержимое файла packages.lock.json будет хэшировано для создания ключа динамического кэша. Это гарантирует, что при каждом изменении файла создается новый ключ кэша.

Снимок экрана: создание ключа кэша в Azure Pipelines.

variables:
  NUGET_PACKAGES: $(Pipeline.Workspace)/.nuget/packages

- task: Cache@2
  displayName: Cache
  inputs:
    key: 'nuget | "$(Agent.OS)" | **/packages.lock.json,!**/bin/**,!**/obj/**'
    restoreKeys: |
       nuget | "$(Agent.OS)"
       nuget
    path: '$(NUGET_PACKAGES)'
    cacheHitVar: 'CACHE_RESTORED'

Примечание

Кэши являются неизменяемыми. После создания кэша его содержимое невозможно изменить.

Восстановление кэша

Эта задача будет выполняться, только если CACHE_RESTORED переменная имеет значение false.

- task: NuGetCommand@2
  condition: ne(variables.CACHE_RESTORED, true)
  inputs:
    command: 'restore'
    restoreSolution: '**/*.sln'

Если во время задачи сборки появляется сообщение об ошибке "project.assets.json не найден", это можно устранить, удалив условие condition: ne(variables.CACHE_RESTORED, true) из задачи восстановления. Таким образом будет выполнена команда restore, создающая файл project.assets.json. Задача восстановления не будет скачивать пакеты, которые уже присутствуют в соответствующей папке.

Примечание

Конвейер может содержать одну или несколько задач кэширования, а задания и задачи в одном конвейере могут получать доступ к одному кэшу и совместно использовать его.

Сравнение производительности

Кэширование конвейера — это отличный способ ускорить выполнение конвейера. Ниже приведено параллельное сравнение производительности для двух разных конвейеров. Перед добавлением задачи кэширования (справа) задача восстановления заняла около 41 секунды. Мы добавили задачу кэширования во второй конвейер (слева) и настроили задачу восстановления для запуска при обнаружении промаха кэша. Задача восстановления в этом случае заняла 8 секунд.

Снимок экрана: производительность конвейера с кэшированием и без нее.

Ниже приведен полный конвейер YAML для справки:

pool:
  vmImage: 'windows-latest'

variables:
  solution: '**/*.sln'
  buildPlatform: 'Any CPU'
  buildConfiguration: 'Release'
  NUGET_PACKAGES: $(Pipeline.Workspace)/.nuget/packages

steps:
- task: NuGetToolInstaller@1
  displayName: 'NuGet tool installer'

- task: Cache@2
  displayName: 'NuGet Cache'
  inputs:
    key: 'nuget | "$(Agent.OS)" | **/packages.lock.json,!**/bin/**,!**/obj/**'
    restoreKeys: |
       nuget | "$(Agent.OS)"
       nuget
    path: '$(NUGET_PACKAGES)'
    cacheHitVar: 'CACHE_RESTORED'

- task: NuGetCommand@2
  displayName: 'NuGet restore'
  condition: ne(variables.CACHE_RESTORED, true)
  inputs:
    command: 'restore'
    restoreSolution: '$(solution)'

- task: VSBuild@1
  displayName: 'Visual Studio Build'
  inputs:
    solution: '$(solution)'
    platform: '$(buildPlatform)'
    configuration: '$(buildConfiguration)'