パイプライン キャッシュ
Azure DevOps Services
パイプライン キャッシュを使用すると、1 回の実行の出力またはダウンロードした依存関係を後の実行で再利用できるため、ビルド時間を短縮できます。これにより、同じファイルを再作成または再ダウンロードするコストを削減、またはなくすことができます。 キャッシュは、各実行の開始時に同じ依存関係が何度もダウンロードされるシナリオで特に便利です。 これは、多くの場合、数百または数千のネットワーク呼び出しが伴う時間のかかるプロセスです。
キャッシュは、キャッシュを復元して保存する方が、出力を最初から再生成するよりも早い場合に、ビルド時間を向上する上で効果的です。 このため、キャッシュはすべてのシナリオで有効ではなく、実際にはビルド時間に悪影響を及ぼす可能性があります。
Note
パイプライン キャッシュは、YAML パイプラインとクラシック パイプラインの両方のエージェント プール ジョブでサポートされています。 ただし、クラシック リリースのパイプラインではサポートされていません。
成果物を使用する場合とキャッシュを使用する場合
パイプライン キャッシュとパイプライン成果物は、同様の関数を実行しますが、異なるシナリオ向けに設計されているため、区別して使用してください。
1 つのジョブで生成された特定のファイルを他のジョブと共有する必要がある場合は、パイプライン成果物を使用します (これらのファイルがないと他のジョブが失敗する可能性があります)。
以前の実行のファイルを再利用してビルド時間を短縮する場合は、パイプライン キャッシュを使用します (これらのファイルがなくても、ジョブの実行機能には影響しない) 。
注意
パイプライン キャッシュとパイプライン成果物は、すべての階層 (無料および有料) において無料です。 詳細については、「成果物のストレージ使用量」を参照してください。
キャッシュ タスク: しくみ
キャッシュは、キャッシュ タスクを使用してパイプラインに追加されます。 このタスクは他のタスクと同様に機能し、ジョブの steps
セクションに追加されます。
実行中にキャッシュ ステップが検出されると、タスクは指定された入力に基づいてキャッシュを復元します。 キャッシュが見つからない場合は、ステップが完了し、ジョブの次のステップが実行されます。
ジョブ内のすべてのステップが実行され、ジョブの状態が成功であると仮定すると、スキップされなかった "キャッシュの復元" ステップごとに、特別な "ジョブ後: キャッシュ" ステップが自動的に追加され、トリガーされます。 このステップでは、キャッシュを保存します。
注意
キャッシュは変更不可です。つまり、いったん作成されたキャッシュの内容は変更することはできません。
キャッシュ タスクを構成する
キャッシュ タスクには、key と path の 2 つの必須引数があります。
- path: キャッシュするフォルダーのパス。 絶対パスか相対パスにすることができます。 相対パスは
$(System.DefaultWorkingDirectory)
に対して解決されます。
注意
定義済みの変数を使用して、キャッシュするフォルダーへのパスを格納できますが、ワイルドカードはサポートされていません。
- key: 復元または保存するキャッシュの識別子に設定する必要があります。 キーは、文字列値、ファイル パス、またはファイル パターンの組み合わせで構成され、各セグメントは
|
文字で区切られます。
文字列:
固定値 (キャッシュ名やツール名など) または環境変数から取得された値 (現在の OS や現在のジョブ名など)ファイル パス:
コンテンツがハッシュ化される特定のファイルへのパス。 このファイルは、タスクの実行時に存在する必要があります。 "ファイル パスのように見える" キー セグメントは、どれもファイル パスのように扱われることに注意してください。 特に、.
を含むセグメントがこれに該当します。 これにより、この "ファイル" が存在しない場合にタスクが失敗する可能性があります。ヒント
パスに似た文字列セグメントがファイル パスのように扱われないようにするには、二重引用符で囲みます。例:
"my.key" | $(Agent.OS) | key.file
ファイル パターン:
glob スタイルのワイルドカード パターンのコンマ区切りの一覧。少なくとも 1 つのファイルと一致する必要があります。 例:**/yarn.lock
: ソース ディレクトリのすべての yarn.lock ファイル*/asset.json, !bin/**
: bin ディレクトリ下を除く、ソース ディレクトリ下のディレクトリにあるすべての asset.json ファイル
ファイル パスまたはファイル パターンによって識別されるファイルの内容は、動的キャッシュ キーを生成するためにハッシュ化されます。 これは、キャッシュされているものを一意に識別するファイルがプロジェクトに含まれている場合に便利です。 たとえば、package-lock.json
、yarn.lock
、Gemfile.lock
、Pipfile.lock
などのファイルはすべて一意の依存関係のセットを表しているため、一般的にキャッシュ キーで参照されます。
相対ファイル パスまたはファイル パターンは、$(System.DefaultWorkingDirectory)
に対して解決されます。
例:
次に、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
この例では、キャッシュ キーには、静的文字列 ("yarn")、ジョブが実行されている OS (このキャッシュはオペレーティング システムごとに一意であるため)、およびキャッシュ内の依存関係のセットを一意に識別する yarn.lock
ファイルのハッシュの 3 つの部分が含まれています。
タスク追加後の最初の実行では、このキーで識別されたキャッシュが存在しないため、キャッシュ ステップで "キャッシュ ミス" が報告されます。 最後のステップの後に、$(Pipeline.Workspace)/s/.yarn
内のファイルからキャッシュが作成され、アップロードされます。 次回の実行では、キャッシュ ステップで "キャッシュ ヒット" が報告され、キャッシュの内容がダウンロードされて復元されます。
checkout: self
を使用すると、リポジトリは$(Pipeline.Workspace)/s
にチェックアウトされ、.yarn
フォルダは通常リポジトリ自体に存在します。
Note
Pipeline.Workspace
は、すべてのディレクトリが作成されるパイプラインを実行しているエージェントのローカル パスです。 この変数の値は Agent.BuildDirectory
と同じです。
YARN_CACHE_FOLDER
以外を使用する場合は、変数checkout: self
を更新するようにしてください。これは.yarn
が存在するリポジトリを指すはずからです。
キーを復元する
restoreKeys
は、複数の正確なキーまたはキー プレフィックスに対してクエリを実行する場合に使用できます。 これは、key
がヒットしない場合に、別のキーにフォールバックするために使用されます。 復元キーは、プレフィックスによるキーを検索し、結果として最後に作成されたキャッシュ エントリを生成します。 これは、パイプラインで完全一致を見つけられず、代わりに部分的なキャッシュ ヒットを使用する場合に便利です。 複数の復元キーを挿入するには、復元キーを示す新しい行を使用してキーを区切ります (詳細については、例を参照してください)。 復元キーが上から下に順番に試行されます。
セルフホステッド エージェントで必要なソフトウェア
アーカイブ ソフトウェア/プラットフォーム | Windows | Linux | Mac |
---|---|---|---|
GNU Tar | 必須 | 必須 | いいえ |
BSD Tar | いいえ | いいえ | 必須 |
7-Zip | 推奨 | いいえ | いいえ |
上記の実行可能ファイルは、PATH 環境変数に一覧表示されているフォルダーに存在する必要があります。 ホステッド エージェントにはソフトウェアが付属しています。これはセルフホステッド エージェントにのみ適用されます。
例:
次に、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
この例では、キャッシュ タスクで、キーがキャッシュ内に存在するかどうかを確認します。 キーがキャッシュに存在しない場合は、最初の復元キー yarn | $(Agent.OS)
を使用しようとします。
これは、そのキーと完全に一致するか、そのキーをプレフィックスとして持つすべてのキーの検索を試みます。 プレフィックス ヒットは、別の yarn.lock
ハッシュ セグメントがあった場合に発生する可能性があります。
たとえば、次のキー yarn | $(Agent.OS) | old-yarn.lock
がキャッシュ内に存在し、old-yarn.lock
が yarn.lock
とは異なるハッシュを生成した場合、復元キーは部分的なヒットを生成します。
最初の復元キーにミスがあった場合は、次の復元キー yarn
が使用され、yarn
で始まるキーが検索されます。 プレフィックス ヒットの場合、結果は直近に作成されたキャッシュ キーを結果として生成します。
Note
パイプラインには、1 つ以上のキャッシュ タスクが含まれることがあります。 キャッシュ ストレージ容量に制限はなく、同じパイプラインのジョブとタスクは同じキャッシュにアクセスして共有できます。
キャッシュの分離とセキュリティ
異なるパイプラインと異なるブランチのキャッシュを確実に分離するため、すべてのキャッシュはスコープと呼ばれる論理コンテナーに属します。 スコープは、あるパイプラインのジョブが別のパイプラインのキャッシュにアクセスできないことを保証するセキュリティ境界を提供します。PR を構築するジョブは PR のターゲット ブランチ (同じパイプラインの場合) のキャッシュへの読み取りアクセス権を持ちますが、ターゲット ブランチのスコープにキャッシュを書き込む (作成する) ことはできません。
実行中にキャッシュ ステップが検出されると、キーによって識別されるキャッシュがサーバーから要求されます。 次に、サーバーはジョブに表示されるスコープからこのキーを持つキャッシュを検索し、キャッシュを返します (存在する場合)。 キャッシュの保存時 (ジョブの最後) には、パイプラインとブランチを表すスコープにキャッシュが書き込まれます。 詳細については、以下を参照してください。
CI、手動、スケジュールされた実行
Scope | Read | Write |
---|---|---|
ソース ブランチ | はい | はい |
main ブランチ |
はい | いいえ |
master ブランチ |
はい | いいえ |
Pull request の実行
Scope | Read | Write |
---|---|---|
ソース ブランチ | はい | いいえ |
ターゲット ブランチ | はい | いいえ |
中間ブランチ (refs/pull/1/merge など) |
はい | はい |
main ブランチ |
はい | いいえ |
master ブランチ |
はい | いいえ |
Pull request fork の実行
ブランチ | Read | Write |
---|---|---|
ターゲット ブランチ | はい | いいえ |
中間ブランチ (refs/pull/1/merge など) |
はい | はい |
main ブランチ |
はい | いいえ |
master ブランチ |
はい | いいえ |
ヒント
キャッシュのスコープは既にプロジェクト、パイプライン、ブランチであるため、プロジェクト、パイプライン、またはブランチの識別子をキャッシュ キーに含める必要はありません。
-キャッシュ復元の条件付け
一部のシナリオでは、キャッシュを正常に復元すると、別のステップの実行が必要となることがあります。 たとえば、キャッシュが復元されると、依存関係をインストールするステップはスキップされることがあります。 これは、cacheHitVar
タスク入力を使用することによって可能です。 この入力を環境変数の名前に設定すると、変数は、キャッシュ ヒットがある場合、true
に設定され、復元キー キャッシュ ヒット上の inexact
に設定され、それ以外の場合は、false
に設定されます。 この変数は、ステップ条件またはスクリプト内から参照できます。
次の例では、キャッシュの復元時に install-deps.sh
ステップがスキップされます。
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
Bundler を使用する Ruby プロジェクトの場合は、Bundler が使用する BUNDLE_PATH
環境変数を上書きして、Bundler が Gems を検索するパスを設定します。
例:
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 は、C/C++ 用のコンパイラ キャッシュです。 パイプラインで Ccache を使用するには、Ccache
がインストールされ、必要に応じて PATH
に追加されていることを確認します (Ccache の実行モードに関するページを参照してください)。 CCACHE_DIR
環境変数を $(Pipeline.Workspace)
のパスに設定し、このディレクトリをキャッシュします。
例:
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)"
詳細については、Ccache 構成設定に関するページを参照してください。
Docker イメージ
Docker イメージをキャッシュすると、パイプラインの実行にかかる時間が大幅に短縮されます。
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'))
- key: (必須) キャッシュの一意の識別子。
- path: (必須) キャッシュするフォルダーまたはファイルのパス。
Golang
Golang プロジェクトの場合は、go.mod ファイルにダウンロードするパッケージを指定できます。 GOCACHE
変数がまだ設定されていない場合は、キャッシュをダウンロードする場所に設定します。
例:
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
Gradle の 組み込みキャッシュ サポートを使用すると、ビルド時間に大きな影響を与える可能性があります。 ビルド キャッシュを有効にするには、GRADLE_USER_HOME
下のパスに $(Pipeline.Workspace)
環境変数を設定し、--build-cache
でビルドを実行するか、org.gradle.caching=true
ファイルに gradle.properties
を追加します 。
例:
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: 主キーが失敗した場合のフォールバック キー (省略可能)
注意
キャッシュは変更不可であるため、所定のスコープ (ブランチ) に対して特定のキーを持つキャッシュが作成されると、キャッシュを更新できなくなります。 つまり、キーが固定値の場合、同じブランチの後続のビルドでは、キャッシュの内容が変更された場合でもキャッシュを更新できないということです。 固定キー値を使用する場合は、フォールバック オプションとして restoreKeys
引数を使用する必要があります。
Maven
Maven には、ダウンロードとビルド成果物を格納するローカル リポジトリがあります。 有効にするには、maven.repo.local
オプションを $(Pipeline.Workspace)
の下 のパスに設定し、このフォルダーをキャッシュします。
例:
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
Maven タスクを使用している場合は、変数が上書きされるため、必ず変数を渡MAVEN_OPTS
してください。
- task: Maven@4
inputs:
mavenPomFile: 'pom.xml'
mavenOptions: '-Xmx3072m $(MAVEN_OPTS)'
.NET/NuGet
PackageReferences
を使用してプロジェクト ファイル内で NuGet の依存関係を直接管理し、packages.lock.json
ファイルがある場合は、NUGET_PACKAGES
環境変数を $(UserProfile)
の下のパスに設定し、このディレクトリをキャッシュすることでキャッシュを有効にすることができます。 依存関係をロックする方法の詳細については、プロジェクト ファイルのパッケージ リファレンスに関するページを参照 してください。
複数の packages.lock.json を使用する場合でも、変更を加えずに次の例を使用できます。 packages.lock.json ファイルすべての内容がハッシュされ、ファイルの 1 つが変更されると、新しいキャッシュ キーが生成されます。
例:
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
Node.js/npm
Node.js プロジェクトでキャッシュを有効にする方法はさまざまですが、npm の共有キャッシュ ディレクトリをキャッシュする方法をお勧めします。 このディレクトリは npm によって管理され、ダウンロードされたすべてのモジュールのキャッシュ バージョンが含まれています。 npm では、インストール時にこのディレクトリを最初にチェックし (既定の動作)、パブリック npm レジストリまたはプライベート レジストリへのネットワーク呼び出しを削減またはなくすことができるモジュールを探します。
npm の共有キャッシュ ディレクトリへの既定のパスはすべてのプラットフォームで同じではないので、npm_config_cache
環境変数を $(Pipeline.Workspace)
の下のパスにオーバーライドすることをお勧めします。 これにより、コンテナー ジョブと非コンテナー ジョブからキャッシュにアクセス可能になります。
例:
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
プロジェクトに package-lock.json
ファイルがない場合は 、代わりにキャッシュ キー入力の package.json
ファイルを参照します。
ヒント
npm ci
によって node_modules
フォルダーが削除され、一貫性のある反復可能なモジュール セットを確保するため、node_modules
を呼び出すときは npm ci
のキャッシュを避ける必要があります。
Node.js/Yarn
npm と同様に、Yarn でインストールされたパッケージをキャッシュするにはさまざまな方法があります。 Yarn の共有キャッシュ フォルダーをキャッシュする方法をお勧めします。 このディレクトリは Yarn によって管理され、ダウンロードされたすべてのパッケージのキャッシュ バージョンが含まれています。 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
Python/Anaconda
Anaconda 環境を使用してパイプライン キャッシュを設定します。
例
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
Composer を使用する PHP プロジェクトの場合は、Composer が使用する COMPOSER_CACHE_DIR
環境変数をオーバーライドします。
例:
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
既知の問題とフィードバック
パイプラインのキャッシュの設定で問題が発生している場合は、 リポジトリで未解決の問題microsoft/azure-pipelines-tasksの一覧を確認します。 問題が一覧にない場合は、新しい問題を作成し、シナリオに関する必要な情報を提供します。
Q&A
Q: キャッシュをクリアできますか?
A: キャッシュのクリアは現在サポートされていません。 ただし、既存のキャッシュ キーに文字列リテラル (version2
など) を追加して、既存のキャッシュへのヒットを回避するようキーを変更できます。 たとえば、次のようなキャッシュ キーの場合:
key: 'yarn | "$(Agent.OS)" | yarn.lock'
結果として、次を実現します。
key: 'version2 | yarn | "$(Agent.OS)" | yarn.lock'
Q: キャッシュの有効期限はいつまでですか?
A: 何も行わずに 7 日が経過すると、キャッシュは期限切れになります。
Q: キャッシュはいつアップロードされますか?
A: パイプラインの最後のステップの後、キャッシュ path
からキャッシュが作成され、アップロードされます。 詳細については、例を参照してください。
Q: キャッシュのサイズに制限はありますか?
A: 個々のキャッシュのサイズや、組織内のすべてのキャッシュの合計サイズに制限はありません。