合并(CI 读数与迭代51连带面·工程+文档): ①现查件堵假绿——绿须坐实跑闸步真跑过,零触发批呈报未验(退出码4)、读数不可信呈报不可判(2),run 55 实证跑闸步 skipped 而 conclusion=success;②迭代 51 四红项随迁——forge_table 词表计数 22→21(卡①删 charge_full)、system_contracts 补 facts 第五参、save_manager_domain 改公开名 migrate_legacy_save、breakpoint_store 参数补类型(09 R3),件核全仓零残留同类点;③口径同步 AGENTS+process-conventions §1/§8+test-conventions §8.7+技能两镜像。本机验证三套件 exit0+类型闸归零+--docs 零新增红;master 停在 5d7579e7 的 run 56 红由本批修复追绿。遗留: settlement_wiring_snapshot golden 平台绑定(本机红/远端绿)待登记
ci / gates (push) Failing after 8m2s

This commit is contained in:
DKChan committed 2026-11-04 07:51:06 +08:00
commit 7046cbaf83
8 files changed
+44 -25

No files matched your search

+32 -14
View File
@@ -1,11 +1,12 @@
#!/usr/bin/env bash
# CI 现查件——按需读远端 run 的终局态,只呈报、不落盘(2026-11-04 用户裁:回执等待件与本地缓存判定退役)。
# 用法: tools/ci_check.sh [<提交hash>](缺省=当前 HEAD)
# 判据:Gitea commit status 只用来取本次任务的 run 链接,绿红一律认 run 自身的 status/conclusion——
# run 未 completed(排队/在跑/尝试级中间态)与零触发批(纯闸件/管线批不建任务)一律呈报「未落定」,不写红。
# 判据:Gitea commit status 只用来取本次任务的 run 链接,绿红一律认 run 自身的 status/conclusion,
# 且绿必须坐实「跑闸步真跑过」——零触发批的 run 照样建、照样 success,但跑闸步是 skipped,
# 一条闸都没跑,读成绿就是假绿(2026-11-04 run 55 实证)。run 未 completed(排队/在跑/尝试级中间态)呈报未落定。
# 调用面:开工前读态(红未修不开新批)、合回后想知道结果时手动查——合回流程不等待、不唤醒,呈报即回合止。
# 授权:GITEA_TOKEN 环境变量优先,否则读 git 凭据库(host=git.kuaimeo.com)。
# 退出码: 0=绿 1=红 2=未落定/零触发/查不到 3=参数或令牌错误
# 退出码: 0=绿(跑闸步真跑过) 1=红 2=未落定/不可判/查不到 3=参数或令牌错误 4=未验(零触发批,跑闸步全跳过)
set -u
COMMON="$(git -C "$(dirname "$0")" rev-parse --path-format=absolute --git-common-dir 2>/dev/null)" \
|| { echo "不在 git 仓库内"; exit 3; }
@@ -49,6 +50,11 @@ def undetermined(msg):
sys.exit(2)
def unknown(msg):
print("CI现查: 不可判 | commit %s | %s" % (short(base), msg))
sys.exit(2)
try:
s = get(api + "/commits/%s/status" % base)
except urllib.error.HTTPError as e:
@@ -59,7 +65,7 @@ except Exception as e:
statuses = s.get("statuses") or []
target = next((x.get("target_url", "") for x in statuses if x.get("target_url")), "")
if not statuses:
undetermined("远端无该提交的任务——零触发批(纯闸件/管线批不建任务),或推送未触发 CI")
undetermined("远端无该提交的 status——该批没推上去(或推的不是 master);零触发批有 run,走 run 侧读数")
m = re.search(r"/actions/runs/(\d+)", target or "")
if not m:
@@ -75,20 +81,32 @@ rstatus, rconclusion = run.get("status"), run.get("conclusion")
if rstatus != "completed":
undetermined("run %s status=%s(runner 需开机在线;队列与日志见 %s/actions)" % (run_id, rstatus, web))
try:
jobs = get(api + "/actions/runs/%s/jobs" % run_id).get("jobs", []) or []
except Exception as e:
unknown("查 run %s 的 job 明细失败:%s——取不到步级读数就不下绿" % (run_id, e))
gate_steps = [x.get("conclusion") for j in jobs for x in (j.get("steps") or []) if "跑闸" in (x.get("name") or "")]
if rconclusion == "success":
print("CI现查: 绿 | commit %s | run %s conclusion=success" % (short(base), run_id))
if not jobs:
unknown("run %s conclusion=success 但 job 列表为空,无法确认闸是否真跑" % run_id)
if not gate_steps:
unknown("run %s 里没有「跑闸」步——工作流结构已改,本件的步级判据需随动(查 %s/actions/runs/%s)" % (run_id, web, run_id))
if all(c == "skipped" for c in gate_steps):
print("CI现查: 未验 | commit %s | run %s conclusion=success 但跑闸步全为 skipped——零触发批,远端一条闸都没跑" % (short(base), run_id))
sys.exit(4)
print("CI现查: 绿 | commit %s | run %s conclusion=success,跑闸步 %d 条真跑过(闸况明细查 job 日志)" % (short(base), run_id, len(gate_steps)))
sys.exit(0)
red_jobs = []
try:
jobs = get(api + "/actions/runs/%s/jobs" % run_id)
for j in jobs.get("jobs", []):
if j.get("conclusion") in ("success", "skipped", None):
continue
bad_steps = [x.get("name") for x in (j.get("steps") or []) if x.get("conclusion") not in ("success", "skipped")]
red_jobs.append((j.get("name"), bad_steps))
except Exception as e:
red_jobs.append(("<job明细获取失败:%s>" % e, []))
for j in jobs:
if j.get("conclusion") in ("success", "skipped", None):
continue
bad_steps = [x.get("name") for x in (j.get("steps") or []) if x.get("conclusion") not in ("success", "skipped")]
red_jobs.append((j.get("name"), bad_steps))
if not red_jobs:
red_jobs.append(("<job 全为成功或跳过——conclusion=%s 与步级读数矛盾,取日志核对>" % rconclusion, []))
print("CI现查: 红 | commit %s | run %s conclusion=%s" % (short(base), run_id, rconclusion))
for name, steps in red_jobs: