你遇到的问题之一是某些预定义变量仅存在于特定类型的流水线中。例如,变量
CI_COMMIT_TAG
,它保存标签名称,只在"标签流水线"(在创建标签后运行)中存在。然而,如果标签指向的提交是Merge Request源分支的HEAD,则它仍然只是一个"标签流水线",因此不存在任何Merge Request特定的变量。
因此,你的条件将会更加复杂,因为我们需要更多的括号或更多的
if
子句来处理
rules
部分。
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
仅在某些管道中可用。最明显的是,只有当存在分支时才存在该变量。如果管道运行的是标签,则该变量不存在,它不仅仅是空的。如果是合并请求事件,则该变量也不存在。$CI_COMMIT_REF_NAME
更可靠,即使它可能具有更多的值(提交SHA、分支名称或标签名称)。
第三,“merge_request_event”源与我们在此处理的其他源完全不同。可用的预定义变量完全不同,因为现在有两个分支(源和目标)。另外,如果您的流水线定义中有用于“merge_request_event”的规则,“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
以下是针对除了
develop
分支的普通
Push
事件的作业输出:
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
注意:只有第一个任务运行,因为分支不是
develop
。如果分支是
develop
并且a_file
存在,则两个任务都会运行,输出相同。
这是针对“web”源的任务输出,针对除
develop
之外的分支:
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
分支并且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
最后,如果我们将源分支推送到一个以
develop
为目标的合并请求中,并且在代码库中有一个名为
a_file
的文件,则会触发
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
这里是有关合并请求管道的文档,提供更多信息。
when: manual
的作业的播放按钮”,实际上是“触发器”,还是“运行管道”按钮?它们是不同的事情,对于CI_PIPELINE_SOURCE
变量具有不同的值。 - Adam Marshall