Condividi tramite


Memorizzare nella cache i pacchetti NuGet

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

La memorizzazione nella cache della pipeline consente di ridurre il tempo di compilazione archiviando le dipendenze per il riutilizzo in esecuzioni future. Questo articolo illustra come utilizzare l'attività cache per salvare nella cache e ripristinare i pacchetti NuGet.

Nota

La memorizzazione nella cache della pipeline non è supportata nelle pipeline di rilascio classiche.

Prerequisiti

Prodotto Requisiti
Azure DevOps - Un progetto Azure DevOps.
Autorizzazioni - :
    - Per concedere l'accesso a tutte le pipeline del progetto, è necessario essere membri del gruppo Project Administrators.

Bloccare le dipendenze

Prima di configurare l'attività della cache, è necessario bloccare le dipendenze del progetto e generare un file package.lock.json. La chiave della cache univoca deriva dall'hash del contenuto di questo file di blocco per garantire la coerenza tra le compilazioni.

Per bloccare le dipendenze del progetto, aggiungere la proprietà RestorePackagesWithLockFile al file csproj e impostarla su true. Quando si esegue nuget restore, viene generato un file packages.lock.json nella directory radice del progetto. Assicurarsi di controllare il file packages.lock.json nel codice sorgente.

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

Memorizzare nella cache i pacchetti NuGet

Per memorizzare nella cache i pacchetti NuGet, definire una variabile della pipeline che punti al percorso dei pacchetti nell'agente che esegue la pipeline.

Nell'esempio seguente il contenuto del packages.lock.json viene sottoposto a hash per generare una chiave della cache dinamica. In questo modo si garantisce che ogni volta che il file viene modificato, viene creata una nuova chiave della cache.

Screenshot che mostra come viene generata la chiave della cache in 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

Le cache non sono modificabili, una volta creata una cache, il relativo contenuto non può essere modificato.

Ripristinare la cache

L'attività seguente verrà eseguita solo se la variabile CACHE_RESTORED è false. Ciò significa che se si verifica un riscontro nella cache (i pacchetti sono già disponibili nella cache), il passaggio di ripristino viene ignorato per risparmiare tempo e risorse. Se non viene trovata alcuna cache, il comando di ripristino viene eseguito per scaricare le dipendenze necessarie.

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

Nota

Se si usa Ubuntu 24.04 o versione successiva, è necessario usare l'attività NuGetAuthenticate con l'interfaccia della riga di comando di .NET anziché l'attività NuGetCommand@2. Per ulteriori dettagli, vedere il supporto per le immagini ospitate di Ubuntu più recenti.

Gestire gli errori "project.assets.json non trovati"

Se si verifica l'errore "project.assets.json non trovato" durante l'attività di compilazione, rimuovere la condizione condition: ne(variables.CACHE_RESTORED, true) dall'attività di ripristino. In questo modo il comando di ripristino viene eseguito e genera il file project.assets.json. L'attività di ripristino non scarica nuovamente i pacchetti già presenti nella cartella corrispondente.

Nota

Una pipeline può includere più attività di memorizzazione nella cache e processi e attività all'interno della stessa pipeline possono accedere e condividere la stessa cache.

Confronto delle prestazioni

La memorizzazione nella cache della pipeline riduce significativamente il tempo necessario per ripristinare le dipendenze, causando compilazioni più veloci. Il confronto seguente illustra l'impatto della memorizzazione nella cache sul tempo di esecuzione della pipeline per due pipeline diverse:

  • Senza memorizzazione nella cache (a destra): l'attività di ripristino ha richiesto circa 41 secondi.

  • Con memorizzazione nella cache (a sinistra): Abbiamo aggiunto l'attività di memorizzazione nella cache a una seconda pipeline e configurato l'attività di ripristino per essere eseguita solo in caso di un miss della cache. L'attività di ripristino in questo caso è stata completata in soli 8 secondi.

Screenshot che mostra le prestazioni della pipeline con e senza memorizzazione nella cache.

Di seguito è riportata la pipeline YAML completa per riferimento:

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

Questo approccio si applica anche ai progetti .NET Core, purché il progetto usi packages.lock.json per bloccare le versioni dei pacchetti. È possibile abilitare questa opzione impostando RestorePackagesWithLockFile su True nel file * Csproj* oppure eseguendo il comando seguente: dotnet restore --use-lock-file.