来探讨下git工作流下golang项目的version信息该如何处理比较符合标准
之前自己写的几个简单的小工具都是没有把version信息注入到编译出来的文件里,发布版本多了后也无法溯源了.想着有必要看下这方面的知识了.
观察现有的一些
之前我博客docker panic那次事故就是根据docker info里的containerd的commit id找到了相关的代码来回溯.我们先看看各个项目的version信息
$ docker version Client: Docker Engine - Community Version: 19.03.2 API version: 1.40 Go version: go1.12.8 Git commit: 6a30dfc Built: Thu Aug 29 05:28:55 2019 OS/Arch: linux/amd64 Experimental: false Server: Docker Engine - Community Engine: Version: 19.03.2 API version: 1.40 (minimum version 1.12) Go version: go1.12.8 Git commit: 6a30dfc Built: Thu Aug 29 05:27:34 2019 OS/Arch: linux/amd64 Experimental: false containerd: Version: 1.2.10 GitCommit: b34a5c8af56e510852c35414db4c1f4fa6172339 runc: Version: 1.0.0-rc8+dev GitCommit: 3e425f80a8c931f88e6d94a8c831b9d5aa481657 docker-init: Version: 0.18.0 GitCommit: fec3683
$ etcd --version etcd Version: 3.3.13 Git SHA: 98d3084 Go Version: go1.10.8 Go OS/Arch: linux/amd64
$ kubectl version -o json { "clientVersion": { "major": "1", "minor": "13", "gitVersion": "v1.13.12", "gitCommit": "a8b52209ee172232b6db7a6e0ce2adc77458829f", "gitTreeState": "clean", "buildDate": "2019-10-15T12:12:15Z", "goVersion": "go1.11.13", "compiler": "gc", "platform": "linux/amd64" }, "serverVersion": { "major": "1", "minor": "13", "gitVersion": "v1.13.12", "gitCommit": "a8b52209ee172232b6db7a6e0ce2adc77458829f", "gitTreeState": "clean", "buildDate": "2019-10-15T12:04:30Z", "goVersion": "go1.11.13", "compiler": "gc", "platform": "linux/amd64" } }
如何注入
对比下都有如下信息:
- version
- go version
- arch info and os
- git commit id
- build date
makefile
go build -ldflags
包名.变量名
市面上很多都是单独整了个version文件,直接从里面cat的.实际都是master代码测试完美了后发布tag,tag触发release.可以根据tag号做版本号来外部注入.总的来说就是k8s这方面最规范.去看它的源码.
从k8s源码学习
staging/src/k8s.io/component-base/version/version.go
staging/src/k8s.io/component-base/version/base.go
hack/lib/init.sh
version脚本里逻辑可能对于非运维看比较麻烦,简单说下上面version信息:
Major1.18.21Minor1.18.218GitVersion$release-dirtyGitCommitGitTreeState
个人实现
我简单说下现在我推荐的逻辑判断:
git=(git --work-tree "${KUBE_ROOT}") #后面使用git命令用:"${git[@]}"
BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
HEAD=$("${git[@]}" rev-parse "HEAD^{commit}")
if [ -n "$TAG" ]; then TAG_COMMITID=$("${git[@]}" rev-parse $TAG 2>/dev/null) if [ "$?" -ne 0 ];then echo no such tag: $TAG exit 1 fi
else #默认取最新的tag TAG_COMMITID=$("${git[@]}" rev-list --tags --max-count=1) TAG=$("${git[@]}" describe --tags ${TAG_COMMITID}) fi
"${git[@]}" checkout $TAG 2>/dev/null BUILD_VERSION=${TAG}
if [ -z "$("${git[@]}" status --porcelain 2>/dev/null)" ];then GIT_TREE_STATE='clean' else GIT_TREE_STATE='dirty' fi
if [ "${HEAD}" != "${TAG_COMMITID}" ];then #tag的基础上改动,所以tag版本号-dirty BUILD_VERSION+="-dirty" COMMIT_ID=${HEAD} else COMMIT_ID=${TAG_COMMITID} fi
"${git[@]}" checkout $HEAD 2>/dev/null
整个细节性都在我github上