7e5e412f7f
Tests / lint (pull_request) Failing after 9s
Tests / test (pull_request) Failing after 28s
Auto Merge PRs (main) / Auto Merge on CI Green + Approved (main) (pull_request) Failing after 30s
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Successful in 1m53s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 2m29s
CI/CD Pipeline / Build Production Runtime Images (pull_request) Has been skipped
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
- 触发方式:pull_request事件(CI状态变更时) - 合并条件:2门禁全绿 + 至少1个APPROVED + 无冲突 + 非草稿 - 安全措施:幂等保护、合并失败留评论、只合main - 新增check_ci_status.py和check_pr_approval.py辅助脚本
47 lines
1.2 KiB
Python
47 lines
1.2 KiB
Python
#!/usr/bin/env python3
|
|
"""检查PR是否有至少N个APPROVED审批。
|
|
|
|
用法: python3 check_pr_approval.py <token> <repo> <pr_number> <min_approval>
|
|
返回: 打印 "approved" 或 "pending"
|
|
"""
|
|
|
|
import json
|
|
import sys
|
|
import urllib.request
|
|
|
|
|
|
def main():
|
|
if len(sys.argv) != 5:
|
|
print("pending")
|
|
return
|
|
|
|
token = sys.argv[1]
|
|
repo = sys.argv[2]
|
|
pr_number = sys.argv[3]
|
|
min_approval = int(sys.argv[4])
|
|
|
|
api_url = f"https://git.xiaoxiajianji.com/api/v1/repos/{repo}/pulls/{pr_number}/reviews"
|
|
req = urllib.request.Request(api_url, headers={"Authorization": f"token {token}"})
|
|
|
|
try:
|
|
with urllib.request.urlopen(req, timeout=30) as resp:
|
|
reviews = json.loads(resp.read().decode())
|
|
except Exception:
|
|
print("pending")
|
|
return
|
|
|
|
# 统计APPROVED的人数(去重,同一人多次审批只算一次)
|
|
approvers = set()
|
|
for r in reviews:
|
|
if r.get("state") == "APPROVED":
|
|
approvers.add(r.get("user", {}).get("login", ""))
|
|
|
|
if len(approvers) >= min_approval:
|
|
print(f"approved ({len(approvers)})")
|
|
else:
|
|
print(f"pending ({len(approvers)})")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|