makefile 中执行 go mod tidy 会导致 ci 构建失败,因其默认修改 go.mod 和 go.sum,网络抖动时可能拉取不同 commit 的间接依赖;应仅在 make deps 中显式运行并校验退出码,且所有构建前必须执行 go mod verify。

Makefile 里执行 go mod tidy 为什么 CI 经常构建失败
因为 go mod tidy 默认会修改 go.mod 和 go.sum,而 CI 环境网络不稳定时,可能拉到不同 commit 的间接依赖(尤其是未打 tag 的模块),导致本地能过、CI 报错。
- 只在显式更新依赖时运行:
make deps,而不是make build前自动触发 -
deps目标中加GO111MODULE=on go mod tidy -v,并检查退出码;失败立即中断流水线 - 所有构建前必须加
go mod verify,防止go.sum被绕过或篡改
go build 不读 vendor?那 make test 为啥还连外网
Go 命令默认不启用 vendor 模式,go build、go test、go run 全部需要显式传参 -mod=vendor 才会跳过远程 fetch。
- 不要在每个命令里重复写
-mod=vendor,统一定义GOFLAGS := -mod=vendor更可靠 - 开启
vendor后,go mod graph、go list -m all等诊断命令失效,调试依赖问题时得临时关掉 -
go mod vendor生成的目录不是“开关”,它只是缓存副本;没配-mod=vendor就等于没用
Makefile 怎么感知 go.mod 变更并触发重建
Make 默认只看文件时间戳,而 go build 并不声明对 go.mod 的依赖,改了依赖后 make build 还走缓存,二进制根本没更新。
- 把
go.mod和go.sum显式加进构建目标的 prerequisites:bin/app: $(shell find . -name 'go.mod' -o -name 'go.sum') - 慎用
$(wildcard)—— 它只匹配当前目录,多模块项目(如含子go.mod)会漏掉嵌套路径 - 更稳的方式:用
find . -name 'go.mod' -print0 | xargs -0 stat -c '%y %n' | head -1生成唯一指纹,作为触发条件
go.work 出现后,Makefile 还能自动管理多模块吗
不能。Makefile 对 go.work 没原生支持,遇到 workspace 场景就得手动解析 go.work 列表,再挨个 cd 执行 go mod tidy 或 go build,极易出错。
- 目前没有通用方案,只能在 Makefile 里硬编码
go work use ./module-a ./module-b,但无法动态发现新增模块 - 如果项目已用
go.work,建议把依赖同步逻辑下沉到 shell 脚本或专用工具(如gowork),Makefile 只做入口调用 - 真正麻烦的不是写对 Makefile,而是当 workspace 成为常态后,所有自动化脚本都要重设计——这点容易被低估











