如何配置GitLab CI Job仅在Merge Request首次打开时运行一次
实现方案
GitLab CI目前没有原生的「仅MR首次打开触发」的规则,但可以通过以下三种方式实现,你可以根据自己的GitLab版本和使用场景选择:
方案一:使用CI_MERGE_REQUEST_EVENT_TYPE变量(推荐,GitLab 13.7+适用)
GitLab 13.7及以上版本提供了CI_MERGE_REQUEST_EVENT_TYPE内置变量,MR首次打开时该变量值为opened,后续MR更新、新提交推送时变量值为updated,直接配置规则匹配即可:
ping: stage: .pre rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_EVENT_TYPE == "opened"' script: - 'curl to slack url'
这个方案无需额外配置,直接修改规则即可生效,适配绝大多数场景。
方案二:使用CI_COMMIT_BEFORE_SHA判断(适用旧版本GitLab)
如果你的GitLab版本低于13.7,可以通过全零空SHA判断是否为MR首次触发:
MR首次创建对应的流水线中,CI_COMMIT_BEFORE_SHA会被赋值为全0的空哈希值,后续有新提交时该值会变为上一次提交的SHA,配置如下:
ping: stage: .pre rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_COMMIT_BEFORE_SHA == "0000000000000000000000000000000000000000"' script: - 'curl to slack url'
注意:该方案仅适用于「推送分支的同时创建MR」的场景,如果是先推送分支、后续手动创建MR的情况,首次MR事件对应的CI_COMMIT_BEFORE_SHA不为全零,会导致规则不生效。
方案三:API打标校验(通用全场景)
如果你的使用场景包含先推分支后开MR的情况,可以通过GitLab API给已经推送过通知的MR打自定义标签,后续触发时先校验标签是否存在,存在则直接跳过:
- 先在GitLab项目的「设置- CI/CD -变量」中添加
GITLAB_TOKEN变量,值为有MR编辑权限的个人访问令牌,勾选「保护变量」「掩码变量」。 - 修改CI配置如下:
ping: stage: .pre rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' script: # 校验MR是否已推送过通知 - | NOTIFIED=$(curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" "https://<你的GitLab域名>/api/v4/projects/$CI_PROJECT_ID/merge_requests/$CI_MERGE_REQUEST_IID/labels" | grep -c "slack-notified") - if [ $NOTIFIED -gt 0 ]; then exit 0; fi # 推送Slack通知 - 'curl to slack url' # 给MR打标记,避免后续重复推送 - | curl --request POST --header "PRIVATE-TOKEN: $GITLAB_TOKEN" "https://<你的GitLab域名>/api/v4/projects/$CI_PROJECT_ID/merge_requests/$CI_MERGE_REQUEST_IID" --form "labels=slack-notified"
该方案适配所有场景,无论MR创建方式如何,都只会触发一次通知。
内容的提问来源于stack exchange,提问作者Coogie
相关产品推荐
相关产品推荐

