You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写GitLab CI定时脚本自动合并符合条件的Merge Request

方案合理性与可选实现方案

纯curl+sed/awk的方案可以实现基础功能,但维护性较差:GitLab API返回的是JSON结构,用文本解析的方式只要API返回格式稍有调整(比如新增嵌套字段、字段顺序变化)就会出现解析错误,更推荐用Shell脚本结合jq做JSON解析,或者用Python实现,逻辑更清晰也方便后续扩展准入条件校验。

Shell脚本实现方案(适合轻量化场景)

将核心逻辑抽成独立Shell脚本,用jq做结构化JSON解析,避免文本解析的不稳定问题:

修改后gitlab-ci.yml配置

variables:
  GROUPID: 6
stages:
  - cleanup

cleanup-code-job:
  stage: cleanup
  image: curlimages/curl:latest # 内置curl和jq,无需额外安装依赖
  tags:
    - build
  before_script:
    - chmod +x auto_merge_mr.sh
  script:
    - ./auto_merge_mr.sh
  only:
    - schedules # 仅定时任务触发时运行,避免代码提交时误执行

auto_merge_mr.sh脚本内容

#!/bin/sh
set -e

# 校验必要环境变量,GITLAB_PRIVATE_TOKEN需提前存入项目CI/CD变量中,不要硬编码
if [ -z "$GITLAB_PRIVATE_TOKEN" ] || [ -z "$CI_API_V4_URL" ] || [ -z "$GROUPID" ]; then
  echo "缺少必要CI变量"
  exit 1
fi

# 1. 拉取群组下所有项目ID
project_ids=$(curl -s --header "PRIVATE-TOKEN:$GITLAB_PRIVATE_TOKEN" \
  "$CI_API_V4_URL/groups/$GROUPID/projects" | jq -r '.[].id')

for project_id in $project_ids; do
  echo "处理项目ID: $project_id"
  # 2. 拉取项目下所有开放MR的IID
  mr_iids=$(curl -s --header "PRIVATE-TOKEN:$GITLAB_PRIVATE_TOKEN" \
    "$CI_API_V4_URL/projects/$project_id/merge_requests?state=opened" | jq -r '.[].iid')
  
  for mr_iid in $mr_iids; do
    echo "尝试合并MR IID: $mr_iid 所属项目ID: $project_id"
    # 此处可扩展准入条件校验:调用MR详情接口判断是否满足流水线通过、已审批等要求
    # 3. 调用合并接口
    merge_resp=$(curl -s -o /dev/null -w "%{http_code}" --request PUT \
      --header "PRIVATE-TOKEN:$GITLAB_PRIVATE_TOKEN" \
      "$CI_API_V4_URL/projects/$project_id/merge_requests/$mr_iid/merge")
    if [ "$merge_resp" = "200" ]; then
      echo "合并成功"
    else
      echo "合并失败,状态码: $merge_resp"
    fi
  done
done

30分钟定时任务配置

进入CI项目的「设置」->「CI/CD」->「计划」,新建定时任务,Cron表达式填写*/30 * * * *即可。

Python实现方案(适合复杂准入条件场景)

curl命令转Python可以直接用curlconverter工具,输入curl命令即可生成对应的requests代码,手动转换也只需对应HTTP方法、请求头、请求地址参数即可。

auto_merge_mr.py代码

import os
import requests

GITLAB_PRIVATE_TOKEN = os.getenv("GITLAB_PRIVATE_TOKEN")
CI_API_V4_URL = os.getenv("CI_API_V4_URL")
GROUPID = os.getenv("GROUPID")
HEADERS = {"PRIVATE-TOKEN": GITLAB_PRIVATE_TOKEN}

if not all([GITLAB_PRIVATE_TOKEN, CI_API_V4_URL, GROUPID]):
    raise Exception("缺少必要环境变量")

# 1. 拉取群组下所有项目ID
group_url = f"{CI_API_V4_URL}/groups/{GROUPID}/projects"
projects_resp = requests.get(group_url, headers=HEADERS)
projects_resp.raise_for_status()
project_ids = [p["id"] for p in projects_resp.json()]

for project_id in project_ids:
    print(f"处理项目ID: {project_id}")
    # 2. 拉取项目下所有开放MR的IID
    mr_url = f"{CI_API_V4_URL}/projects/{project_id}/merge_requests?state=opened"
    mr_resp = requests.get(mr_url, headers=HEADERS)
    mr_resp.raise_for_status()
    mr_iids = [m["iid"] for m in mr_resp.json()]
    
    for mr_iid in mr_iids:
        # 此处扩展准入条件校验,示例:判断MR是否已审批、流水线是否成功
        # mr_detail = requests.get(f"{CI_API_V4_URL}/projects/{project_id}/merge_requests/{mr_iid}", headers=HEADERS).json()
        # if not mr_detail.get("approved") or mr_detail.get("pipeline", {}).get("status") != "success":
        #     print(f"MR {mr_iid} 不满足准入条件,跳过")
        #     continue
        print(f"尝试合并MR {mr_iid}")
        # 3. 调用合并接口
        merge_url = f"{CI_API_V4_URL}/projects/{project_id}/merge_requests/{mr_iid}/merge"
        merge_resp = requests.put(merge_url, headers=HEADERS)
        if merge_resp.status_code == 200:
            print("合并成功")
        else:
            print(f"合并失败,状态码{merge_resp.status_code},返回内容:{merge_resp.text}")

对应gitlab-ci.yml配置

variables:
  GROUPID: 6
stages:
  - cleanup

cleanup-code-job:
  stage: cleanup
  image: python:3.10-slim
  tags:
    - build
  before_script:
    - pip install requests
  script:
    - python auto_merge_mr.py
  only:
    - schedules

注意:PRIVATE_TOKEN对应的账号需要有对应项目的Maintainer及以上权限才能执行合并操作。

内容的提问来源于stack exchange,提问作者Sameer Atharkar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 03:06:03