Azure Pipelines“Cache@2”失败并显示“##[错误]系统找不到指定的文件”

Posted

技术标签:

【中文标题】Azure Pipelines“Cache@2”失败并显示“##[错误]系统找不到指定的文件”【英文标题】:Azure Pipelines "Cache@2" fails with "##[error]The system cannot find the file specified" 【发布时间】:2020-03-31 22:01:45 【问题描述】:

我正在使用带有托管版本的 Azure Pipelines 来构建一个 Web 项目。我们的构建时间达到了 10-15 分钟,其中大部分(5-10 分钟)时间都花在了 npm install 上。为了加快速度,我正在尝试使用 Cache 任务 (https://docs.microsoft.com/en-us/azure/devops/pipelines/caching/?view=azure-devops)。

但是,当自动添加的任务 Post-job: Cache 运行时,它总是会出错:

##[error]The system cannot find the file specified

主机服务器是 Windows Server 2017。

这是我的整个构建 YAML

# Node.js with Vue
# Build a Node.js project that uses Vue.
# Add steps that analyze code, save build artifacts, deploy, and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/javascript

trigger:
- develop

pool:
  name: Default

variables:
  FONTAWESOME_NPM_AUTH_TOKEN: $(FONTAWESOME_NPM_AUTH_TOKEN_VARIABLE)
  npm_config_cache: $(Pipeline.Workspace)/.npm


steps:
- task: DutchWorkzToolsAllVariables@1

- task: NodeTool@0
  inputs:
    versionSpec: '10.x'
  displayName: 'Install Node.js'


- task: Cache@2
  inputs:
    key: 'npm | "$(Agent.OS)" | package-lock.json'
    path: $(npm_config_cache)
    cacheHitVar: NPM_CACHE_RESTORED

- task: Npm@1
  displayName: 'npm install'
  inputs:
    command: 'install'
  condition: ne(variables.NPM_CACHE_RESTORED, 'true')


- task: Npm@1
  displayName: 'npm run build'
  inputs:
    command: 'custom'
    customCommand: 'run build'

- task: CopyFiles@2
  inputs:
    SourceFolder: '$(Build.Repository.LocalPath)\dist'
    Contents: '**'
    TargetFolder: '$(Build.StagingDirectory)'
    CleanTargetFolder: true

- task: PublishBuildArtifacts@1
  inputs:
    PathtoPublish: '$(Build.ArtifactStagingDirectory)'
    ArtifactName: 'drop'
    publishLocation: 'Container'    

缓存任务输出:

Starting: Cache
==============================================================================
Task         : Cache
Description  : Cache files between runs
Version      : 2.0.0
Author       : Microsoft Corporation
Help         : https://aka.ms/pipeline-caching-docs
==============================================================================
Resolving key:
 - npm               [string]
 - "Windows_NT"      [string]
 - package-lock.json [file] --> F93EFA0B87737CC825F422E1116A9E72DFB5A26F609ADA41CC7F80A039B17299
Resolved to: npm|"Windows_NT"|rbCoKv9PzjbAOWAsH9Pgr3Il2ZhErdZTzV08Qdl3Mz8=
Information, ApplicationInsightsTelemetrySender will correlate events with X-TFS-Session zzzzz
Information, Getting a pipeline cache artifact with one of the following fingerprints:
Information, Fingerprint: `npm|"Windows_NT"|rbCoKv9PzjbAOWAsH9Pgr3Il2ZhErdZTzV08Qdl3Mz8=`
Information, There is a cache miss.
Information, ApplicationInsightsTelemetrySender correlated 1 events with X-TFS-Session zzzzz
Finishing: Cache

后期:缓存输出:

Starting: Cache
==============================================================================
Task         : Cache
Description  : Cache files between runs
Version      : 2.0.0
Author       : Microsoft Corporation
Help         : https://aka.ms/pipeline-caching-docs
==============================================================================
Resolving key:
 - npm               [string]
 - "Windows_NT"      [string]
 - package-lock.json [file] --> 2F208E865E6510DE6EEAA6DB0CB7F87B323386881F42EB63E18ED1C0D88CA84E
Resolved to: npm|"Windows_NT"|OQo0ApWAY09wL/ZLr6fxlRIZ5qcoTrNLUv1k6i6GO9Q=
Information, ApplicationInsightsTelemetrySender will correlate events with X-TFS-Session zzzzz
Information, Getting a pipeline cache artifact with one of the following fingerprints:
Information, Fingerprint: `npm|"Windows_NT"|OQo0ApWAY09wL/ZLr6fxlRIZ5qcoTrNLUv1k6i6GO9Q=`
Information, There is a cache miss.
Information, ApplicationInsightsTelemetrySender correlated 1 events with X-TFS-Session zzzzz
##[error]The system cannot find the file specified
Finishing: Cache

如何修复我的构建定义以使缓存正常工作?

【问题讨论】:

我认为问题是先有鸡还是先有蛋的问题。基本上,缓存键基于packages-lock.json 文件的哈希值,但这些文件内容可能会在随后的npm install 期间发生变化。构建后任务运行时,它会重新计算密钥 (?),但无法找到“新”缓存文件夹。 嗨@jklemmack 您是否尝试过 Florian 提供的解决方案。这似乎是正确的答案。 起初,@Florian-Labranche 的解决方案似乎不起作用。一段时间以来,我一直忙于其他事情,但几周后会回到这个话题。最终管道确实可以工作(没有 Cache@2 任务)......只是非常缓慢。 【参考方案1】:

@Levi Lu-MSFT 在他的comment 中是正确的,但有一个问题。

@FLabranche 在他的answer 中有一个可行的解决方案,但我认为推理不太正确。

问题

npm install@Cache 任务正在寻找不同位置的 npm 缓存。考虑管道第一次运行时的流程:

    @Cache task:什么都不做,因为还没有缓存。 npm i(或npm ci)任务:在node_modules/ 中安装软件包并在默认位置更新npm缓存。默认位置是 Linux/Mac 上的 ~/.npm 和 Windows 上的 %AppData%/npm-cache。在 Linux 托管的云代理上,绝对路径将为 /home/vsts/.npm。 (...更多来自您的管道的任务) 作业后@Cache 任务(隐式添加):读取在用户提供的位置找到的 npm 缓存以存储它以供将来重用。用户提供的位置由npm_config_cache: $(Pipeline.Workspace)/.npm 变量设置。在 Linux 托管的云代理上,绝对路径将为 /home/vsts/work/1/.npm

因此,@Cache 任务以tar: /home/vsts/work/1/.npm: Cannot open: No such file or directory 失败。

解决方案

使 npm install@Cache 任务使用相同的 npm 缓存位置。

Levi Lu 建议的一个选项是使用 npm config set cache $(npm_config_cache) --global 更新 npm 配置,但它在管道中不起作用(至少它在 Azure 托管的 Linux 代理中对我不起作用):Error: EACCES: permission denied, open '/usr/local/etc/npmrc'

npm ci --cache $(npm_config_cache) 为单个调用更新 npm 缓存位置,它在这种情况下确实有效。感觉有点 hacky,因为 --cache 选项甚至没有记录在 npm 网站上。

所有这些代码都为我工作:

variables:
  NPM_CACHE_FOLDER: $(Pipeline.Workspace)/.npm

steps:
- task: Cache@2
  displayName: Cache npm dependencies
  inputs:
    key: 'npm | "$(Agent.OS)" | package-lock.json'
    restoreKeys: |
      npm | "$(Agent.OS)"
      npm
    path: $(NPM_CACHE_FOLDER)

- script: npm ci --cache $(NPM_CACHE_FOLDER)
  displayName: 'Install npm dependencies'

...

【讨论】:

优秀的总结。这种详细程度应该诚实地包含在 Microsoft 的官方文档中。一个澄清:删除任务“Cache@2”是否完全阻止后续运行使用缓存?我知道缓存不能被删除(只能重新定位),但我仍然有能力在后续运行中完全忽略缓存,对吧?【参考方案2】:

您可以登录到您的 Windows Server 2017 服务器并检查文件夹 $(Pipeline.Workspace)/.npm 是否已创建并且依赖项是否存储在其中。

我复制并测试了您的 yaml。它适用于本地代理(win2019)和云代理。您可以尝试在云代理或其他具有较新系统的代理上运行您的管道,以检查是否是导致此错误的代理。

【讨论】:

事实上,我确实在适当的位置有一个目录:c:\agent2\_work\40\.npm,看起来它充满了缓存的东西。那么,为什么自动生成的任务会报告错误,从而导致构建出错? 您能否尝试在 npm install 之前添加一个额外的 npm 任务以运行 npm config set cache $(npm_config_cache) --global 以将 npm_config_cache 环境变量覆盖到路径 $(Pipeline.Workspace)/.npm。或者为你的 npm 安装任务运行 npm install --cache $(npm_config_cache)【参考方案3】:

使用您的 package-lock.json 生成的密钥在两个任务之间有所不同。 它发生在文件被修改时。在这里,它们由您的 npm install 任务修改。

在配置缓存任务以回退到最新的缓存条目时,您可以使用 restoreKeys 选项。 而且我认为您不需要“npm install”任务。

您可以尝试替换这个吗:

- task: Cache@2
  inputs:
    key: 'npm | "$(Agent.OS)" | package-lock.json'
    path: $(npm_config_cache)
    cacheHitVar: NPM_CACHE_RESTORED

- task: Npm@1
  displayName: 'npm install'
  inputs:
    command: 'install'
  condition: ne(variables.NPM_CACHE_RESTORED, 'true')

根据这个定义:

- task: Cache@2
  inputs:
    key: 'npm | "$(Agent.OS)" | package-lock.json'
    restoreKeys: |
       npm | "$(Agent.OS)"
       npm
    path: $(npm_config_cache)
  displayName: Cache npm

- script: npm ci --cache $(npm_config_cache)

【讨论】:

我无法对主线程发表评论,但您能否尝试使用 npm ci --cache $(npm_config_cache) 而不是 npm ci 将 Levi Lu 和我的解决方案混合在一起? npm install 是在缓存步骤之后的一个步骤,那么它如何影响锁定文件的哈希?【参考方案4】:

昨天,我能够通过使用它在自托管机器代理上毫无问题地运行它:

- task: Cache@2
  inputs:
    key: '**/package-lock.json, !**/node_modules/**/package-lock.json, !**/.*/**/package-lock.json'
    path: '$(System.DefaultWorkingDirectory)/node_modules'
  displayName: 'Cache Node Modules'

今天,今天尝试在托管代理上工作,但这一点也不成功。 Aggh,回到研磨板。无论如何,也许可以在您的自托管管道上为您工作

【讨论】:

【参考方案5】:

这似乎和这个open issue有关。

我已经通过将构建代理池切换到 hosted 并使用 windows-latest 图像解决了这个问题。

pool:
  vmImage: 'windows-latest'

【讨论】:

在我的情况下不可接受,因为我需要进行托管构建。不过,寻找tar 可能是一个有趣的解决方案。 @jklemmack - 你让焦油工作了吗?我正在尝试在构建服务器上获取 tar 但无法。

以上是关于Azure Pipelines“Cache@2”失败并显示“##[错误]系统找不到指定的文件”的主要内容,如果未能解决你的问题,请参考以下文章

建立Azure Dev Ops持续集成和持续交付(CICD)(使用 Azure Pipelines 建立CICD)

建立Azure Dev Ops持续集成和持续交付(CICD)(使用 Azure Pipelines 建立CICD)

对 Azure Boards 和 Azure Pipelines 使用相同的名称

如何在 Azure Pipelines Yaml 上循环多个 Azure 订阅?

如何在 azure-pipelines 中使用公钥对某些内容进行 scp?

Azure DevOps 发布错误“Microsoft.TeamFoundation.DistributedTask.Pipelines.PipelineValidationException(类型