Sukka's Blog

童话只美在真实却从不续写

和很多持续集成服务一样,Travis CI 也支持将安装的依赖缓存起来加快每次构建的速度,但是 Travis CI 的缓存在一些情况下会和外部 Git Repo 引起冲突导致构建失败。把问题和解决方法记录下来。

准确说大部分 CI 的缓存机制都存在这个问题。

hexo-theme-suka 的之中有用到 Travis CI 进行测试,包括使用一个 Hexo 站点工程文件构建一个 Demo 站点,而 Hexo 工程文件和 Hexo 主题的 Repo 是分开的。由于 Travis CI 是配置在 hexo-theme-suka 的 Repo 下进行持续集成,所以构建过程中需要把 Hexo 工程文件中的 Repo 给 clone 下来。
在 Travis CI 的配置文件中设置缓存 node_modules 目录以后,邮箱就收到 Travis CI 构建失败的提示邮件。查看 Travis CI 的日志可以发现 Travis CI 弹出了报错:

travis-ci-git-error-log.png

明明这个目录是在构建中使用 git clone 命令创建的,为什么还会提示非空目录?

开个新 branch 打个断点,在 Travis CI 的构建流程 git clone 外部 Repo 之前,加一个 ls 指令把目录列出来。然后再看构建日志,发现目录下面有 node_modules——目录非空的原因就是 Travis CI 会在构建一开始就把缓存的目录下载导入。

解决方案就是,设法让构建中需要 git clone 到的目录和最后被缓存的目录不相同。实现的具体思路就是:

  • 构建时先进行 git clone,这时相关的文件会放在目录 A
  • cd 到 clone 下来的 Repo 里删掉 .git 文件夹
  • 将整个目录 mv 到新的位置目录 B
  • 在目录 B 中安装依赖(如执行 yarn 或者 npm i)并进行构建
  • 最后缓存在目录 B 中安装的依赖

这样,在下一次构建的时候,Travis CI 就会先把缓存的依赖储存到目录 B 中,目录 A 尚未创建,就不影响 git clone。而安装依赖是在将目录 A 中的文件移动到目录 B(合并)以后再执行的。

本文作者 : Sukka
本文采用 CC BY-NC-SA 4.0 许可协议。转载和引用时请注意遵守协议!
本文链接 : https://blog.skk.moe/post/travis-ci-cache-git-conflict/

本文最后更新于 天前,文中所描述的信息可能已发生改变