Cachelagring av pipeline
Azure DevOps Services
Pipeline-cachelagring kan minska byggtiden genom att tillåta att utdata eller nedladdade beroenden från en körning återanvänds i senare körningar, vilket minskar eller undviker att behöva betala för att återskapa alternativt ladda ner samma filer igen. Cachelagring är särskilt användbart i scenarier där samma beroenden laddas ned upprepade gånger vid varje körning. Det här är ofta en tidskrävande process som omfattar hundratals eller tusentals nätverksanrop.
Cachelagring kan vara effektivt för att förbättra byggtiden, förutsatt att tiden för att återställa och spara cachen är mindre än den tid då utdata skapas igen från grunden. På grund av detta kanske cachelagring inte är effektivt i alla scenarier och kan faktiskt ha en negativ inverkan på byggtiden.
Obs
Cachelagring av rörledning stöds inte i klassiska utgivningsrörledningar.
När artefakter ska användas jämfört med cachelagring
Pipelincaching och pipelineartefakter utför liknande funktioner, men de är utformade för olika scenarier och bör inte användas växelvis.
Använd pipelineartefakter när du behöver ta specifika filer som skapats i ett jobb och dela dem med andra jobb (och dessa andra jobb misslyckas förmodligen utan dem).
Använd cachelagring av pipelinen när du vill förbättra byggtiden genom att återanvända filer från tidigare körningar (och om du inte har dessa filer påverkas inte jobbets möjlighet att köras).
Anteckning
Pipeline-cache och pipelineartefakter är gratis för alla nivåer (gratis och för betalversioner). Mer information finns i Artifakternas lagringsförbrukning.
Cacheuppgift: så här fungerar den
Caching läggs till i en pipeline med hjälp av Cache-aktiviteten. Den här uppgiften fungerar som alla andra aktiviteter och läggs till i steps
delen av ett jobb.
När ett cachesteg påträffas under en körning återställer uppgiften cachen baserat på de angivna indata. Om ingen cache hittas slutförs steget och nästa steg i jobbet körs.
När alla steg i jobbet har körts och förutsatt att ett lyckades jobbstatus läggs ett särskilt "Post-job: Cache" steg automatiskt till och utlöses för varje "återställningscache" steg som inte hoppades över. Det här steget har ansvar för att spara cacheminnet .
Anteckning
Cacheminnen är oföränderliga, vilket innebär att när en cache har skapats är dess innehåll oföränderligt.
Konfigurera cachningsuppgiften
Uppgiften Cache har två obligatoriska argument: nyckel och sökväg:
-
sökväg: sökvägen till mappen som ska cachelagrats. Kan vara en absolut eller relativ sökväg. Relativa sökvägar löses upp mot
$(System.DefaultWorkingDirectory)
.
Not
Du kan använda fördefinierade variabler för att lagra sökvägen till den mapp du vill cacha, men jokertecken stöds inte.
-
nyckel: ska anges till identifieraren för cacheminnet som du vill återställa eller spara. Nycklarna består av en kombination av strängvärden, filsökvägar eller filmönster, där varje segment avgränsas med ett
|
tecken.
Strängar:
Fast värde (till exempel namnet på cachen eller ett verktygsnamn) eller hämtat från en miljövariabel (till exempel det aktuella operativsystemet eller det aktuella jobbnamnet)Filsökvägar:
Sökväg till en specifik fil vars innehåll ska hashas. Den här filen måste finnas när aktiviteten körs. Tänk på att alla nyckelsegment som "ser ut som en filsökväg" behandlas som en filsökväg. I synnerhet omfattar detta segment som innehåller en.
. Detta kan leda till att aktiviteten misslyckas när den här "filen" inte finns.Tips
Om du vill undvika att ett sökvägsliknande strängsegment behandlas som en filsökväg, omsluter du det med dubbla citattecken, till exempel:
"my.key" | $(Agent.OS) | key.file
Filmönster:
Kommaavgränsad lista över jokerteckenmönster i globformat som måste matcha minst en fil. Till exempel:-
**/yarn.lock
: alla yarn.lock-filer under källkatalogen -
*/asset.json, !bin/**
: alla asset.json filer som finns i en katalog under källkatalogen, förutom under bin-katalogen
-
Innehållet i en fil som identifieras av en filsökväg eller ett filmönster hashas för att skapa en dynamisk cachenyckel. Detta är användbart när projektet har filer som unikt identifierar vad som cachelagras. Till exempel refereras filer som package-lock.json
, yarn.lock
, Gemfile.lock
eller Pipfile.lock
ofta i en cachenyckel eftersom de alla representerar en unik uppsättning beroenden.
Relativa filsökvägar eller filmönster avgörs mot $(System.DefaultWorkingDirectory)
.
Exempel:
Här är ett exempel som visar hur du cachelagrar beroenden som installerats av 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
I det här exemplet innehåller cachenyckeln tre delar: en statisk sträng ("yarn"), operativsystemet som jobbet körs på eftersom cacheminnet är unikt per operativsystem och hashen för den yarn.lock
fil som unikt identifierar uppsättningen beroenden i cacheminnet.
Vid den första körningen efter att aktiviteten har lagts till rapporterar cachesteget en "cache miss" eftersom det cacheminne som identifieras av denna nyckel inte existerar. Efter det sista steget skapas en cache från filerna i $(Pipeline.Workspace)/s/.yarn
och laddas upp. Vid nästa körning rapporterar cachesteget en "cacheträff" och innehållet i cachen laddas ned och återställs.
När du använder checkout: self
checkas lagringsplatsen ut till $(Pipeline.Workspace)/s
och din .yarn
-mapp finns vanligtvis i lagringsplatsen.
Anteckning
Pipeline.Workspace
är den lokala sökvägen på agenten som kör din pipeline där alla kataloger skapas. Den här variabeln har samma värde som Agent.BuildDirectory
.
Se till att uppdatera variabeln YARN_CACHE_FOLDER
om du använder något annat än checkout: self
eftersom detta bör peka på lagringsplatsen där .yarn
finns.
Återställa nycklar
restoreKeys
kan användas om man vill köra frågor mot flera exakta nycklar eller nyckelprefix. Detta används för att återgå till en annan nyckel om en key
inte ger en träff. En återställningsnyckel söker efter en nyckel efter prefix och ger därför den senaste skapade cacheposten. Detta är användbart om pipelinen inte kan hitta en exakt matchning men vill använda en partiell cacheträff i stället. Om du vill infoga flera återställningsnycklar avgränsar du dem med hjälp av en ny rad för att ange återställningsnyckeln (se exemplet för mer information). Ordningen som återställningsnycklarna ska provas mot kommer att vara uppifrån och ned.
Nödvändig programvara på en lokalt installerad agent
Arkivera programvara/plattform | Windows | Linux | Mac |
---|---|---|---|
GNU Tar | Krävs | Krävs | Nej |
BSD Tar | Nej | Nej | Krävs |
7-Zip | Rekommenderad | Nej | Nej |
Ovanstående körbara filer måste finnas i en mapp som anges i PATH-miljövariabeln. Tänk på att de värdbaserade agenterna kommer med den programvara som ingår, detta gäller endast för lokalt installerade agenter.
Exempel:
Här är ett exempel på hur du använder återställningsnycklar av 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
I det här exemplet försöker cacheuppgiften ta reda på om nyckeln finns i cacheminnet. Om nyckeln inte finns i cacheminnet försöker den använda den första återställningsnyckeln yarn | $(Agent.OS)
.
Detta försöker söka efter alla nycklar som antingen exakt matchar den nyckeln eller har den nyckeln som ett prefix. En prefixträff kan inträffa om det fanns ett annat yarn.lock
hash-segment.
Om följande nyckel yarn | $(Agent.OS) | old-yarn.lock
till exempel fanns i cachen där old-yarn.lock
gav en annan hash än yarn.lock
, skulle återställningsnyckeln ge en partiell träff.
Om det finns en miss på den första återställningsnyckeln använder den sedan nästa återställningsnyckel yarn
som försöker hitta alla nycklar som börjar med yarn
. För prefixträffar ger resultatet den senast skapade cachenyckeln som resultat.
Not
En pipeline kan ha en eller flera cachelagringsuppgifter. Det finns ingen gräns för lagringskapaciteten för cachelagring, och jobb och uppgifter från samma pipeline kan komma åt och dela samma cache.
Cacheisolering och säkerhet
För att säkerställa isolering mellan cacheminnen från olika pipelines och olika grenar tillhör varje cache en logisk container som kallas för ett omfång. Scopes ger en säkerhetsgräns som säkerställer:
- Ett jobb från en pipeline kan inte komma åt cacheminnena från en annan pipeline och
- Ett jobb som skapar en PR har läsåtkomst till cacheminnena för PR:s målgren (för samma pipeline), men kan inte skriva (skapa) cacheminnen i målgrenens omfång.
När ett cachesteg påträffas under en körning begärs den av nyckeln identifierade cachen från servern. Servern letar sedan efter en cache med den här nyckeln från de omfång som är synliga för jobbet och returnerar cacheminnet (om tillgängligt). När cachen sparas (i slutet av jobbet) skrivs den till det område som representerar pipelinen och grenen. Mer information finns nedan.
CI, manuella och schemalagda körningar
Omfattning | Läsa | Skriva |
---|---|---|
Källgren | Ja | Ja |
main gren |
Ja | Nej |
master gren |
Ja | Nej |
Pull-begäranden genomförs
Omfattning | Läsa | Skriva |
---|---|---|
Källkodsförgrening | Ja | Nej |
Målfilial | Ja | Nej |
Mellanliggande gren (till exempel refs/pull/1/merge ) |
Ja | Ja |
main gren |
Ja | Nej |
master avdelning |
Ja | Nej |
Körningar av förgrenade pull-begäranden
Gren | Läsa | Skriva |
---|---|---|
Målgenerering | Ja | Nej |
Mellanliggande gren (till exempel refs/pull/1/merge ) |
Ja | Ja |
main gren |
Ja | Nej |
master gren |
Ja | Nej |
Tips
Eftersom cacheminnen redan är begränsade till ett projekt, en pipeline och en gren behöver du inte inkludera några projekt-, pipeline- eller grenidentifierare i cachenyckeln.
Förberedelse för cacheåterställning
I vissa scenarier bör en lyckad återställning av cachen leda till att en annan uppsättning steg körs. Om cacheminnet har återställts kan ett steg som installerar beroenden till exempel hoppas över. Detta är möjligt med hjälp av cacheHitVar
uppgiftsindata. Om du anger den här indatan till namnet på en miljövariabel blir variabeln inställd på true
när det finns en cacheträff, inexact
på en återställningsnyckelcacheträff, annars är den inställd på false
. Den här variabeln kan sedan refereras i ett stegvillkor eller inifrån ett skript.
I följande exempel hoppas steget install-deps.sh
över när cacheminnet återställs.
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
Bundler
För Ruby-projekt som använder Bundler åsidosätter du BUNDLE_PATH
miljövariabeln som används av Bundler för att ange den sökvägen Bundler söker efter Gems i.
Exempel:
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
Ccache (C/C++)
Ccache är en kompilatorcache för C/C++. Om du vill använda Ccache i pipelinen kontrollerar du att Ccache
har installerats och eventuellt läggs till i din PATH
(se Ccache-körningslägen). Ange miljövariabeln CCACHE_DIR
till en sökväg under $(Pipeline.Workspace)
och cachelagra denna katalog.
Exempel:
variables:
CCACHE_DIR: $(Pipeline.Workspace)/ccache
steps:
- bash: |
sudo apt-get install ccache -y
echo "##vso[task.prependpath]/usr/lib/ccache"
displayName: Install ccache and update PATH to use linked versions of gcc, cc, etc
- task: Cache@2
displayName: Ccache caching
inputs:
key: 'ccache | "$(Agent.OS)" | $(Build.SourceVersion)'
path: $(CCACHE_DIR)
restoreKeys: |
ccache | "$(Agent.OS)"
Mer information finns i Konfigurationsinställningar för Ccache.
Docker-avbildningar
Cachelagring av Docker-avbildningar minskar avsevärt den tid det tar att köra pipelinen.
variables:
repository: 'myDockerImage'
dockerfilePath: '$(Build.SourcesDirectory)/app/Dockerfile'
tag: '$(Build.BuildId)'
pool:
vmImage: 'ubuntu-latest'
steps:
- task: Cache@2
displayName: Cache task
inputs:
key: 'docker | "$(Agent.OS)" | cache'
path: $(Pipeline.Workspace)/docker
cacheHitVar: CACHE_RESTORED #Variable to set to 'true' when the cache is restored
- script: |
docker load -i $(Pipeline.Workspace)/docker/cache.tar
displayName: Docker restore
condition: and(not(canceled()), eq(variables.CACHE_RESTORED, 'true'))
- task: Docker@2
displayName: 'Build Docker'
inputs:
command: 'build'
repository: '$(repository)'
dockerfile: '$(dockerfilePath)'
tags: |
'$(tag)'
- script: |
mkdir -p $(Pipeline.Workspace)/docker
docker save -o $(Pipeline.Workspace)/docker/cache.tar $(repository):$(tag)
displayName: Docker save
condition: and(not(canceled()), not(failed()), ne(variables.CACHE_RESTORED, 'true'))
- nyckel: (krävs) – en unik identifierare för cachen.
- sökväg: (krävs) – sökvägen till den mapp eller fil som du vill cachelagras.
Golang
För Golang-projekt kan du ange vilka paket som ska laddas ned i filen go.mod. Om din GOCACHE
variabel inte redan har angetts anger du den till den där du vill att cachen ska laddas ned.
Exempel:
variables:
GO_CACHE_DIR: $(Pipeline.Workspace)/.cache/go-build/
steps:
- task: Cache@2
inputs:
key: 'go | "$(Agent.OS)" | go.mod'
restoreKeys: |
go | "$(Agent.OS)"
path: $(GO_CACHE_DIR)
displayName: Cache GO packages
Gradle
Att använda Gradles inbyggda cachestöd kan ha en betydande inverkan på byggtiden. Om du vill aktivera byggcachen anger du miljövariabeln GRADLE_USER_HOME
till en sökväg under $(Pipeline.Workspace)
och kör antingen bygget med --build-cache
eller lägger till org.gradle.caching=true
i gradle.properties
-filen.
Exempel:
variables:
GRADLE_USER_HOME: $(Pipeline.Workspace)/.gradle
steps:
- task: Cache@2
inputs:
key: 'gradle | "$(Agent.OS)" | **/build.gradle.kts' # Swap build.gradle.kts for build.gradle when using Groovy
restoreKeys: |
gradle | "$(Agent.OS)"
gradle
path: $(GRADLE_USER_HOME)
displayName: Configure gradle caching
- task: Gradle@2
inputs:
gradleWrapperFile: 'gradlew'
tasks: 'build'
options: '--build-cache'
displayName: Build
- script: |
# stop the Gradle daemon to ensure no files are left open (impacting the save cache operation later)
./gradlew --stop
displayName: Gradlew stop
- restoreKeys: Återställningsnycklarna om den primära nyckeln misslyckas (valfritt)
Obs
Cacheminnen är oföränderliga när en cache med en viss nyckel har skapats för ett specifikt omfång (gren) och cacheminnet inte kan uppdateras. Det innebär att om nyckeln är ett fast värde kommer alla efterföljande versioner för samma gren inte att kunna uppdatera cacheminnet även om cachens innehåll har ändrats. Om du vill använda ett fast nyckelvärde måste du använda argumentet restoreKeys
som reserv.
Maven
Maven har en lokal lagringsplats där den lagrar nedladdningar och skapade artefakter. Om du vill aktivera, ange alternativet maven.repo.local
till en sökväg under $(Pipeline.Workspace)
och cachelagra den här mappen.
Exempel:
variables:
MAVEN_CACHE_FOLDER: $(Pipeline.Workspace)/.m2/repository
MAVEN_OPTS: '-Dmaven.repo.local=$(MAVEN_CACHE_FOLDER)'
steps:
- task: Cache@2
inputs:
key: 'maven | "$(Agent.OS)" | **/pom.xml'
restoreKeys: |
maven | "$(Agent.OS)"
maven
path: $(MAVEN_CACHE_FOLDER)
displayName: Cache Maven local repo
- script: mvn install -B -e
Om du använder en Maven-aktivitetska du även skicka variabeln MAVEN_OPTS
eftersom den skrivs över annars:
- task: Maven@4
inputs:
mavenPomFile: 'pom.xml'
mavenOptions: '-Xmx3072m $(MAVEN_OPTS)'
.NET/NuGet
Om du använder PackageReferences
för att hantera NuGet-beroenden direkt i projektfilen och har en packages.lock.json
fil kan du aktivera cachelagring genom att ange NUGET_PACKAGES
miljövariabeln till en sökväg under $(UserProfile)
och cachelagra den här katalogen. Mer information om hur du låser beroenden finns i Paketreferens i projektfiler.
Om du vill använda flera packages.lock.jsonkan du fortfarande använda följande exempel utan att göra några ändringar. Innehållet i alla packages.lock.json filer hashas och om en av filerna ändras genereras en ny cachenyckel.
Exempel:
variables:
NUGET_PACKAGES: $(Pipeline.Workspace)/.nuget/packages
steps:
- task: Cache@2
inputs:
key: 'nuget | "$(Agent.OS)" | $(Build.SourcesDirectory)/**/packages.lock.json'
restoreKeys: |
nuget | "$(Agent.OS)"
nuget
path: $(NUGET_PACKAGES)
displayName: Cache NuGet packages
Den här metoden är också giltig för .NET Core-projekt om projektet använder packages.lock.json för att låsa paketversioner. Du kan aktivera detta genom att ställa in RestorePackagesWithLockFile
till True
i din Csproj--fil eller med hjälp av följande kommando: dotnet restore --use-lock-file
.
Node.js/npm
Det finns olika sätt att aktivera cachelagring i ett Node.js projekt, men det rekommenderade sättet är att cachelagra npm:s delade cachekatalogen. Den här katalogen hanteras av npm och innehåller en cachelagrad version av alla nedladdade moduler. Under installationen kontrollerar npm den här katalogen först (som standard) efter moduler som kan minska eller eliminera nätverksanrop till det offentliga npm-registret eller till ett privat register.
Eftersom standardsökvägen till npm:s delade cachekatalog är inte samma på alla plattformarrekommenderar vi att du åsidosätter miljövariabeln npm_config_cache
till en sökväg under $(Pipeline.Workspace)
. Detta säkerställer också att cachen är tillgänglig från container- och icke-containerjobb.
Exempel:
variables:
npm_config_cache: $(Pipeline.Workspace)/.npm
steps:
- task: Cache@2
inputs:
key: 'npm | "$(Agent.OS)" | package-lock.json'
restoreKeys: |
npm | "$(Agent.OS)"
path: $(npm_config_cache)
displayName: Cache npm
- script: npm ci
Om projektet inte har någon package-lock.json
-fil, refererar du till den package.json
-filen i cache-nyckelns indata istället.
Tips
Eftersom npm ci
tar bort mappen node_modules
för att säkerställa att en konsekvent, repeterbar uppsättning moduler används bör du undvika cachelagring node_modules
när du anropar npm ci
.
Node.js/Yarn
Precis som med npm finns det olika sätt att cachelagrat paket som installerats med Yarn. Det rekommenderade sättet är att cachelagra Yarns delade cachemapp . Den här katalogen hanteras av Yarn och innehåller en cachelagrad version av alla nedladdade paket. Under installationen kontrollerar Yarn den här katalogen först (som standard) för moduler, vilket kan minska eller eliminera nätverksanrop till offentliga eller privata register.
Exempel:
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
Python/Anaconda
Konfigurera cachelagring för din pipeline med Anaconda-miljöer:
Exempel
variables:
CONDA_CACHE_DIR: /usr/share/miniconda/envs
# Add conda to system path
steps:
- script: echo "##vso[task.prependpath]$CONDA/bin"
displayName: Add conda to PATH
- bash: |
sudo chown -R $(whoami):$(id -ng) $(CONDA_CACHE_DIR)
displayName: Fix CONDA_CACHE_DIR directory permissions
- task: Cache@2
displayName: Use cached Anaconda environment
inputs:
key: 'conda | "$(Agent.OS)" | environment.yml'
restoreKeys: |
python | "$(Agent.OS)"
python
path: $(CONDA_CACHE_DIR)
cacheHitVar: CONDA_CACHE_RESTORED
- script: conda env create --quiet --file environment.yml
displayName: Create Anaconda environment
condition: eq(variables.CONDA_CACHE_RESTORED, 'false')
Windows
- task: Cache@2 displayName: Cache Anaconda inputs: key: 'conda | "$(Agent.OS)" | environment.yml' restoreKeys: | python | "$(Agent.OS)" python path: $(CONDA)/envs cacheHitVar: CONDA_CACHE_RESTORED - script: conda env create --quiet --file environment.yml displayName: Create environment condition: eq(variables.CONDA_CACHE_RESTORED, 'false')
PHP/Composer
För PHP-projekt som använder Composer åsidosätter du miljövariabeln COMPOSER_CACHE_DIR
som används av Composer.
Exempel:
variables:
COMPOSER_CACHE_DIR: $(Pipeline.Workspace)/.composer
steps:
- task: Cache@2
inputs:
key: 'composer | "$(Agent.OS)" | composer.lock'
restoreKeys: |
composer | "$(Agent.OS)"
composer
path: $(COMPOSER_CACHE_DIR)
displayName: Cache composer
- script: composer install
Kända problem och feedback
Om du har problem med att konfigurera cachelagring för din pipeline, kontrollera listan över öppna ärenden i microsoft/azure-pipelines-tasks förrådet. Om du inte ser ditt problem i listan skapa en ny och ange nödvändig information om ditt scenario.
Q&A
F: Kan jag rensa en cache?
S: Det finns för närvarande inte stöd för att rensa en cache. Du kan dock lägga till en strängliteral (till exempel version2
) i din befintliga cachenyckel för att ändra nyckeln på ett sätt som undviker träffar på befintliga cacheminnen. Ändra till exempel följande cachenyckel från detta:
key: 'yarn | "$(Agent.OS)" | yarn.lock'
Så här gör du:
key: 'version2 | yarn | "$(Agent.OS)" | yarn.lock'
F: När upphör en cache att gälla?
Cacher går ut efter sju dagar utan aktivitet.
F: När laddas cachen upp?
S: Efter det sista steget i pipelinen skapas en cache från din cache path
och laddas upp. Mer information finns i exempel.
F: Finns det en gräns för storleken på en cache?
S: Det finns ingen framtvingad gräns för storleken på enskilda cacheminnen eller den totala storleken på alla cacheminnen i en organisation.