NuGet パッケージをキャッシュする

Azure DevOps Services

パイプラインのキャッシュを使うと、後の実行で再利用する依存関係をキャッシュすることで、ビルド時間を短縮できます。 この記事では、 キャッシュ タスク を使用して NuGet パッケージをキャッシュおよび復元する方法について説明します。

依存関係をロックする

キャッシュ タスクを設定するには、最初にプロジェクトの依存関係をロックして、package.lock.json ファイルを作成する必要があります。 このファイルの内容のハッシュを使用して、キャッシュの一意のキーを生成します。

プロジェクトの依存関係をロックするには、csproj ファイルで RestorePackagesWithLockFile プロパティを true に設定します。 NuGet の復元では、プロジェクトのルート ディレクトリにロック ファイル packages.lock.json が生成されます。 必ず packages.lock.json ファイルをソース コードにチェックインしてください。

<PropertyGroup>
  <RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
</PropertyGroup>

NuGet パッケージをキャッシュする

パイプラインを実行しているエージェント上のパッケージの場所を指すパイプライン変数を作成する必要があります。

この例では、packages.lock.json の内容がハッシュされて、動的なキャッシュ キーが生成されます。 これにより、ファイルが変更されるたびに、新しいキャッシュ キーが生成されます。

Azure Pipelines でキャッシュ キーが生成される方法を示すスクリーンショット。

variables:
  NUGET_PACKAGES: $(Pipeline.Workspace)/.nuget/packages

- task: Cache@2
  displayName: Cache
  inputs:
    key: 'nuget | "$(Agent.OS)" | **/packages.lock.json,!**/bin/**,!**/obj/**'
    restoreKeys: |
       nuget | "$(Agent.OS)"
       nuget
    path: '$(NUGET_PACKAGES)'
    cacheHitVar: 'CACHE_RESTORED'

注意

キャッシュは変更できません。キャッシュが作成されると、その内容は変更できません。

キャッシュを復元する

このタスクは、CACHE_RESTORED 変数が false の場合にのみ実行されます。

- task: NuGetCommand@2
  condition: ne(variables.CACHE_RESTORED, true)
  inputs:
    command: 'restore'
    restoreSolution: '**/*.sln'

ビルド タスク中に "project.assets.json が見つかりません" というエラー メッセージが表示された場合は、復元タスクから条件 condition: ne(variables.CACHE_RESTORED, true) を削除することで解決できます。 これにより、restore コマンドが実行され、project.assets.json ファイルが生成されます。 復元タスクでは、対応するフォルダーに既に存在するパッケージはダウンロードされません。

注意

パイプラインには 1 つ以上のキャッシュ タスクを含めることができます。また、同じパイプライン内のジョブとタスクは、同じキャッシュにアクセスして共有できます。

パフォーマンスの比較

パイプライン キャッシュは、パイプラインの実行を高速化する優れた方法です。 2 つの異なるパイプラインの並列パフォーマンス比較を次に示します。 キャッシュ タスクを追加する前は (右)、復元タスクに約 41 秒かかりました。 キャッシュ タスクを 2 番目のパイプラインに追加し (左)、キャッシュ ミスが発生したときに実行するように復元タスクを構成しました。 この場合の復元タスクは、完了するまで 8 秒かかりました。

キャッシュがある場合とない場合のパイプラインのパフォーマンスを示すスクリーンショット。

参照のため、完全な YAML パイプラインを次に示しておきます。

pool:
  vmImage: 'windows-latest'

variables:
  solution: '**/*.sln'
  buildPlatform: 'Any CPU'
  buildConfiguration: 'Release'
  NUGET_PACKAGES: $(Pipeline.Workspace)/.nuget/packages

steps:
- task: NuGetToolInstaller@1
  displayName: 'NuGet tool installer'

- task: Cache@2
  displayName: 'NuGet Cache'
  inputs:
    key: 'nuget | "$(Agent.OS)" | **/packages.lock.json,!**/bin/**,!**/obj/**'
    restoreKeys: |
       nuget | "$(Agent.OS)"
       nuget
    path: '$(NUGET_PACKAGES)'
    cacheHitVar: 'CACHE_RESTORED'

- task: NuGetCommand@2
  displayName: 'NuGet restore'
  condition: ne(variables.CACHE_RESTORED, true)
  inputs:
    command: 'restore'
    restoreSolution: '$(solution)'

- task: VSBuild@1
  displayName: 'Visual Studio Build'
  inputs:
    solution: '$(solution)'
    platform: '$(buildPlatform)'
    configuration: '$(buildConfiguration)'