Compartir a través de


Almacenamiento en caché de paquetes NuGet

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

El almacenamiento en caché de canalizaciones ayuda a reducir el tiempo de compilación mediante el almacenamiento de dependencias para su reutilización en futuras ejecuciones. En este artículo, obtendrá información sobre cómo a usar la tarea Caché para almacenar en caché y restaurar los paquetes NuGet.

Nota:

El almacenamiento en caché de canalizaciones no se admite en canalizaciones de versión clásica.

Prerrequisitos

Producto Requisitos
Azure DevOps - Un proyecto de Azure DevOps .
- Permisos:
    - Para conceder acceso a todas las canalizaciones del proyecto, debe ser miembro del Grupo de Administradores del Proyecto .

Bloqueo de dependencias

Antes de configurar la tarea de caché, debe bloquear las dependencias del proyecto y generar un archivo package.lock.json. La clave de caché única se deriva del hash del contenido de este archivo de bloqueo para garantizar la coherencia entre compilaciones.

Para bloquear las dependencias del proyecto, agregue la propiedad RestorePackagesWithLockFile al archivo csproj y establézcalo en true. Al ejecutar nuget restore, genera un archivo packages.lock.json en el directorio raíz del proyecto. Asegúrese de comprobar el archivo packages.lock.json en el código fuente.

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

Almacenamiento en caché de paquetes NuGet

Para almacenar en caché paquetes NuGet, defina una variable de canalización que apunte a la ubicación de los paquetes en el agente que ejecuta la canalización.

En el ejemplo siguiente, el contenido del packages.lock.json se hash para generar una clave de caché dinámica. Esto garantiza que cada vez que cambia el archivo, se crea una nueva clave de caché.

captura de pantalla que muestra cómo se genera la clave de caché en 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:

Las memorias caché son inmutables, una vez creada una caché, no se puede modificar su contenido.

Restauración de caché

La siguiente tarea solo se ejecutará si la variable CACHE_RESTORED es false. Esto significa que si se produce una acierto de caché (los paquetes ya están disponibles en la memoria caché), se omite el paso de restauración para ahorrar tiempo y recursos. Si no se encuentra ninguna memoria caché, el comando restore se ejecuta para descargar las dependencias necesarias.

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

Nota:

Si usa Ubuntu 24.04 o posterior, debe usar la tarea NuGetAuthenticate con la CLI de .NET en lugar de la tarea NuGetCommand@2. Consulte Compatibilidad con las imágenes más recientes hospedadas en Ubuntu para obtener más detalles.

Administrar los errores "project.assets.json no encontrado"

Si encuentra el error "project.assets.json no encontrado" durante la tarea de compilación, quite la condición condition: ne(variables.CACHE_RESTORED, true) de la tarea de restauración. Esto garantiza que el comando restore se ejecute y genere el archivo project.assets.json. La tarea de restauración no vuelve a descargar paquetes que ya están presentes en la carpeta correspondiente.

Nota:

Una canalización puede incluir varias tareas de almacenamiento en caché, y los trabajos y tareas dentro de la misma canalización pueden acceder y compartir la misma caché.

Comparación del rendimiento

El almacenamiento en caché de pipelines reduce significativamente el tiempo necesario para restaurar las dependencias, lo que conduce a compilaciones más rápidas. En la siguiente comparación se muestra el impacto del almacenamiento en caché en el tiempo de ejecución de la canalización para dos canalizaciones diferentes:

  • sin almacenamiento en caché (derecha): la tarea de restauración tardó aproximadamente 41 segundos.

  • Con el almacenamiento en caché (izquierda): agregamos la tarea de almacenamiento en caché a una segunda canalización y configuramos la tarea de restauración para que solo se ejecute cuando se produzca una falta de caché. La tarea de restauración en este caso se completó en tan solo 8 segundos.

captura de pantalla que muestra el rendimiento de la canalización con y sin almacenamiento en caché.

A continuación se muestra la canalización YAML completa como referencia:

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

Este enfoque también se aplica a los proyectos de .NET Core, siempre que el proyecto use packages.lock.json para bloquear las versiones del paquete. Puede habilitarlo estableciendo RestorePackagesWithLockFile en True en el archivo * Csproj* o ejecutando el siguiente comando: dotnet restore --use-lock-file.