如何用GitLab Rules排除特定合并请求中的流水线任务?
问题
需要在GitLab流水线中实现:当特定源/目标分支或特定标题的Merge Request(MR)触发流水线时,排除指定任务。具体规则:
- 若MR是production合并到testing(标题为
production into testing),任务不执行; - 若MR是testing合并到development(标题为
testing into development),任务不执行; - 其他类型MR,任务正常执行。
已尝试多种Rules配置但均未生效,示例配置如下:
示例1
rules: - if: $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME == "production" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "testing" when: never - if: $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME == "testing" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "development" when: never - if: $CI_PIPELINE_SOURCE == "merge_request_event"
示例2
rules: - if: $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME == "production" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "testing" || $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME == "testing" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "development" when: never - if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TITLE != "production into testing" - if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TITLE != "testing into development"
示例3
rules: - if: $CI_MERGE_REQUEST_TITLE == "production into testing" || $CI_MERGE_REQUEST_TITLE == "testing into development" when: never - if: $CI_COMMIT_BRANCH == "production" || $CI_COMMIT_BRANCH == "testing" || $CI_COMMIT_BRANCH == "development"
当前问题:功能分支合并到三个分支时任务正常执行,但通过API自动创建的上述两个特定MR触发流水线时,目标分支(testing/development)的指定任务仍会执行。
问题分析与正确配置
各示例配置的问题
- 示例1:最后一条规则仅匹配MR事件流水线,但当流水线是目标分支的分支流水线(比如MR合并后触发的testing/development分支流水线)时,
$CI_MERGE_REQUEST_*变量不存在,前两条规则会被跳过,最后一条规则也不匹配,任务会默认执行。 - 示例2:
- 逻辑运算符优先级没问题,但后面两条规则是独立判断,只要满足其中一条就会执行任务。比如当MR标题是
testing into development时,第二条规则$CI_MERGE_REQUEST_TITLE != "production into testing"会成立,导致任务执行,不符合需求; - 同样未处理目标分支的分支流水线场景。
- 逻辑运算符优先级没问题,但后面两条规则是独立判断,只要满足其中一条就会执行任务。比如当MR标题是
- 示例3:
- 第一条规则依赖
$CI_MERGE_REQUEST_TITLE,分支流水线中该变量不存在,规则直接跳过; - 第二条规则匹配三个分支的所有分支流水线,所以特定MR合并后触发的目标分支流水线会执行任务。
- 第一条规则依赖
正确的Rules配置
需要同时覆盖MR事件流水线和目标分支的分支流水线两种场景,明确指定任务执行/跳过的条件:
rules: # 匹配需要跳过任务的两种MR场景(含MR事件和合并后的分支流水线) - if: > ($CI_MERGE_REQUEST_SOURCE_BRANCH_NAME == "production" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "testing") || ($CI_MERGE_REQUEST_SOURCE_BRANCH_NAME == "testing" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "development") || ($CI_COMMIT_BRANCH == "testing" && $CI_PIPELINE_SOURCE != "merge_request_event" && $CI_COMMIT_MESSAGE =~ /production into testing/) || ($CI_COMMIT_BRANCH == "development" && $CI_PIPELINE_SOURCE != "merge_request_event" && $CI_COMMIT_MESSAGE =~ /testing into development/) when: never # 其他符合要求的场景执行任务 - if: > $CI_PIPELINE_SOURCE == "merge_request_event" || ($CI_COMMIT_BRANCH == "production" || $CI_COMMIT_BRANCH == "testing" || $CI_COMMIT_BRANCH == "development") when: on_success
配置说明
- 第一条规则:
- 前两行匹配MR事件流水线的两种特殊情况;
- 后两行匹配MR合并后的分支流水线:通过
$CI_COMMIT_MESSAGE匹配合并提交的标题(API创建的MR合并后,提交消息通常会包含MR标题);
- 第二条规则:覆盖所有需要执行任务的场景,包括所有MR事件流水线,以及三个分支的分支流水线;
- 使用
>换行书写条件,提升可读性; - 规则顺序必须是跳过规则在前,执行规则在后——GitLab规则按顺序匹配,匹配到第一条后就停止后续判断。
内容的提问来源于stack exchange,提问作者Nikolajs Andumins
相关产品推荐
相关产品推荐

