为什么本地通过不代表 CI 一定通过

因为本地和 CI 通常不共享这些东西:

  • 模块缓存
  • 环境变量
  • Git 凭据
  • 代理配置

本地能过,有时候只是因为你机器上“刚好已经下载过正确依赖”。

模块缓存带来的错觉

Go 模块缓存会让依赖获取变快,但也会让你误以为当前配置没问题。

例如:

  • 本地已经有旧版本依赖
  • 本地已经有访问过的私有模块
  • 本地之前成功过一次,所以后面一直复用缓存

这时 CI 首次全新构建,就更容易暴露真实问题。

什么叫可复现构建

对我来说,最核心的标准不是“永远完全一致”,而是:

  • 换一台新机器
  • 只拿代码和配置
  • 仍然能稳定拉起同一套依赖并完成构建

更稳的习惯

1. 把依赖整理交给工具

例如定期执行:

1go mod tidy

2. CI 里用干净环境做构建

这能更早暴露依赖图和配置问题。

3. 不把本地临时 replace 当作长期配置

不然本地和 CI 行为很容易分叉。

我的复盘

模块缓存是加速器,不是正确性的证明。真正稳定的项目,应该在“没有任何本地历史包袱”的环境里也能把构建跑起来。