常规作业的“if”语句中的$CI_COMMIT_TAG

问题描述 投票:0回答:1

我尝试做一个非常基本的 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 的变量的直观方式似乎很常见。
但它就是行不通。请好心人向我解释一下如何实现我的目标吗?

docker deployment devops gitlab-ci gitlab-ci-runner
1个回答
13
投票

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>

这有点令人困惑,所以这里逐行介绍:

  1. 如果
    $CI_PIPELINE_SOURCE
    变量不是“推”,我们
    exit 0
  2. 如果
    $CI_COMMIT_REF_NAME
    (同样是提交 SHA、标签名称或分支名称)不是
    develop
    并且
    $CI_COMMIT_TAG
    为空,则
    exit 0
  3. 如果
    $CI_COMMIT_TAG
    不为空,我们运行命令来查看标签是否基于
    main
    git branch --contains <tag_name>
    。这将返回该标签所属的所有分支(即创建该标签的分支以及创建该标签后存在的所有分支)。然后我们将结果传递给
    grep
    来寻找
    main
    。如果
    main
    在结果列表中,则退出代码为
    0
    ,我们可以使用特殊变量
    $?
    获得它(始终返回上一个命令的退出代码)。然后我们将此退出代码设置为一个变量以在下一个条件中使用。
  4. 我们检查步骤
    grep
    3.
    的退出代码是否为非 0(即,
    main
    是否是 <tag_name> 分支列表中的
    not
    ),并且我们
    exit 0

完成所有这些之后,我们可以确定管道源是

push
,要么有标签并且位于
main
分支上,要么没有标签并且管道用于
develop 
分支。

© www.soinside.com 2019 - 2024. All rights reserved.