Partilhar via


Cache de pacotes NuGet

Serviços de DevOps do Azure

Com o cache de pipeline, você pode reduzir o tempo de compilação armazenando em cache suas dependências para serem reutilizadas em execuções posteriores. Neste artigo, você aprenderá a usar a tarefa Cache para armazenar em cache e restaurar seus pacotes NuGet.

Nota

O cache de pipeline é suportado em trabalhos de pool de agentes para pipelines YAML e Classic. No entanto, ele não é suportado em pipelines de versão clássica.

Bloquear dependências

Para configurar a tarefa de cache, devemos primeiro bloquear as dependências do nosso projeto e criar um arquivo package.lock.json . Usaremos o hash do conteúdo deste arquivo para gerar uma chave exclusiva para nosso cache.

Para bloquear as dependências do projeto, defina a propriedade RestorePackagesWithLockFile no arquivo csproj como true. A restauração do NuGet gera um arquivo de bloqueio packages.lock.json no diretório raiz do seu projeto. Certifique-se de verificar seu arquivo packages.lock.json em seu código-fonte.

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

Cache de pacotes NuGet

Precisaremos criar uma variável de pipeline para apontar para o local de nossos pacotes no agente que executa o pipeline.

Neste exemplo, o conteúdo do packages.lock.json será colocado em hash para produzir uma chave de cache dinâmica. Isso garante que toda vez que o arquivo for modificado, uma nova chave de cache seja gerada.

Uma captura de tela mostrando como a chave de cache é gerada no 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'

Nota

Os caches são imutáveis, uma vez que um cache é criado, seu conteúdo não pode ser modificado.

Restaurar cache

Esta tarefa só será executada se a CACHE_RESTORED variável for false.

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

Se encontrar a mensagem de erro "project.assets.json não encontrado" durante a tarefa de compilação, pode resolvê-la removendo a condição condition: ne(variables.CACHE_RESTORED, true) da tarefa de restauro. Ao fazer isso, o comando restore será executado, gerando seu arquivo project.assets.json. A tarefa de restauração não baixará pacotes que já estejam presentes na pasta correspondente.

Nota

Um pipeline pode conter uma ou mais tarefas de cache, e trabalhos e tarefas dentro do mesmo pipeline podem acessar e compartilhar o mesmo cache.

Comparação de desempenho

O cache de pipeline é uma ótima maneira de acelerar a execução do pipeline. Aqui está uma comparação de desempenho lado a lado para dois pipelines diferentes. Antes de adicionar a tarefa de cache (à direita), a tarefa de restauração levou aproximadamente 41 segundos. Adicionamos a tarefa de cache a um segundo pipeline (à esquerda) e configuramos a tarefa de restauração para ser executada quando uma falha de cache for encontrada. A tarefa de restauração, neste caso, levou 8 segundos para ser concluída.

Uma captura de tela mostrando o desempenho do pipeline com e sem cache.

Abaixo está o pipeline YAML completo para referência:

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)'