GitHub Actions可重用工作流yarn缓存未命中问题咨询
核心认知偏差
- GitHub Actions 所有作业(Job)默认运行在完全独立的全新虚拟机实例上,作业之间不共享运行时的文件系统。你在前置
yarn作业里执行安装生成的node_modules、软链等文件,作业运行结束后对应虚拟机就会被销毁,后续作业根本拿不到这些文件,这是报错的根本原因。 actions/cache不是作业之间实时共享文件的通道,它的逻辑是:当前作业运行结束后,把你指定路径的文件打包上传到GitHub的缓存存储区;后续其他作业启动时,如果匹配到相同缓存键,会提前把对应缓存包下载解压到作业环境的指定路径。它不会自动把前置作业运行时生成的所有文件同步给后续作业。- 你当前的缓存配置本身就有问题:仅配置了缓存yarn的全局包下载目录(也就是yarn存压缩包的路径),完全没有缓存实际安装依赖生成的
node_modules目录,也没有缓存yarn bootstrap生成的monorepo软链、关联配置文件,就算后续作业命中缓存,拿到的也只是安装包的压缩缓存,不是可直接运行的依赖文件,自然会报concurrently: not found的错误。
现有配置的具体错误
validate_lint.yml存在语法错误:Enable node步骤被写在了steps层级之外,该步骤根本不会执行,你配置的cache: 'yarn'完全没有生效。- 就算修正上述语法错误,
actions/setup-node自带的cache: 'yarn'配置也只会恢复yarn的全局包缓存目录,不会自动执行yarn install,更不会自动生成node_modules目录,依然会报错。 - 你试图用单独的前置作业完成依赖安装、给后续所有作业复用的思路本身就是反模式:跨作业缓存node_modules的上传、下载耗时往往比直接在当前作业执行带缓存的install还长,大仓库场景下反而会拖慢整体运行速度。
正确实现方案
不需要在每个作业里重复写全量依赖配置,按照官方最佳实践调整即可:
- 把「拉取代码、配置Node.js、配置yarn缓存、执行依赖安装」这一套重复逻辑封装成复合动作(Composite Action),而不是拆成独立的前置可重用工作流作业。复合动作的步骤会直接在调用它的当前作业环境里执行,不存在跨虚拟机的文件隔离问题。
- 每个需要依赖的作业(比如lint、单元测试、构建等)开头直接调用这个封装好的复合动作即可,没有代码冗余。配合缓存命中的场景,
yarn install --frozen-lockfile执行速度通常在几秒内,不会有明显的耗时增加。 - 不要为了省install步骤强行跨作业缓存node_modules:即使用缓存,也建议每个作业正常执行install命令——缓存命中时yarn会直接从本地缓存解压文件,不需要走网络下载;缓存未命中时yarn会自动拉取缺失的包,逻辑稳定性远高于直接恢复全量node_modules。
如果你一定要保留单独的yarn安装作业,就必须把
node_modules、yarn bootstrap生成的所有关联文件路径全部加入缓存配置,同时在后续所有作业里配置完全一致的缓存键、缓存路径来恢复文件,还要承担缓存包上传下载的额外耗时,性价比极低,不推荐使用。
内容的提问来源于stack exchange,提问作者Phil Lucks
相关产品推荐
相关产品推荐

