パイプライン キャッシュ
Azure DevOps Services
パイプライン キャッシュを使用すると、1 回の実行から出力またはダウンロードした依存関係を後の実行で再利用できるため、ビルド時間を短縮できます。これにより、同じファイルを再作成または再ダウンロードするコストを削減または回避できます。 キャッシュは、各実行の開始時に同じ依存関係が何度もダウンロードされるシナリオで特に便利です。 これは、多くの場合、数百または数千のネットワーク呼び出しを伴う時間のかかるプロセスです。
キャッシュは、キャッシュを復元して保存する時間が、最初から出力を生成する時間よりも短い場合に、ビルド時間の向上に効果的です。 このため、キャッシュはすべてのシナリオで有効であるとは限らず、実際にはビルド時間に悪影響を及ぼす可能性があります。
手記
パイプライン キャッシュは、クラシック リリース パイプラインではサポートされていません。
アーティファクトを利用する場合とキャッシュを利用する場合の使い分け
パイプラインのキャッシュと パイプライン成果物 は、同様の機能を持ちますが、異なるシナリオに対応するように設計されており、互いに置き換えて使用すべきではありません。
1 つのジョブで生成された特定のファイルを取得し、それを他のジョブと共有する必要がある場合には、パイプライン成果物 を使用します。これらの他のジョブはそれがないとおそらく失敗します。
以前の実行のファイルを再利用してビルド時間を短縮する必要がある場合は、パイプライン キャッシュ を使用します (これらのファイルがない場合は、ジョブの実行能力に影響しません)。
手記
パイプライン キャッシュとパイプライン成果物は、すべてのプラン (無料および有料) で無料で利用できます。 詳細については、「アーティファクトのストレージ使用量」を参照してください。
キャッシュ タスク: しくみ
キャッシュは、キャッシュ タスクを使用してパイプラインに追加されます。 このタスクは他のタスクと同様に機能し、ジョブの steps
セクションに追加されます。
実行中にキャッシュ ステップが発生すると、タスクは指定された入力に基づいてキャッシュを復元します。 キャッシュが見つからない場合は、ステップが完了し、ジョブの次のステップが実行されます。
ジョブ内のすべてのステップが実行され、ジョブの状態が成功であると仮定すると、スキップされなかった "キャッシュの復元" ステップごとに、特別な "ジョブ後: キャッシュ" ステップが自動的に追加され、トリガーされます。 この手順はキャッシュを保存する
手記
キャッシュは不変です。つまり、キャッシュが作成されると、その内容は変更できません。
キャッシュ タスクを構成する
キャッシュ タスク には、キー と パスという 2 つの必須引数があります。
- パス: キャッシュするフォルダーのパス。 絶対パスまたは相対パスを指定できます。 相対パスは、
$(System.DefaultWorkingDirectory)
に対して解決されます。
- キー: 復元または保存するキャッシュの識別子に設定する必要があります。 キーは、文字列値、ファイル パス、またはファイル パターンの組み合わせで構成され、各セグメントは
|
文字で区切られます。
文字列:
固定値 (キャッシュ名やツール名など) または環境変数から取得された値 (現在の OS や現在のジョブ名など)ファイル パス:
コンテンツがハッシュされる特定のファイルへのパス。 このファイルは、タスクの実行時に存在する必要があります。 "ファイル パスのように見える" キー セグメントは、ファイル パスのように扱われることに注意してください。 特に、これには、 .
を含むセグメントが含まれます。 これにより、この "ファイル" が存在しない場合にタスクが失敗する可能性があります。ヒント
パスに似た文字列セグメントがファイル パスのように扱われないようにするには、二重引用符で囲みます (例:
"my.key" | $(Agent.OS) | key.file
ファイル パターン:
少なくとも 1 つのファイルと一致する必要がある glob スタイルのワイルドカード パターンのコンマ区切りリスト。 例えば:**/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
フォルダーはリポジトリ自体に存在します。
手記
Pipeline.Workspace
は、すべてのディレクトリが作成されるパイプラインを実行しているエージェントのローカル パスです。 この変数の値は Agent.BuildDirectory
と同じです。
checkout: self
以外のものを使用する場合は、.yarn
が存在するリポジトリを指すように、変数 YARN_CACHE_FOLDER
を更新してください。
キーの復元
restoreKeys
は、複数の正確なキーまたはキー プレフィックスに対してクエリを実行する場合に使用できます。 これは、key
がヒットしない場合に別のキーにフォールバックするために使用されます。 復元キーは、プレフィックスでキーを検索し、結果として作成された最新のキャッシュ エントリを生成します。 これは、パイプラインが完全に一致するものを見つけられないが、代わりに部分キャッシュ ヒットを使用する場合に便利です。 複数の復元キーを挿入するには、復元キーを示す新しい行を使用して区切ります (詳細については、例を参照してください)。 復元キーが上から下に順番に試行されます。
セルフホステッド エージェントで必要なソフトウェア
アーカイブ ソフトウェア/プラットフォーム | ウィンドウズ | 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
で始まるキーが検索されます。 プレフィックス ヒットの場合、結果として最後に作成されたキャッシュ キーが生成されます。
手記
パイプラインには、1 つ以上のキャッシュ タスクを含めることができます。 キャッシュ ストレージの容量に制限はなく、同じパイプラインのジョブとタスクが同じキャッシュにアクセスして共有できます。
キャッシュの分離とセキュリティ
異なるパイプラインと異なるブランチからのキャッシュ間の分離を確保するために、すべてのキャッシュはスコープと呼ばれる論理コンテナーに属します。 スコープは、次のことを保証するセキュリティ境界を提供します。
- あるパイプラインのジョブが別のパイプラインのキャッシュにアクセスできない
- PR を構築するジョブは、(同じパイプラインの) PR のターゲット ブランチのキャッシュへの読み取りアクセス権を持ちますが、ターゲット ブランチのスコープ内でキャッシュを書き込む (作成) することはできません。
実行中にキャッシュ ステップが発生すると、キーによって識別されるキャッシュがサーバーから要求されます。 その後、サーバーはジョブに表示されるスコープからこのキーを持つキャッシュを検索し、キャッシュ (使用可能な場合) を返します。 キャッシュの保存時 (ジョブの最後) に、パイプラインとブランチを表すスコープにキャッシュが書き込まれます。 詳細については、以下を参照してください。
CI、手動、スケジュールされた実行
スコープ | 既読 | 書き込み |
---|---|---|
ソース ブランチ | はい | はい |
main ブランチ |
はい | いいえ |
master ブランチ |
はい | いいえ |
Pull request の実行
スコープ | 既読 | 書き込み |
---|---|---|
ソース ブランチ | はい | いいえ |
ターゲット ブランチ | はい | いいえ |
中間分岐 (refs/pull/1/merge など) |
はい | はい |
main ブランチ |
はい | いいえ |
master ブランチ |
はい | いいえ |
Pull request fork の実行
ブランチ | 既読 | 書き込み |
---|---|---|
ターゲット ブランチ | はい | いいえ |
中間分岐 (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 を使用する 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_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: (必須) キャッシュの一意の識別子。
- パス: (必須) - キャッシュするフォルダーまたはファイルのパス。
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
を使用してビルドを実行するか、gradle.properties
ファイルに org.gradle.caching=true
を追加します。
例の:
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 ファイルの内容がハッシュされ、いずれかのファイルが変更されると、新しいキャッシュ キーが生成されます。
例の:
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
この方法は、プロジェクトがパッケージバージョンをロックするために packages.lock.json を使用している場合、.NET Core プロジェクトでも有効です。 これを有効にするには、RestorePackagesWithLockFile
を Csproj ファイルに True
するように設定するか、次のコマンドを使用します dotnet restore --use-lock-file
。
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
フォルダーを削除するため、npm ci
を呼び出すときに node_modules
をキャッシュしないようにする必要があります。
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 で使用
例の:
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
既知の問題とフィードバック
パイプラインのキャッシュの設定で問題が発生している場合は、
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: 個々のキャッシュのサイズや組織内のすべてのキャッシュの合計サイズに対する制限は適用されません。