Condividi tramite


Memorizzazione nella cache della pipeline

Servizi di Azure DevOps

La memorizzazione nella cache della pipeline consente di ridurre il tempo di compilazione riutilizzando le dipendenze scaricate dalle esecuzioni precedenti, evitando la necessità di ricreare o scaricare nuovamente gli stessi file. Ciò è particolarmente utile negli scenari in cui le stesse dipendenze vengono scaricate ripetutamente all'inizio di ogni esecuzione. Si tratta spesso di un processo dispendioso in termini di tempo che coinvolge centinaia o migliaia di chiamate di rete.

La memorizzazione nella cache è più efficace quando il tempo necessario per ripristinare e salvare la cache è inferiore al tempo necessario per rigenerare i file. Tuttavia, in alcuni casi, la memorizzazione nella cache potrebbe non offrire vantaggi in termini di prestazioni e potrebbe influire negativamente sul tempo di compilazione. È importante valutare lo scenario specifico per determinare se la memorizzazione nella cache è l'approccio corretto.

Nota

La memorizzazione nella cache della pipeline non è supportata per le pipeline di distribuzione classica.

Quando usare gli artefatti della pipeline rispetto alla memorizzazione nella cache della pipeline

La memorizzazione nella cache delle pipeline e gli artefatti della pipeline eseguono funzioni simili, ma sono destinate a scenari diversi e non devono essere usati in modo intercambiabile.

  • Usare gli artefatti della pipeline: quando è necessario acquisire file specifici generati da un processo e condividerli con altri processi (e questi altri processi potrebbero avere esito negativo senza di essi).

  • Usare la memorizzazione nella cache della pipeline: quando si vuole migliorare il tempo di compilazione riutilizzando i file dalle esecuzioni precedenti e il fatto di non avere tali file non influisce sulla capacità del processo di essere eseguito.

Nota

La memorizzazione nella cache e gli artefatti della pipeline sono disponibili gratuitamente per tutti i livelli (gratuiti e a pagamento). Vedere Consumo spazio di archiviazione degli artefatti per maggiori dettagli.

Requisiti dell'agente autogestito

I seguenti file eseguibili devono trovarsi in una cartella elencata nella PATH variabile di ambiente. Si noti che questi requisiti si applicano solo agli agenti self-hosted, perché gli agenti ospitati vengono preinstallati con il software necessario.

Software d'archivio/piattaforma Finestre Linux Mac
GNU Tar Obbligatorio Obbligatorio NO
BSD Tar (un'applicazione di archiviazione e compressione) NO NO Obbligatorio
7-Zip Raccomandato NO NO

Attività cache: funzionamento

La memorizzazione nella cache viene aggiunta a una pipeline aggiungendo l'attività Cache alla sezione steps di un processo.

Durante l'esecuzione della pipeline, quando viene rilevato un passaggio della cache, l'attività tenta di ripristinare la cache in base agli input forniti. Se non viene trovata alcuna cache, il passaggio viene completato e viene eseguito il passaggio successivo del processo.

Una volta che tutti i passaggi del processo sono stati eseguiti correttamente, viene automaticamente aggiunto e attivato un passaggio speciale "Post-processo: cache" per ogni passaggio "ripristina cache" che non è stato ignorato. Questo passaggio è responsabile del salvataggio della cache .

Nota

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

Configurare l'attività di Cache

L'attività Cache ha due argomenti obbligatori: percorso e chiave:

  1. path: percorso della cartella da memorizzare nella cache. Può trattarsi di un percorso assoluto o relativo. I percorsi relativi vengono determinati in $(System.DefaultWorkingDirectory).

    Suggerimento

    È possibile usare variabili predefinite per archiviare il percorso della cartella da memorizzare nella cache. Tuttavia, i caratteri jolly non sono supportati.

  2. key: definisce l'identificatore per la cache da ripristinare o salvare. La chiave è costituita da una combinazione di valori stringa, percorsi di file o modelli di file, con ogni segmento separato da un | carattere.

    • Stringhe:
      Valore fisso ,ad esempio il nome della cache o il nome di uno strumento, o ricavato da una variabile di ambiente (ad esempio il sistema operativo o il nome del processo corrente).

    • Percorsi di file:
      Percorso di un file specifico il cui contenuto verrà sottoposto a hashing. Il file deve esistere al momento dell'esecuzione dell'attività. Qualsiasi segmento simile a un percorso di file viene considerato come tale, quindi prestare attenzione, soprattutto quando si usano segmenti contenenti ., in quanto ciò può causare errori di "file non esistono".

      Suggerimento

      Per evitare che un segmento di stringa simile al percorso venga trattato come un percorso di file, racchiuderlo tra virgolette doppie, ad esempio: "my.key" | $(Agent.OS) | key.file

    • Modelli di file:
      Elenco delimitato da virgole di modelli con caratteri jolly di tipo glob che devono corrispondere ad almeno un file. Esempi:

      • **/yarn.lock: tutti i file yarn.lock nella directory sources.
      • */asset.json, !bin/**: tutti i fileasset.json presenti in una sottodirectory della cartella sources, ad eccezione di quelli nella cartella bin.

Il contenuto di qualsiasi file identificato da un percorso di file o da un modello di file viene sottoposto a hash per generare una chiave della cache dinamica. Ciò è utile quando il progetto include file che identificano in modo univoco ciò che viene memorizzato nella cache. Ad esempio, i file come package-lock.json, yarn.lock, Gemfile.lock, o Pipfile.lock vengono spesso citati in una chiave della cache, poiché rappresentano un insieme unico di dipendenze. I percorsi o i modelli di file relativi vengono risolti in $(System.DefaultWorkingDirectory).

  • Esempio:

L'esempio seguente illustra come memorizzare nella cache i pacchetti 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

In questo esempio la chiave della cache è costituita da tre parti: una stringa statica ("yarn"), il sistema operativo in cui è in esecuzione il processo (poiché la cache è univoca per ogni sistema operativo) e l'hash del yarn.lock file (che identifica in modo univoco le dipendenze).

Alla prima esecuzione dopo l'aggiunta dell'attività, la fase della cache segnalerà un "assenza di cache" perché la cache identificata da questa chiave identificativa non esiste. Dopo l'ultimo passaggio, verrà creata una cache dai file in $(Pipeline.Workspace)/s/.yarn e verrà caricata. All'esecuzione successiva, il passaggio della cache riporterà un "cache hit" e il contenuto della cache verrà scaricato e ripristinato.

Quando si usa checkout: self, il repository viene estratto in $(Pipeline.Workspace)/s, e la cartella .yarn probabilmente risiederà nel repository stesso.

Nota

Pipeline.Workspace è il percorso locale dell'agente che esegue la pipeline in cui vengono create tutte le directory. Questa variabile ha lo stesso valore di Agent.BuildDirectory. Se non si usa checkout: self, assicurarsi di aggiornare la YARN_CACHE_FOLDER variabile in modo che punti alla posizione di .yarn nel repository.

Usare le chiavi di ripristino

restoreKeys consente di eseguire query su più chiavi esatte o prefissi di chiave. Viene utilizzato come fallback quando l'oggetto specificato key non restituisce un risultato utile. Una chiave di ripristino cerca una chiave per prefisso e restituisce la voce della cache creata più di recente. Ciò è utile quando la pipeline non riesce a trovare una corrispondenza esatta, ma vuole comunque usare un hit parziale della cache.

Per specificare più chiavi di ripristino, elencarle in righe separate. L'ordine in cui vengono tentate le chiavi di ripristino è dall'alto verso il basso.

  • Esempio:

Ecco un esempio di come usare le chiavi di ripristino per memorizzare nella cache i pacchetti 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

In questo esempio l'attività cache tenta innanzitutto di ripristinare la chiave specificata. Se la chiave non esiste nella cache, prova la prima chiave di ripristino: yarn | $(Agent.OS). Viene eseguita la ricerca di eventuali chiavi della cache che corrispondono esattamente o iniziano con questo prefisso.

Una corrispondenza del prefisso può verificarsi se l'hash del yarn.lock file è stato modificato. Ad esempio, se la cache contiene la chiave yarn | $(Agent.OS) | old-yarn.lock (dove old-yarn.lock ha un hash diverso da quello corrente yarn.lock), questa chiave di ripristino genererà un riscontro parziale nella cache.

Se la prima chiave di ripristino non restituisce una corrispondenza, la chiave di ripristino successiva (yarn) Verrà eseguita la ricerca di qualsiasi chiave della cache che inizia con yarn. Per le corrispondenze di prefisso, il processo di ripristino della cache restituisce l'entrata della cache creata più di recente.

Nota

Una pipeline può includere più attività di memorizzazione nella cache e non esiste alcun limite di archiviazione per la memorizzazione nella cache. I processi e le attività all'interno della stessa pipeline possono accedere e condividere la stessa cache.

Usare la condizione di ripristino

In alcuni scenari, è possibile eseguire i passaggi in modo condizionale in base al fatto che la cache sia stata ripristinata correttamente. Ad esempio, è possibile ignorare un passaggio che installa le dipendenze se la cache è stata ripristinata. Questa operazione può essere ottenuta usando l'argomento cacheHitVar .

Se si imposta questo input sul nome di una variabile di ambiente, la variabile viene impostata true su quando si verifica un riscontro nella cache, inexact se una chiave di ripristino restituisce un riscontro parziale nella cache e false se non viene trovata alcuna cache. È quindi possibile fare riferimento a questa variabile in una condizione di passaggio o all'interno di uno script.

Ecco un esempio in cui il install-deps.sh passaggio viene ignorato quando viene ripristinata la cache:

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

Isolamento e sicurezza della cache

Per garantire l'isolamento tra cache da pipeline diverse e rami diversi, ogni cache viene archiviata all'interno di un contenitore logico denominato ambito. Gli ambiti fungono da limite di sicurezza che garantisce:

  • I job di una pipeline non possono accedere alle cache di un'altra pipeline.

  • I processi che creano richieste pull possono leggere le cache dal ramo di destinazione (per la stessa pipeline), ma non possono scrivere (creare) cache nell'ambito del ramo di destinazione.

Quando viene rilevato un passaggio della cache durante un'esecuzione, la cache identificata dalla chiave viene richiesta dal server. Il server cerca quindi una cache con questa chiave dagli ambiti visibili al processo e restituisce la cache (se disponibile). Al salvataggio della cache (alla fine del processo), una cache viene scritta nello spazio che rappresenta la pipeline e il ramo.

Esecuzioni CI, manuali e pianificate

Ambito Leggere Scrivere
Ramo di origine
ramo main NO
ramo master NO

Esecuzioni delle richieste di pull

Ambito Leggere Scrivere
Ramo di origine NO
Ramo di destinazione NO
Ramo intermedio (ad esempio refs/pull/1/merge)
ramo main NO
ramo master NO

Esecuzioni della richiesta pull del fork

Filiale Leggere Scrivere
Ramo di destinazione NO
Ramo intermedio (ad esempio refs/pull/1/merge)
ramo main NO
ramo master NO

Suggerimento

Poiché le cache hanno già come ambito un progetto, una pipeline e un ramo, non è necessario includere alcun progetto, pipeline o identificatori di ramo nella chiave della cache.

Esempi

Per i progetti Ruby che usano Bundler, eseguire l'override della BUNDLE_PATH variabile di ambiente per impostare il percorso in cui Bundler cerca gemme.

Esempio:

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   

Problemi noti e feedback

Se si verificano problemi durante la configurazione del caching della pipeline, controllare l'elenco dei problemi aperti nel microsoft/azure-pipelines-tasks repository. Se il problema non è elencato, crearne uno nuovo e fornire le informazioni necessarie sullo scenario.

Domande e risposte

D: È possibile cancellare una cache?

R: La cancellazione di una cache non è supportata. Tuttavia, è possibile evitare riscontri nelle cache esistenti aggiungendo un valore letterale stringa (ad esempio version2) alla chiave della cache. Ad esempio, modificare la chiave della cache seguente da questo:

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

A questo scopo:

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

D: Quando scade una cache?

R: Le cache scadono dopo sette giorni di assenza di attività.

D: Quando viene caricata la cache?

R: una cache viene creata dall'oggetto specificato path e caricata dopo l'ultimo passaggio del processo. Per altri dettagli, vedere l'esempio di .

D: Esiste un limite per le dimensioni di una cache?

R: Non esiste alcun limite applicato alle dimensioni delle singole cache o alle dimensioni totali della cache all'interno di un'organizzazione.