Compartir a través de


Almacenamiento en caché de las canalizaciones

Servicios de Azure DevOps

El almacenamiento en caché de canalizaciones puede ayudar a reducir el tiempo de compilación mediante la reutilización de dependencias descargadas de ejecuciones anteriores, lo que evita la necesidad de volver a crear o volver a descargar los mismos archivos. Esto resulta especialmente útil en escenarios en los que las mismas dependencias se descargan repetidamente al principio de cada ejecución. Suele ser un proceso lento que implica cientos o miles de llamadas de red.

El almacenamiento en caché es más eficaz cuando el tiempo necesario para restaurar y guardar la memoria caché es menor que el tiempo necesario para volver a generar los archivos. Sin embargo, en algunos casos, es posible que el almacenamiento en caché no proporcione ventajas de rendimiento e incluso podría afectar negativamente al tiempo de compilación. Es importante evaluar su escenario específico para determinar si el almacenamiento en caché es el enfoque correcto.

Nota

No se admite el almacenamiento en caché de canalizaciones para canalizaciones de versión clásicas.

Cuándo usar artefactos de canalización versus caché de canalización

La caché de la canalización y los artefactos de canalización realizan funciones similares, pero están diseñados para distintos escenarios y no deben usarse de manera intercambiable.

  • Usar artefactos de canalización: cuando necesite tomar archivos específicos generados por un trabajo y compartirlos con otros trabajos (y esos otros trabajos puedan fallar sin ellos).

  • Utilice el almacenamiento en caché de la canalización: cuando desee mejorar el tiempo de compilación reutilizando archivos de ejecuciones previas (la ausencia de esos archivos no afectará a la capacidad del trabajo para ejecutarse).

Nota

El almacenamiento en caché de canalización y los artefactos de la canalización están disponibles sin costo alguno para todos los niveles (tanto gratuitos como de pago). Consulte Consumo de almacenamiento de artefactos para obtener más detalles.

Requisitos del agente autohospedado

Los siguientes ejecutables deben encontrarse en una carpeta que aparece en la PATH variable de entorno. Tenga en cuenta que estos requisitos solo se aplican a los agentes autohospedados, ya que los agentes hospedados vienen preinstalados con el software necesario.

Software de archivo / Plataforma Windows Linux Mac
GNU Tar Obligatorio Obligatorio No
Alquitrán BSD No No Obligatorio
7-Cremallera Recomendado No No

Tarea de caché: cómo funciona

El almacenamiento en caché se agrega a una canalización al añadir la tarea Caché a la sección de un trabajo steps.

Durante la ejecución de la canalización, cuando se encuentra un paso de caché, la tarea intenta restaurar la memoria caché en función de las entradas proporcionadas. Si no se encuentra ninguna memoria caché, se completa el paso y se ejecuta el siguiente paso del trabajo.

Una vez que todos los pasos del trabajo se han ejecutado correctamente, se agrega y desencadena automáticamente un paso especial "Post-job: Cache" para cada paso de "caché de restauración" que no se ha omitido. Este paso es responsable de guardar la memoria caché.

Nota

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

Configurar la memoria caché

La tarea Caché tiene dos argumentos necesarios: ruta de acceso y clave:

  1. path: ruta de acceso a la carpeta que desea almacenar en caché. Puede ser una ruta de acceso absoluta o relativa. Las rutas de acceso relativas se resuelven en $(System.DefaultWorkingDirectory).

    Sugerencia

    Puede usar variables predefinidas para almacenar la ruta de acceso a la carpeta que desea almacenar en caché. Sin embargo, no se admiten caracteres comodín.

  2. key: define el identificador de la memoria caché que desea restaurar o guardar. La clave se compone de una combinación de valores de cadena, rutas de acceso de archivo o patrones de archivo, con cada segmento separado por un | carácter.

    • Cadenas:
      Valor fijo (como el nombre de la memoria caché o un nombre de herramienta) o tomado de una variable de entorno (como el nombre actual del sistema operativo o del trabajo).

    • Rutas de acceso a archivos:
      Ruta de acceso a un archivo específico cuyo contenido será cifrado mediante un hash. El archivo debe existir en el momento en que se ejecuta la tarea. Cualquier segmento similar a una ruta de acceso de archivo se trata como tal, por lo que tenga cuidado, especialmente cuando use segmentos que contengan ., ya que esto puede provocar errores de "archivo no existe".

      Sugerencia

      Para evitar que un segmento de cadena que se asemeja a una ruta de acceso se trate como una ruta de archivo, envuélvelo con comillas dobles, por ejemplo: "my.key" | $(Agent.OS) | key.file

    • Patrones de archivo:
      Lista separada por comas de patrones de comodín estilo glob que deben coincidir con al menos un archivo. Ejemplos:

      • **/yarn.lock: todos los archivos yarn.lock en el directorio sources.
      • */asset.json, !bin/**: todos los archivos asset.json ubicados en un directorio bajo el directorio sources, excepto los del directorio bin .

El contenido de cualquier archivo identificado por una ruta de acceso o un patrón de archivo se hashea para generar una clave de caché dinámica. Esto resulta útil cuando el proyecto tiene archivos que identifican de forma única lo que se almacena en caché. Por ejemplo, los archivos como package-lock.json, yarn.lock, Gemfile.locko Pipfile.lock a menudo se hacen referencia a ellos en una clave de caché, ya que representan un conjunto único de dependencias. Las rutas de acceso o patrones de archivo relativos se resuelven con respecto a $(System.DefaultWorkingDirectory).

  • ejemplo:

En el ejemplo siguiente se muestra cómo almacenar en caché paquetes de Yarn:

variables:
  YARN_CACHE_FOLDER: $(Pipeline.Workspace)/s/.yarn

steps:
- task: Cache@2
  inputs:
    key: '"yarn" | "$(Agent.OS)" | yarn.lock'
    restoreKeys: |
       "yarn" | "$(Agent.OS)"
       "yarn"
    path: $(YARN_CACHE_FOLDER)
  displayName: Cache Yarn packages

- script: yarn --frozen-lockfile

En este ejemplo, la clave de caché consta de tres partes: una cadena estática ("yarn"), el sistema operativo en el que se ejecuta el trabajo (ya que la memoria caché es única por sistema operativo) y el hash del yarn.lock archivo (que identifica de forma única las dependencias).

En la primera ejecución después de agregar la tarea, el paso de caché notificará una "falta de caché" porque la memoria caché identificada por esta clave no existe. Después del último paso, se creará una caché a partir de los archivos de $(Pipeline.Workspace)/s/.yarn y se cargará. En la siguiente ejecución, el paso de caché notificará un "impacto en caché" y se descargará y restaurará el contenido de la caché.

Al usar checkout: self, el repositorio se descargará en $(Pipeline.Workspace)/s, y es probable que su carpeta .yarn se encuentre dentro del propio repositorio.

Nota

Pipeline.Workspace es la ruta de acceso local del agente que ejecuta la canalización donde se crean todos los directorios. Esta variable tiene el mismo valor que Agent.BuildDirectory. Si no usa checkout: self, asegúrese de actualizar la YARN_CACHE_FOLDER variable para que apunte a la ubicación de .yarn en el repositorio.

Uso de claves de restauración

restoreKeys permite consultar varias claves exactas o prefijos de clave. Se utiliza como alternativa cuando el key especificado no produce un acierto. Una clave de restauración busca una clave por prefijo y devuelve la entrada de caché creada más recientemente. Esto resulta útil cuando la tubería no encuentra una coincidencia exacta, pero todavía quiere usar un acierto de caché parcial.

Para especificar varias claves de restauración, enumere en líneas independientes. El orden en el que se prueban las claves de restauración es de arriba a abajo.

  • ejemplo:

Este es un ejemplo de cómo usar claves de restauración para almacenar en caché paquetes de Yarn:

variables:
  YARN_CACHE_FOLDER: $(Pipeline.Workspace)/.yarn

steps:
- task: Cache@2
  inputs:
    key: '"yarn" | "$(Agent.OS)" | yarn.lock'
    restoreKeys: |
       yarn | "$(Agent.OS)"
       yarn
    path: $(YARN_CACHE_FOLDER)
  displayName: Cache Yarn packages

- script: yarn --frozen-lockfile

En este ejemplo, la tarea de caché primero intenta restaurar la clave especificada. Si la clave no existe en la memoria caché, intenta la primera clave de restauración: yarn | $(Agent.OS). Esto busca las claves de caché que coincidan exactamente o empiecen por este prefijo.

Se puede producir una coincidencia de prefijo si el hash del yarn.lock archivo ha cambiado. Por ejemplo, si la memoria caché contiene la clave yarn | $(Agent.OS) | old-yarn.lock (donde old-yarn.lock tiene un hash diferente al actual yarn.lock), esta clave de restauración daría lugar a un acierto parcial de caché.

Si la primera clave de restauración no produce una coincidencia, la siguiente clave de restauración (yarn) Buscará cualquier clave de caché que comience por yarn. Para las coincidencias de prefijo, el proceso de restauración devuelve la entrada de caché creada más recientemente.

Nota

Una canalización puede incluir varias tareas de almacenamiento en caché y no hay límite para el almacenamiento en caché. Los trabajos y las tareas dentro de la misma canalización pueden acceder y compartir la misma caché.

Uso de la condición de restauración

En algunos escenarios, puede que desee ejecutar condicionalmente los pasos en función de si la memoria caché se restauró correctamente. Por ejemplo, puede omitir un paso que instale las dependencias si se restauró la memoria caché. Esto se puede lograr mediante el cacheHitVar argumento .

Establecer esta entrada en el nombre de una variable de entorno hace que la variable se establezca en true cuando haya un acierto de caché, inexact si una clave de restauración produce un acierto de caché parcial y false , si no se encuentra ninguna caché. A continuación, puede hacer referencia a esta variable en una condición de paso o dentro de un script.

Este es un ejemplo en el que se omite el install-deps.sh paso cuando se restaura la memoria caché:

steps:
- task: Cache@2
  inputs:
    key: mykey | mylockfile
    restoreKeys: mykey
    path: $(Pipeline.Workspace)/mycache
    cacheHitVar: CACHE_RESTORED

- script: install-deps.sh
  condition: ne(variables.CACHE_RESTORED, 'true')

- script: build.sh

Aislamiento y seguridad de caché

Para garantizar el aislamiento entre las memorias caché de diferentes canalizaciones y diferentes ramas, cada caché se almacena dentro de un contenedor lógico denominado ámbito. Los ámbitos actúan como límites de seguridad que garantizan:

  • Los trabajos de una canalización no pueden acceder a los cachés de otra canalización.

  • Los trabajos que compilan solicitudes de incorporación de cambios pueden leer cachés de la rama de destino (para la misma canalización), pero no pueden escribir (crear) cachés en el ámbito de la rama de destino.

Cuando se encuentra un paso de caché durante una ejecución, la memoria caché identificada por la clave se solicita desde el servidor. A continuación, el servidor busca una memoria caché con esta clave de los ámbitos visibles para el trabajo y devuelve la memoria caché (si está disponible). Al guardar en caché (al final del trabajo), se escribe una caché en el ámbito que representa la canalización y la rama.

CI, manual y ejecuciones programadas

Alcance Leer Escribir
Rama de origen
rama main No
rama master No

Ejecuciones de solicitudes de incorporación de cambios

Alcance Leer Escribir
Rama de origen No
Rama de destino No
Rama intermedia (por ejemplo, refs/pull/1/merge)
rama main No
rama master No

Ejecuciones de bifurcación de solicitud de incorporación de cambios

Sucursal Leer Escribir
Rama de destino No
Rama intermedia (por ejemplo, refs/pull/1/merge)
rama main No
rama master No

Sugerencia

Dado que las memorias caché ya están limitadas a un proyecto, canalización y rama, no es necesario incluir ningún proyecto, canalización o identificadores de rama en la clave de caché.

Ejemplos

En el caso de los proyectos de Ruby que usan Bundler, invalide la BUNDLE_PATH variable de entorno para establecer la ruta de acceso donde Bundler busca Gems.

ejemplo:

variables:
  BUNDLE_PATH: $(Pipeline.Workspace)/.bundle

steps:
- task: Cache@2
  displayName: Bundler caching
  inputs:
    key: 'gems | "$(Agent.OS)" | Gemfile.lock'
    path: $(BUNDLE_PATH)
    restoreKeys: | 
      gems | "$(Agent.OS)"
      gems   

Problemas conocidos y comentarios

Si tiene problemas para configurar el almacenamiento en caché en la canalización, compruebe la lista de problemas abiertos en el microsoft/azure-pipelines-tasks repositorio. Si no ve el problema en la lista, cree uno nuevo y proporcione la información necesaria sobre su escenario.

Preguntas y respuestas

P: ¿Puedo borrar una memoria caché?

R: No se admite borrar una memoria caché. Sin embargo, puede evitar que se produzcan aciertos en las cachés existentes agregando una cadena literal (como version2) en su clave de caché. Por ejemplo, cambie la siguiente clave de caché:

key: 'yarn | "$(Agent.OS)" | yarn.lock'

Por esta otra:

key: 'version2 | yarn | "$(Agent.OS)" | yarn.lock'

P: ¿Cuándo expira una memoria caché?

R: Las memorias caché expiran después de siete días sin actividad.

P: ¿Cuándo se carga la memoria caché?

Se crea una memoria caché a partir de la que has especificado path y se carga después del último paso del trabajo. Consulte el ejemplo para obtener más información.

P: ¿Existe un límite en el tamaño de una memoria caché?

R: No se aplica ningún límite en el tamaño de las cachés individuales o el tamaño total de la caché dentro de una organización.