次の方法で共有


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

Azure DevOps Services | Azure DevOps Server 2022 | Azure DevOps Server 2020

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

Note

パイプライン キャッシュは、クラシック リリース パイプラインではサポートされていません。

前提条件

製品 要件
Azure DevOps - Azure DevOps プロジェクト
- アクセス許可:
    - プロジェクト内のすべてのパイプラインへのアクセスを許可するには、プロジェクト管理者グループのメンバーである必要があります。

依存関係をロックする

キャッシュ タスクを設定する前に、プロジェクトの依存関係をロックし、package.lock.json ファイルを生成する必要があります。 一意のキャッシュ キーは、ビルド間の一貫性を確保するために、このロック ファイルのコンテンツのハッシュから派生します。

プロジェクトの依存関係をロックするには、RestorePackagesWithLockFile プロパティを csproj ファイルに追加し、true に設定します。 nuget restoreを実行すると、プロジェクトのルート ディレクトリに packages.lock.json ファイルが生成されます。 必ず packages.lock.json ファイルをソースコードに登録してください。

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

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

NuGet パッケージをキャッシュするには、パイプラインを実行しているエージェント上のパッケージの場所を指すパイプライン変数を定義します。

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

Azure Pipelines でキャッシュ キーがどのように生成されるかを示すスクリーンショット。

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

- task: Cache@2
  displayName: Cache v2 task 
  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'

メモ

Ubuntu 24.04 以降を使用している場合は、NuGetCommand@2 タスクではなく、.NET CLI で NuGetAuthenticate タスクを使用する必要があります。 詳細については、Ubuntu でホストされる新しいイメージ のサポートに関するページを参照してください。

"project.assets.json が見つかりません" エラーを処理する

ビルド タスク中にエラー "project.assets.json not found" が発生した場合は、復元タスクから条件 condition: ne(variables.CACHE_RESTORED, true) を削除します。 これにより、復元コマンドが実行され、project.assets.json ファイルが生成されます。 復元タスクは、対応するフォルダーに既に存在するパッケージを再ダウンロードしません。

注記

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

パフォーマンスの比較

パイプライン キャッシュにより、依存関係の復元に必要な時間が大幅に短縮され、ビルドが高速化されます。 次の比較は、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)'

この方法は、プロジェクトで packages.lock.json を使用してパッケージのバージョンをロックする場合に、.NET Core プロジェクトにも適用されます。 これを有効にするには、*Csproj* ファイルに True するように RestorePackagesWithLockFile を設定するか、次のコマンドを実行します: dotnet restore --use-lock-file