我尝试做一个非常基本的 GitLab CI 工作。
我想要:
当我推动开发时,gitlab 会使用标签“develop”构建 docker 镜像
当我推送到 main 时,gitlab 检查当前提交是否有标签,并用它构建图像,否则不会触发作业。
Build and publish docker image:
stage: build
rules:
- if:
($CI_COMMIT_BRANCH == "main" && $CI_COMMIT_TAG && $CI_PIPELINE_SOURCE == "push")
variables:
TAG: $CI_COMMIT_TAG
- if:
($CI_COMMIT_BRANCH == "develop" && $CI_PIPELINE_SOURCE == "push")
variables:
TAG: develop
script:
- echo $TAG
- ...<another commands>
但它并没有按预期工作。 $CI_COMMIT_TAG - 为空。尽管触发作业(合并提交)的提交有标签。
我发现的解释我发现无助于使用“if”语句实现我的目标。
此处建议的解决方案基于工作流程也没有帮助。
使用称为 COMMIT_TAG 的变量的直观方式似乎很常见。
但它就是行不通。请好心人向我解释一下如何实现我的目标吗?
Gitlab CI/CD 有多个“管道源”,并且一些预定义变量仅存在于某些源。
例如,如果您只是将新提交push到远程,则
CI_PIPELINE_SOURCE
的值将为push
。对于 push
管道,许多预定义变量将不存在,例如 CI_COMMIT_TAG
、CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
、CI_EXTERNAL_PULL_REQUEST_SOURCE_BRANCH_NAME
等
但是,如果您在 GitLab UI 中或通过
git push --tags
命令创建 Git 标签,它将创建一个标签管道,并且像 CI_COMMIT_TAG
这样的变量将存在,但 CI_COMMIT_BRANCH
不会存在。
无论什么触发管道,始终存在的一个变量是
CI_COMMIT_REF_NAME
。对于提交与分支绑定的推送源,此变量将保存分支名称。如果提交未绑定到分支(即,该提交曾经有一个分支,但现在已被删除),它将保留完整的提交 SHA。或者,如果管道用于标签,它将保存标签名称。
有关更多信息,请阅读不同的管道源(在
CI_PIPELINE_SOURCE
变量的描述中)以及上面链接的文档中的其他变量。
我要做的就是将此检查移至
script
部分,以便我们可以使其变得更加复杂,以利于我们的利益,或者立即 exit 0
以便作业不会运行且不会失败,或者运行脚本的其余部分。
Build and publish docker image:
stage: build
image: alpine:latest
script:
- if [ $CI_PIPELINE_SOURCE != 'push' ]; then exit 0 fi
- if [ $CI_COMMIT_REF_NAME != 'develop' && $CI_COMMIT_TAG == '' ]; then exit 0 fi
- if [ $CI_COMMIT_TAG != '' ]; then git branch --contains $CI_COMMIT_TAG | grep main; TAG_ON_MAIN=$? fi
- if [ $TAG_ON_MAIN -ne 0 ]; then exit 0 fi
- echo $TAG
- ...<other commands>
这有点令人困惑,所以这里逐行介绍:
$CI_PIPELINE_SOURCE
变量不是“推”,我们 exit 0
。$CI_COMMIT_REF_NAME
(同样是提交 SHA、标签名称或分支名称)不是 develop
并且 $CI_COMMIT_TAG
为空,则 exit 0
$CI_COMMIT_TAG
不为空,我们运行命令来查看标签是否基于 main
、git branch --contains <tag_name>
。这将返回该标签所属的所有分支(即创建该标签的分支以及创建该标签后存在的所有分支)。然后我们将结果传递给 grep
来寻找 main
。如果 main
在结果列表中,则退出代码为 0
,我们可以使用特殊变量 $?
获得它(始终返回上一个命令的退出代码)。然后我们将此退出代码设置为一个变量以在下一个条件中使用。grep
中 3.
的退出代码是否为非 0(即,main
是否是 <tag_name>
分支列表中的 not),并且我们
exit 0
。完成所有这些之后,我们可以确定管道源是
push
,要么有标签并且位于main
分支上,要么没有标签并且管道用于develop
分支。