如何让GitLab流水线特定任务在创建Merge Request时仅运行一次?
嘿,这个需求我之前帮团队落地过,完全可以实现!下面给你两种GitLab CI原生支持的方案,按需选择就行:
方案1:通过CI规则锁定MR创建事件
GitLab CI提供了专门的MR事件变量,我们可以直接通过rules来限定任务只在MR首次创建时运行。
比如分配评审人的任务可以这么写:
assign-reviewer: stage: pre-process script: - echo "开始为MR分配评审人..." # 这里替换成实际的逻辑,比如调用GitLab API分配指定评审人 # 示例API调用(需要提前配置GITLAB_API_TOKEN作为CI变量): # curl --request POST --header "PRIVATE-TOKEN: $GITLAB_API_TOKEN" "https://your-gitlab-instance/api/v4/projects/${CI_PROJECT_ID}/merge_requests/${CI_MERGE_REQUEST_IID}/reviewers" --form "user_ids[]=123&user_ids[]=456" rules: # 仅当流水线来自MR事件,且事件类型是"opened"(首次创建)时运行 - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_EVENT_TYPE == "opened"' when: always # 其他情况跳过该任务 - when: never
这个方案的好处是简单直接,完全依赖GitLab的原生事件触发,不需要额外存储状态。如果需要支持MR重新打开时也执行一次,把条件改成$CI_MERGE_REQUEST_EVENT_TYPE =~ /opened|reopened/就行。
方案2:用状态标记确保绝对仅执行一次
如果你的场景要求无论MR后续怎么更新(比如多次push代码、重新打开),任务都只跑一次,可以结合GitLab API给MR添加自定义变量作为标记,脚本里先检查标记再执行操作。
比如QA环境数据迁移的任务:
migrate-qa-data: stage: data-handling script: - | # 检查当前MR是否已经执行过迁移 MR_HAS_MIGRATED=$(curl --silent --header "PRIVATE-TOKEN: $GITLAB_API_TOKEN" "https://your-gitlab-instance/api/v4/projects/${CI_PROJECT_ID}/merge_requests/${CI_MERGE_REQUEST_IID}/variables" | grep -c "QA_DATA_MIGRATED") if [ "$MR_HAS_MIGRATED" -eq 0 ]; then echo "开始从QA环境迁移数据..." # 这里写你的数据迁移脚本逻辑 # 迁移完成后,给MR添加变量标记已执行 curl --request POST --header "PRIVATE-TOKEN: $GITLAB_API_TOKEN" "https://your-gitlab-instance/api/v4/projects/${CI_PROJECT_ID}/merge_requests/${CI_MERGE_REQUEST_IID}/variables" --form "key=QA_DATA_MIGRATED" --form "value=true" --form "protected=false" else echo "该MR已完成数据迁移,跳过任务" fi rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' when: always - when: never
需要注意:
- 提前在项目CI/CD变量里配置
GITLAB_API_TOKEN,令牌需要有api权限,并且设为受保护变量避免泄露。 - 如果不需要支持重新打开MR的场景,也可以把
rules和方案1的条件结合,进一步缩小触发范围。
额外小提示
- GitLab 13.10及以上版本推荐用
rules替代旧的only/except,逻辑更清晰灵活。 - 分配评审人也可以用GitLab内置的审批规则,但如果需要自定义逻辑(比如根据代码变更路径分配不同评审人),还是用CI脚本调用API更灵活。
内容的提问来源于stack exchange,提问作者TomNg
相关产品推荐
相关产品推荐

