Gitlab CI 仅 CD 运行 满足特定条件时的流水线步骤
Gitlab CI CD only run Pipeline Step when certain criteria is met
我正在尝试配置我的 CI/CD 管道,以便仅在满足某些条件时才执行特定步骤。
我当前的规则定义如下所示:
rules:
- if: '($CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "web" || $CI_PIPELINE_SOURCE == "merge_request_event") && $CI_COMMIT_BRANCH == "develop" '
exists:
- $MY_FILE
我想达到的目标:
- 仅当从 branch_x 合并到 develop
时才执行步骤
- 或 当管道在 GitLab 上触发时执行步骤 UI
- 或 如果提交直接推送到 develop
则执行步骤
- 并且
$MY_FILE
中的文件存在于存储库中
与预期不同,该步骤 未 在
上执行
- 推送
- 合并 Branch_X 进入开发
- 通过 GitLab 手动触发 UI
存储库中存在相应的文件。
步骤工作是如果我改回
only:
- develop
但是我无法设置文件需要存在的条件。
您 运行 遇到的部分问题是某些预定义变量仅存在于特定类型的管道中。例如,保存标签名称的 CI_COMMIT_TAG
变量仅在管道是“标签管道”时才存在(创建标签后 运行 )。但是,如果标记指向作为合并请求源的 b运行ch 的 HEAD 的提交,它仍然只是标记管道,因此合并请求特定变量的 none将存在。
因此,您的条件会变得稍微复杂一些,因为我们需要更多的括号,或者我们的 rules
部分需要更多的 if
子句:
rules:
- if: ($CI_PIPELINE_SOURCE == 'push' || $CI_PIPELINE_SOURCE == 'web') && $CI_COMMIT_REF_NAME == 'develop'
exists:
- $MY_FILE
when: always
- if: $CI_PIPELINE_SOURCE == 'merge_request_event' && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == 'develop'
exists:
- $MY_FILE
when: always
- when: never
注意: 你可以只使用一个 if
子句来写这个,只需要使用更多的括号。
让我们一一看看这些变化。
首先,push
和 web
管道源在管道如何 运行 以及哪些预定义变量可用方面或多或少相同。
其次,变量$CI_COMMIT_BRANCH
仅在某些管道中可用。最值得注意的是,它仅在存在 B运行ch 时存在。如果管道 运行s 用于标记,则该变量将不存在,它不仅仅是空的。如果是合并请求事件,变量将不存在。 $CI_COMMIT_REF_NAME
更可靠,即使它可以有更多的值(提交 SHA、B运行ch 名称或标记名称)。
第三,与我们在这里处理的其他来源相比,merge_request_event
来源是一种完全不同的动物。可用的预定义变量完全不同,因为现在有两个 b运行ches(源和目标)。此外,如果您在 merge_request_event 的管道定义中有 rules
,则 merge_request_event 管道只能 运行。
我 运行 使用此规则场景和此管道定义进行了一些测试:
stages:
- run
Run Job:
stage: run
image: alpine:latest
script:
- echo $CI_PIPELINE_SOURCE
- echo $CI_COMMIT_REF_NAME
- echo $CI_COMMIT_BRANCH
- echo $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
- echo $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
Second Run Job:
stage: run
image: alpine:latest
rules:
- if: ($CI_PIPELINE_SOURCE == 'push' || $CI_PIPELINE_SOURCE == 'web') && $CI_COMMIT_REF_NAME == 'develop'
exists:
- 'a_file'
when: always
- if: $CI_PIPELINE_SOURCE == 'merge_request_event' && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == 'new_branch'
exists:
- 'a_file'
when: always
- when: never
script:
- echo $CI_PIPELINE_SOURCE
- echo $CI_COMMIT_REF_NAME
- echo $CI_COMMIT_BRANCH
- echo $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
- echo $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
这是正常 Push
事件到 develop
以外的 b运行ch 的作业输出:
Executing "step_script" stage of the job script
00:02
$ echo $CI_PIPELINE_SOURCE
push
$ echo $CI_COMMIT_REF_NAME
other_branch
$ echo $CI_COMMIT_BRANCH
other_branch
$ echo $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
$ echo $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
注意:只有第一份工作 运行s 因为 b运行ch 不是 develop
。如果 b运行ch develop
和 a_file
存在,则两个作业 运行,输出相同。
这是 'web' 源的作业输出到 develop
以外的 b运行ch:
Executing "step_script" stage of the job script
00:00
$ echo $CI_PIPELINE_SOURCE
web
$ echo $CI_COMMIT_REF_NAME
other_branch
$ echo $CI_COMMIT_BRANCH
other_branch
$ echo $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
$ echo $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
同样,在这种情况下,管道中只有一项工作。相反,如果我们为 develop
b运行ch 命中 运行 管道并且 a_file
存在,我们 运行 两个作业和输出是相同的:
Executing "step_script" stage of the job script
00:00
$ echo $CI_PIPELINE_SOURCE
web
$ echo $CI_COMMIT_REF_NAME
develop
$ echo $CI_COMMIT_BRANCH
develop
$ echo $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
$ echo $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
最后,如果我们推送到 b运行ch,它是存储库中针对 develop
和 a_file
的合并请求的 source
,我们会得到 merge_request_event
,但由于合并请求管道的工作方式,只能获得第二份工作:
Executing "step_script" stage of the job script
00:01
$ echo $CI_PIPELINE_SOURCE
merge_request_event
$ echo $CI_COMMIT_REF_NAME
some_other_branch
$ echo $CI_COMMIT_BRANCH
$ echo $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
some_other_branch
$ echo $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
new_branch
这里是 Merge Request Pipelines 的文档以获取更多信息。
我正在尝试配置我的 CI/CD 管道,以便仅在满足某些条件时才执行特定步骤。
我当前的规则定义如下所示:
rules:
- if: '($CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "web" || $CI_PIPELINE_SOURCE == "merge_request_event") && $CI_COMMIT_BRANCH == "develop" '
exists:
- $MY_FILE
我想达到的目标:
- 仅当从 branch_x 合并到 develop 时才执行步骤
- 或 当管道在 GitLab 上触发时执行步骤 UI
- 或 如果提交直接推送到 develop 则执行步骤
- 并且
$MY_FILE
中的文件存在于存储库中
与预期不同,该步骤 未 在
上执行- 推送
- 合并 Branch_X 进入开发
- 通过 GitLab 手动触发 UI
存储库中存在相应的文件。
步骤工作是如果我改回
only:
- develop
但是我无法设置文件需要存在的条件。
您 运行 遇到的部分问题是某些预定义变量仅存在于特定类型的管道中。例如,保存标签名称的 CI_COMMIT_TAG
变量仅在管道是“标签管道”时才存在(创建标签后 运行 )。但是,如果标记指向作为合并请求源的 b运行ch 的 HEAD 的提交,它仍然只是标记管道,因此合并请求特定变量的 none将存在。
因此,您的条件会变得稍微复杂一些,因为我们需要更多的括号,或者我们的 rules
部分需要更多的 if
子句:
rules:
- if: ($CI_PIPELINE_SOURCE == 'push' || $CI_PIPELINE_SOURCE == 'web') && $CI_COMMIT_REF_NAME == 'develop'
exists:
- $MY_FILE
when: always
- if: $CI_PIPELINE_SOURCE == 'merge_request_event' && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == 'develop'
exists:
- $MY_FILE
when: always
- when: never
注意: 你可以只使用一个 if
子句来写这个,只需要使用更多的括号。
让我们一一看看这些变化。
首先,push
和 web
管道源在管道如何 运行 以及哪些预定义变量可用方面或多或少相同。
其次,变量$CI_COMMIT_BRANCH
仅在某些管道中可用。最值得注意的是,它仅在存在 B运行ch 时存在。如果管道 运行s 用于标记,则该变量将不存在,它不仅仅是空的。如果是合并请求事件,变量将不存在。 $CI_COMMIT_REF_NAME
更可靠,即使它可以有更多的值(提交 SHA、B运行ch 名称或标记名称)。
第三,与我们在这里处理的其他来源相比,merge_request_event
来源是一种完全不同的动物。可用的预定义变量完全不同,因为现在有两个 b运行ches(源和目标)。此外,如果您在 merge_request_event 的管道定义中有 rules
,则 merge_request_event 管道只能 运行。
我 运行 使用此规则场景和此管道定义进行了一些测试:
stages:
- run
Run Job:
stage: run
image: alpine:latest
script:
- echo $CI_PIPELINE_SOURCE
- echo $CI_COMMIT_REF_NAME
- echo $CI_COMMIT_BRANCH
- echo $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
- echo $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
Second Run Job:
stage: run
image: alpine:latest
rules:
- if: ($CI_PIPELINE_SOURCE == 'push' || $CI_PIPELINE_SOURCE == 'web') && $CI_COMMIT_REF_NAME == 'develop'
exists:
- 'a_file'
when: always
- if: $CI_PIPELINE_SOURCE == 'merge_request_event' && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == 'new_branch'
exists:
- 'a_file'
when: always
- when: never
script:
- echo $CI_PIPELINE_SOURCE
- echo $CI_COMMIT_REF_NAME
- echo $CI_COMMIT_BRANCH
- echo $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
- echo $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
这是正常 Push
事件到 develop
以外的 b运行ch 的作业输出:
Executing "step_script" stage of the job script
00:02
$ echo $CI_PIPELINE_SOURCE
push
$ echo $CI_COMMIT_REF_NAME
other_branch
$ echo $CI_COMMIT_BRANCH
other_branch
$ echo $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
$ echo $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
注意:只有第一份工作 运行s 因为 b运行ch 不是 develop
。如果 b运行ch develop
和 a_file
存在,则两个作业 运行,输出相同。
这是 'web' 源的作业输出到 develop
以外的 b运行ch:
Executing "step_script" stage of the job script
00:00
$ echo $CI_PIPELINE_SOURCE
web
$ echo $CI_COMMIT_REF_NAME
other_branch
$ echo $CI_COMMIT_BRANCH
other_branch
$ echo $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
$ echo $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
同样,在这种情况下,管道中只有一项工作。相反,如果我们为 develop
b运行ch 命中 运行 管道并且 a_file
存在,我们 运行 两个作业和输出是相同的:
Executing "step_script" stage of the job script
00:00
$ echo $CI_PIPELINE_SOURCE
web
$ echo $CI_COMMIT_REF_NAME
develop
$ echo $CI_COMMIT_BRANCH
develop
$ echo $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
$ echo $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
最后,如果我们推送到 b运行ch,它是存储库中针对 develop
和 a_file
的合并请求的 source
,我们会得到 merge_request_event
,但由于合并请求管道的工作方式,只能获得第二份工作:
Executing "step_script" stage of the job script
00:01
$ echo $CI_PIPELINE_SOURCE
merge_request_event
$ echo $CI_COMMIT_REF_NAME
some_other_branch
$ echo $CI_COMMIT_BRANCH
$ echo $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
some_other_branch
$ echo $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
new_branch
这里是 Merge Request Pipelines 的文档以获取更多信息。