与其他几位用户一样,我面临着 GitLab CI/CD 中重复管道的问题。虽然 GitLab 文档中散布着一些关于如何防止这种情况的文档, 我的印象是各个文档页面和部分相当不一致。
我的问题是,以下规则有什么区别?或者,更具体地说,是否存在对这些规则进行不同评估的情况?
在分支管道和合并请求管道之间切换建议这样做来识别合并请求管道:
if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
此外,分支管道和合并请求管道之间的切换也结合使用此规则和
$CI_COMMIT_BRANCH &&
:
if: '$CI_OPEN_MERGE_REQUESTS'
此外,MergeRequest-Pipelines.gitlab-ci.yml使用第三条规则:
if: $CI_MERGE_REQUEST_IID
非常感谢我可能忽略的文档页面的任何解释或提示。
为了避免重复创建管道以及要在分支管道和合并请求管道之间切换的要求,我建议使用这些
workflow rules
workflow:
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'
when: never
- if: '$CI_COMMIT_BRANCH' || '$CI_COMMIT_TAG'
还有另一个 SO 问题询问如何防止重复管道这里
在下一节中,我将尝试解释不同的规则以及 GitLab CI 在管道创建过程中如何评估它们。
merge_request_event
规则使用此规则:
if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
每次创建/更新合并请求时都会创建一个管道,但如果您没有其他预防机制(规则),也会为分支创建一个管道。 正如变量命名也指出的那样,这与管道触发器的来源有关,其他来源可能是
schedule
、push
、trigger
等。
CI_OPEN_MERGE_REQUESTS
变量:使用如下规则:
if: '$CI_OPEN_MERGE_REQUESTS'
如果该分支有开放的合并请求,GitLab 将创建新的管道。管道,因为将有一个合并请求管道(用
detached
标志表示)和一个用于您推送更改的分支的分支管道。
if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'
当且仅当该分支上有开放的 MR 时,上面的规则才会为您的分支创建管道。
if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'
when: never
使用上述组合时,如果该分支上有开放的合并请求,则不会创建管道,这也可能是不可取的,因为 CI 应该对分支和/或合并请求运行测试。
但是如何能够拥有 MR 和分支的管道,同时防止管道创建重复?
- if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'
when: never
- if: '$CI_COMMIT_BRANCH' || '$CI_COMMIT_TAG'
通过上面设置的规则,GitLab 将为分支和合并请求(
detached
)创建管道,以及为 git-tags
创建管道,但它将阻止 GitLab 复制管道。
当有对分支的提交或有 git-tag 时,最后一条规则的计算结果为 true。
您还可以添加环境变量来帮助管道中的任务识别模式,而无需重复该逻辑。这些变量应该传播到子管道,使上下文识别一致且更简单。
例如:
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
variables:
CI_MODE: MR #i.e - merge request
- if: >
$CI_PIPELINE_SOURCE == "push" &&
$CI_COMMIT_TAG
variables:
CI_MODE: TAG
- if: >
$CI_PIPELINE_SOURCE == "push" &&
$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
variables:
CI_MODE: RC #i.e - release-candidate
然后,沿着管道和子管道 - 上下文相关的作业可以用 if: $CI_MODE = ".."
标记,无需任何喧嚣。