缓存 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'

注意

缓存是不可变的,创建缓存后,无法修改其内容。

还原缓存

仅当变量为 false 时,才会运行此 CACHE_RESTORED 任务。

- 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 文件。 还原任务不会下载已存在于相应文件夹中的包。

注意

管道可以包含一个或多个缓存任务,同一管道中的作业和任务可以访问和共享同一缓存。

性能比较

管道缓存是加快管道执行速度的好方法。 下面是两个不同管道的并行性能比较。 在) (添加缓存任务之前,还原任务大约需要 41 秒。 我们将缓存任务添加到第二个管道 (左) ,并将还原任务配置为在遇到缓存未命中时运行。 在这种情况下,还原任务需要 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)'