k8s && bazel 项目从 go1.20 升级 go1.21
go1.20
-> go1.21
的变化就不细说了,release note
在这 https://tip.golang.org/doc/go1.21。
主要是 bazel 构建相关的升级,还是值得留下一些文字记录。(本文仓库的 bazel 构建在初期借鉴了 https://github.com/kubernetes/repo-infra
go
版本的升级很简单,go.mod
修改 1.20
为 1.21
即可。go1.21
需要使用 rules_go
>= 0.41.0,而 rules_go
0.41.0 又需要 gazelle
>= 0.30.0。
一整套工具链都需要升级。
看 rules_go
和 gazelle
的 release note,就可以看到这个版本之后需要手动导入 googleapis
依赖了,有例子,依葫芦画瓢即可。如果使用的 proto
较多,可以善用 github search
或者 gazelle
的 git history。
其实仅仅到这里就没有文字记录的必要了,坑在后面。
有部分很老的带 proto
的依赖需要手动添加 googleapis
的 directives
,不想仓库直接写在 BUILD.bazel
就可以。这需要自行写在 go_repository
的 build_directives
里面。
然后就是更坑的。
当以上问题解决之后,update-bazel.sh
执行正常,但是 verify-bazel.sh
(gazelle fix --mode=diff
)跪了,会提示所有与 go
相关的 rules
都需要清除。换个说法就是在 gazelle
视角里面似乎已经没有任何 go
代码了。
为此我创建了一个最小复现仓库,使用不同版本的 gazelle
进行测试,最终找到了 bazelbuild/bazel-gazelle#1384。
由于 verify-bazel.sh
面对的文件并非直接来自于当前上下文而是 filegroup all-srcs
。这个 commit
使 gazelle
不再读取任何软链接内容,而 filegroup
就是软链接构建的,所以在 gazelle
视角里面就没有任何文件了。
具体的修复可以看 kubernetes/repo-infra#250。
嗯其实还有一个坑,很隐蔽,上线生产两个周才被发现,来自于 go1.21
release note
里面轻飘飘的一句话
Package initialization order is now specified more precisely
有机会下篇再说。