#!/bin/bash # 自动合并通过 CI 检查的 PR # 用法: ./scripts/auto_merge_prs.sh [target_branch] # # 合并前必须验证的 CI 检查项: # - CI/CD Pipeline / Validate Code Quality And Tests (push) # - CI/CD Pipeline / Frontend Lint (push) # 只有两个检查项均为 success 状态才允许合并 GITEA_API="${GITEA_API_URL:-https://git.xiaoxiajianji.com/api/v1}" TOKEN="${GITEA_API_TOKEN:?Please set GITEA_API_TOKEN environment variable}" REPO="xiaoxia/xiaoxia-saas" TARGET_BRANCH="${1:-develop}" # 必需的 CI 检查项(context 名称前缀匹配,避免 pipeline 名称变化导致匹配失败) REQUIRED_CHECKS=( "Validate Code Quality And Tests" "Frontend Lint" ) echo "=== Checking open PRs targeting $TARGET_BRANCH ===" # 获取所有 open PR PRS=$(curl -s -H "Authorization: token $TOKEN" \ "$GITEA_API/repos/$REPO/pulls?state=open&sort=updated&direction=desc" | python3 -c " import json, sys data = json.load(sys.stdin) for pr in data: if pr.get('base', {}).get('ref') == '$TARGET_BRANCH': head_sha = pr.get('head', {}).get('sha', '') print(f\"{pr['number']}|{pr['title']}|{head_sha}\") ") if [ -z "$PRS" ]; then echo "No open PRs found for $TARGET_BRANCH" exit 0 fi merge_count=0 skip_count=0 echo "$PRS" | while IFS='|' read -r number title head_sha; do echo "" echo "--- PR #$number: $title ---" echo " Head SHA: $head_sha" # 获取该 commit 的 combined CI 状态 STATUS_JSON=$(curl -s -H "Authorization: token $TOKEN" \ "$GITEA_API/repos/$REPO/commits/$head_sha/status") # 检查每个必需的 CI 项是否通过 all_passed=true failed_checks="" for check_pattern in "${REQUIRED_CHECKS[@]}"; do state=$(echo "$STATUS_JSON" | python3 -c " import json, sys d = json.load(sys.stdin) pattern = '$check_pattern' # 在 statuses 中找到匹配的最新状态 target = None for s in d.get('statuses', []): if pattern in s.get('context', ''): target = s break # status 接口返回的是每个 context 的最新状态,取第一个匹配即可 if target: print(target.get('state', 'unknown')) else: print('not_found') ") if [ "$state" = "success" ]; then echo " ✅ $check_pattern: $state" else echo " ❌ $check_pattern: $state" all_passed=false failed_checks="$failed_checks $check_pattern($state)" fi done if [ "$all_passed" != "true" ]; then echo " ⏭️ Skipping - CI not passed:$failed_checks" skip_count=$((skip_count + 1)) continue fi # CI 全部通过,执行合并 echo " 🚀 All CI checks passed, merging..." RESULT=$(curl -s -X POST \ -H "Authorization: token $TOKEN" \ -H "Content-Type: application/json" \ "$GITEA_API/repos/$REPO/pulls/$number/merge" \ -d '{"Do": "merge"}') if echo "$RESULT" | python3 -c "import json,sys; d=json.load(sys.stdin); sys.exit(0 if d.get('merged', False) or 'id' in d else 1)" 2>/dev/null; then echo " ✅ PR #$number merged successfully" merge_count=$((merge_count + 1)) else echo " ❌ PR #$number merge failed" # 提取错误信息 err_msg=$(echo "$RESULT" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('message', str(d)[:200]))" 2>/dev/null) echo " Error: $err_msg" fi done echo "" echo "=== Done ===" echo "Merged: $merge_count | Skipped: $skip_count"