$CI_COMMIT_TAG in "if" statemets of regular job
$CI_COMMIT_TAG in "if" statemets of regular job
我尝试做一个非常基本的 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 - 是空的。尽管触发作业的提交(合并提交)有标签。
我找到的解释 that i found 无助于使用“if”语句实现我的目标。
此处建议的解决方案 也无济于事。
使用名为 COMMIT_TAG 的变量的直观方式似乎很常见。
但它就是行不通。请哪位好心人给我解释一下如何实现我的目标?
Gitlab CI/CD 有多个 'pipeline sources',其中一些 Predefined Variables 只存在于某些来源。
例如,如果您只是 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
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
变量不是 'push',我们 exit 0
.
- 如果
$CI_COMMIT_REF_NAME
(同样,提交 SHA、标记名称或分支名称)不是 develop
并且 $CI_COMMIT_TAG
为空,exit 0
- 如果
$CI_COMMIT_TAG
不为空,我们 运行 一个命令来查看标签是否基于 main
、git branch --contains <tag_name>
。这将 return 该标签所属的所有分支(即创建它的分支,以及创建标签后存在的所有分支)。然后我们通过 grep
传递结果来寻找 main
。如果 main
在结果列表中,退出代码是 0
我们可以用特殊变量 $?
得到它(总是 return 是前一个命令的退出代码)。然后我们将此退出代码设置为一个变量以在下一个条件中使用。
- 我们检查
grep
的退出代码是否来自步骤 3.
是非 0(也就是说,如果 main
是 not[=分支列表中的74=]是<tag_name>
的一部分),而我们exit 0
.
完成所有这些之后,我们可以确定管道源是 push
,或者有标签并且它在 main
分支上,或者没有标签管道用于 develop
分支。
我尝试做一个非常基本的 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 - 是空的。尽管触发作业的提交(合并提交)有标签。
我找到的解释 that i found 无助于使用“if”语句实现我的目标。
此处建议的解决方案
使用名为 COMMIT_TAG 的变量的直观方式似乎很常见。
但它就是行不通。请哪位好心人给我解释一下如何实现我的目标?
Gitlab CI/CD 有多个 'pipeline sources',其中一些 Predefined Variables 只存在于某些来源。
例如,如果您只是 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
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
变量不是 'push',我们exit 0
. - 如果
$CI_COMMIT_REF_NAME
(同样,提交 SHA、标记名称或分支名称)不是develop
并且$CI_COMMIT_TAG
为空,exit 0
- 如果
$CI_COMMIT_TAG
不为空,我们 运行 一个命令来查看标签是否基于main
、git branch --contains <tag_name>
。这将 return 该标签所属的所有分支(即创建它的分支,以及创建标签后存在的所有分支)。然后我们通过grep
传递结果来寻找main
。如果main
在结果列表中,退出代码是0
我们可以用特殊变量$?
得到它(总是 return 是前一个命令的退出代码)。然后我们将此退出代码设置为一个变量以在下一个条件中使用。 - 我们检查
grep
的退出代码是否来自步骤3.
是非 0(也就是说,如果main
是 not[=分支列表中的74=]是<tag_name>
的一部分),而我们exit 0
.
完成所有这些之后,我们可以确定管道源是 push
,或者有标签并且它在 main
分支上,或者没有标签管道用于 develop
分支。