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(类型