Files
gplan-2/tools/ci_watch.sh
T

58 lines
3.1 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# 回执等待件——合回后等 CI 回执的后台轮询器(2026-11-02 用户裁;规则面=process-conventions §1 第 3 条「回执等待纪律」)。
# 用法: tools/ci_watch.sh <合并提交hash> [超时秒,默认 900]
# 调用面: 合回落地先向用户呈报本批总结,随即以 run_in_background 后台任务运行本件;命令结束时
# harness 唤醒会话——绿→删区收口;红→呈报红闸名单走修复批;超时→呈报「回执未落」(CI 可能崩溃)。
# 「本次回执已落」认领判据(三条全满足,防认错轮):
# ① 回执可整读——CI 写回执非原子,半截/读空静默重试;
# ② 回执 commit 为传入提交或其后代——另一会话合回推进尖端触发补跑覆盖时按后代认领(coalesce 语义见 ci_runner.sh);
# ③ 回执 timestamp 晚于合并提交时刻——排除合并前盘上的旧回执(旧尖端是合并提交的祖先,只查②会误领旧回执)。
# 退出码: 0=绿 1=红 2=超时/回执未落 3=参数错误
set -u
# 主工作区定位:CI 只在主工作区跑(post-merge 钩子限主区),从任务 worktree 内调用也要读主区回执——
# 经 git 公共目录(.git)的上级定位主仓根,主区调用与 worktree 调用同一读数
COMMON="$(git -C "$(dirname "$0")" rev-parse --path-format=absolute --git-common-dir 2>/dev/null)" \
|| { echo "不在 git 仓库内"; exit 3; }
REPO="$(dirname "$COMMON")"
STATUS="$REPO/game/tests/.gates/ci-status.json"
BASE="${1:-}"
TIMEOUT="${2:-900}"
INTERVAL=30
[ -n "$BASE" ] || { echo "用法: ci_watch.sh <合并提交hash> [超时秒]"; exit 3; }
BASE="$(git -C "$REPO" rev-parse --verify "${BASE}^{commit}")" || { echo "提交不存在: $BASE"; exit 3; }
BASE_CT="$(git -C "$REPO" log -1 --format=%ct "$BASE")"
_deadline=$(( $(date +%s) + TIMEOUT ))
while :; do
_read="$(python -I -c "
import json, sys, datetime
try:
d = json.load(open(sys.argv[1], encoding='utf-8'))
ts = int(datetime.datetime.fromisoformat(d['timestamp']).timestamp())
print(d.get('commit', ''), d.get('verdict', ''), ts)
except Exception:
pass
" "$STATUS")"
_com=""; _verdict=""; _ts=""
if [ -n "$_read" ]; then
set -- $_read
[ $# -eq 3 ] && { _com="$1"; _verdict="$2"; _ts="$3"; }
fi
if [ -n "$_com" ] && [ -n "$_verdict" ] && [ -n "$_ts" ] \
&& [ "$_ts" -gt "$BASE_CT" ] \
&& git -C "$REPO" merge-base --is-ancestor "$BASE" "$_com" 2>/dev/null; then
python -I -c "
import json, sys
d = json.load(open(sys.argv[1], encoding='utf-8'))
print('CI回执:', d.get('verdict'), '| commit', d.get('commit', '')[:8], '| 耗时', d.get('duration_s'), 's')
if d.get('note'): print('note:', d['note'])
for g in d.get('red_gates', []): print('红闸:', g)
for l in d.get('key_lines', []): print('key:', l)
" "$STATUS"
[ "$_verdict" = "green" ] && exit 0
exit 1
fi
_now=$(date +%s); _left=$((_deadline - _now))
[ "$_left" -le 0 ] && { echo "超时(${TIMEOUT}s)回执未落——CI 可能崩溃或未触发,查 game/tests/.gates/ 的 ci.lock 与 ci.log"; exit 2; }
sleep $(( _left < INTERVAL ? _left : INTERVAL ))
done