Partilhar via


Cache de pacotes NuGet

Serviços de DevOps do Azure | Azure DevOps Server | Azure DevOps Server 2022

O cache de pipeline ajuda a reduzir o tempo de compilação armazenando dependências para reutilização em execuções futuras. Neste artigo, você aprenderá a usar a tarefa Cache para armazenar em cache e restaurar seus pacotes NuGet.

Nota

A cache de pipeline não é suportada em pipelines de lançamento clássico.

Pré-requisitos

Produto Requisitos
Azure DevOps - Um projeto Azure DevOps .
- Permissões:
    - Para conceder acesso a todos os pipelines no projeto, deves ser membro do grupo Administradores de Projeto.

Bloquear dependências

Antes de configurar a tarefa de cache, você precisa bloquear as dependências do projeto e gerar um arquivo package.lock.json. A chave de cache exclusiva é derivada do hash do conteúdo desse arquivo de bloqueio para garantir a consistência entre as compilações.

Para bloquear as dependências do projeto, adicione a propriedade RestorePackagesWithLockFile ao seu arquivo csproj do e defina-o como true. Quando você executa nuget restore, ele gera um arquivo packages.lock.json no diretório raiz do projeto. Certifique-se de incluir o seu arquivo packages.lock.json no seu código-fonte.

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

Cache de pacotes NuGet

Para armazenar em cache pacotes NuGet, defina uma variável de pipeline que aponte para o local dos pacotes no agente que executa o pipeline.

No exemplo abaixo, o conteúdo do packages.lock.json é colocado em hash para gerar uma chave de cache dinâmica. Isso garante que, sempre que o arquivo for alterado, uma nova chave de cache seja criada.

Uma captura de tela exibindo como a chave de cache é gerada no Azure Pipelines.

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

- task: Cache@2
  displayName: Cache v2 task 
  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

A tarefa seguinte só será executada se a variável CACHE_RESTORED for falso. Isso significa que, se ocorrer um acerto de cache (os pacotes já estão disponíveis no cache), a etapa de restauração será ignorada para economizar recursos e tempo. Se nenhum cache for encontrado, o comando restore será executado para baixar as dependências necessárias.

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

Nota

Se você estiver usando o Ubuntu 24.04 ou posterior, você deve usar a tarefa NuGetAuthenticate com a CLI do .NET em vez da tarefa NuGetCommand@2. Consulte Suporte para imagens hospedadas mais recentes do Ubuntu para obter mais detalhes.

Lidar com o erro "project.assets.json não encontrado"

Se você encontrar o erro "project.assets.json não encontrado" durante a tarefa de compilação, remova a condição condition: ne(variables.CACHE_RESTORED, true) da tarefa de restauração. Isso garante que o comando restore seja executado e gere o arquivo project.assets.json. A tarefa de restauração não baixará novamente os pacotes que já estão presentes na pasta correspondente.

Nota

Um pipeline pode incluir várias 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 reduz significativamente o tempo necessário para restaurar dependências, resultando em compilações mais rápidas. A comparação a seguir ilustra o impacto do cache no tempo de execução do pipeline para dois pipelines diferentes:

  • Sem cache (à direita): A tarefa de restauração levou aproximadamente 41 segundos.

  • Com cache (esquerda): adicionamos a tarefa de cache a um segundo pipeline e configuramos a tarefa de restauração para ser executada somente quando ocorrer uma falha de cache. A tarefa de restauração, neste caso, foi concluída em apenas 8 segundos.

Uma captura de tela exibindo 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)'

Essa abordagem também se aplica a projetos .NET Core, desde que seu projeto use packages.lock.json para bloquear versões de pacote. Você pode habilitar isso definindo RestorePackagesWithLockFile para True no arquivo * Csproj* ou executando o seguinte comando: dotnet restore --use-lock-file.