パイプライン キャッシュ

Azure DevOps Services

パイプライン キャッシュを使用すると、1 回の実行の出力またはダウンロードした依存関係を後の実行で再利用できるため、ビルド時間を短縮できます。これにより、同じファイルを再作成または再ダウンロードするコストを削減、またはなくすことができます。 キャッシュは、各実行の開始時に同じ依存関係が何度もダウンロードされるシナリオで特に便利です。 これは、多くの場合、数百または数千のネットワーク呼び出しが伴う時間のかかるプロセスです。

キャッシュは、キャッシュを復元して保存する方が、出力を最初から再生成するよりも早い場合に、ビルド時間を向上する上で効果的です。 このため、キャッシュはすべてのシナリオで有効ではなく、実際にはビルド時間に悪影響を及ぼす可能性があります。

Note

パイプライン キャッシュは、YAML パイプラインとクラシック パイプラインの両方のエージェント プール ジョブでサポートされています。 ただし、クラシック リリースのパイプラインではサポートされていません。

成果物を使用する場合とキャッシュを使用する場合

パイプライン キャッシュとパイプライン成果物は、同様の関数を実行しますが、異なるシナリオ向けに設計されているため、区別して使用してください。

  • 1 つのジョブで生成された特定のファイルを他のジョブと共有する必要がある場合は、パイプライン成果物を使用します (これらのファイルがないと他のジョブが失敗する可能性があります)。

  • 以前の実行のファイルを再利用してビルド時間を短縮する場合は、パイプライン キャッシュを使用します (これらのファイルがなくても、ジョブの実行機能には影響しない) 。

注意

パイプライン キャッシュとパイプライン成果物は、すべての階層 (無料および有料) において無料です。 詳細については、「成果物のストレージ使用量」を参照してください。

キャッシュ タスク: しくみ

キャッシュは、キャッシュ タスクを使用してパイプラインに追加されます。 このタスクは他のタスクと同様に機能し、ジョブの steps セクションに追加されます。

実行中にキャッシュ ステップが検出されると、タスクは指定された入力に基づいてキャッシュを復元します。 キャッシュが見つからない場合は、ステップが完了し、ジョブの次のステップが実行されます。

ジョブ内のすべてのステップが実行され、ジョブの状態が成功であると仮定すると、スキップされなかった "キャッシュの復元" ステップごとに、特別な "ジョブ後: キャッシュ" ステップが自動的に追加され、トリガーされます。 このステップでは、キャッシュを保存します

注意

キャッシュは変更不可です。つまり、いったん作成されたキャッシュの内容は変更することはできません。

キャッシュ タスクを構成する

キャッシュ タスクには、keypath の 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.jsonyarn.lockGemfile.lockPipfile.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.lockyarn.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: 個々のキャッシュのサイズや、組織内のすべてのキャッシュの合計サイズに制限はありません。