Compartilhar via


Armazenar em cache pacotes NuGet

Azure DevOps Services | Azure DevOps Server 2022 | Azure DevOps Server 2020

O cache de pipeline ajuda a reduzir o tempo de build 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.

Observação

Não há suporte para o cache de pipeline em pipelines de lançamento clássicos.

Pré-requisitos

Produto Requisitos
Azure DevOps - Um projeto do Azure DevOps.
- Permissões:
    – Para conceder acesso a todos os pipelines do projeto, você deve ser membro do grupo Administradores do Projeto.

Bloquear as 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 builds.

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

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

Armazenar em cache 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 a seguir, o conteúdo do packages.lock.json é convertido em hash para gerar uma chave de cache dinâmica. Isso garante que sempre que o arquivo for alterado, uma nova chave de cache será criada.

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 v2 task 
  inputs:
    key: 'nuget | "$(Agent.OS)" | **/packages.lock.json,!**/bin/**,!**/obj/**'
    restoreKeys: |
       nuget | "$(Agent.OS)"
       nuget
    path: '$(NUGET_PACKAGES)'
    cacheHitVar: 'CACHE_RESTORED'

Observação

Os caches são imutáveis, depois que um cache é criado, o conteúdo dele não pode ser alterado.

Restaurar cache

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

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

Observação

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

Lidar com erros de "project.assets.json não encontrado"

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

Observação

Um pipeline pode incluir várias tarefas de cache, e trabalhos e tarefas no mesmo pipeline podem acessar e compartilhar o mesmo cache.

Comparação de desempenho

O cache de pipelines 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 em um segundo pipeline e configuramos a tarefa de restauração para ser executada somente quando uma falha de cache ocorrer. A tarefa de restauração, nesse caso, foi concluída em apenas 8 segundos.

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

Veja abaixo 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 do .NET Core, desde que seu projeto use packages.lock.json para bloquear versões do pacote. Você pode habilitar isso definindo RestorePackagesWithLockFile para True no arquivo * Csproj* ou executando o seguinte comando: dotnet restore --use-lock-file.