如何在Golang项目Makefile中使用GitLab CI导出的TAG变量
问题原因
你之前在Makefile中直接引用TAG拿不到有效值,核心原因有两个:
before_script中导出的TAG是Shell环境变量,如果调用make时没有显式传入,或是Makefile内部定义了同名TAG变量覆盖了环境变量值,就会出现取值为空的问题。- 你当前的
go build命令写了两个-ldflags参数,Go编译时只会生效最后一个-ldflags配置,就算变量传对了,前面的-s(去除符号表缩小编译产物体积)配置也会失效。
实现方案
两种方案选其一即可,优先推荐方案1,版本生成逻辑只维护一份,避免双份逻辑不一致。
方案1:直接复用GitLab CI生成的TAG变量
不需要在Makefile里重复写版本号生成逻辑,只需要做两处修改:
- 修改GitLab CI的Job配置,调用
make时显式传入TAG参数,同时修复原逻辑中分支名带/会导致版本号非法的问题:
test: before_script: - | BUILD_NUM="1.0-${CI_PIPELINE_IID}" NORMALIZED_BRANCH="${CI_COMMIT_REF_NAME//\//-}" REPO_NAME=$(echo ${CI_PROJECT_NAME} | tr '[:upper:]' '[:lower:]') if [ ${CI_COMMIT_REF_NAME} = 'master' ]; then export TAG=${BUILD_NUM} else # 原逻辑直接用CI_COMMIT_REF_NAME会带/,替换为转义后的NORMALIZED_BRANCH export TAG="${BUILD_NUM}-${NORMALIZED_BRANCH}" fi script: # 显式把TAG传入Makefile,避免变量覆盖 - make dockercompile TAG=$TAG
- 修改Makefile的
dockercompile目标,合并两个-ldflags参数,替换原有的CI_PIPELINE_IID为传入的TAG:
dockercompile: # 可临时开启下面这行打印,验证取值是否正确 # @echo "Building with version tag: $(TAG)" GOOS=linux CGO_ENABLED=0 go build -mod=readonly -a -installsuffix cgo -o $(BIN_NAME) -ldflags="-s -X github.com/richardwilkes/toolbox/cmdline.AppVersion=1.0 -X github.com/richardwilkes/toolbox/cmdline.BuildNumber=$(TAG)" $(MAIN_FILE)
方案2:在Makefile中内置和CI一致的版本号生成逻辑
如果需要本地执行make也能生成符合规则的版本号、不依赖CI环境,可以直接把版本生成逻辑写在Makefile中,同时做本地环境兼容:
直接替换Makefile中的相关配置即可:
# 兼容本地构建:不在CI环境时,自动获取当前分支名、提交计数作为构建参数 CI_PIPELINE_IID ?= $(shell git rev-list --count HEAD 2>/dev/null || echo "0") CI_COMMIT_REF_NAME ?= $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "local") # 和CI完全一致的TAG生成规则 NORMALIZED_BRANCH := $(subst /,-,$(CI_COMMIT_REF_NAME)) BUILD_NUM := 1.0-$(CI_PIPELINE_IID) ifeq ($(CI_COMMIT_REF_NAME),master) TAG ?= $(BUILD_NUM) else TAG ?= $(BUILD_NUM)-$(NORMALIZED_BRANCH) endif dockercompile: @echo "Building with version tag: $(TAG)" GOOS=linux CGO_ENABLED=0 go build -mod=readonly -a -installsuffix cgo -o $(BIN_NAME) -ldflags="-s -X github.com/richardwilkes/toolbox/cmdline.AppVersion=1.0 -X github.com/richardwilkes/toolbox/cmdline.BuildNumber=$(TAG)" $(MAIN_FILE)
该方案兼容CI场景:如果CI中已经生成了
TAG变量,调用make dockercompile TAG=$TAG时会优先使用传入的TAG值,不会重复生成。
内容的提问来源于stack exchange,提问作者norman
相关产品推荐
相关产品推荐

