CI: 将全部 7 套测试纳入 gate;修复 e2e 退出竞态

回应事后审计:此前 CI 只跑 3 套(contract/merge-smoke/workflow-e2e),新增的 4 套
(contract-events/benchmark-metrics/benchmark-collector/baseline-comparison)未进入 gate,
PR 描述「七套全绿」与 CI 实跑不符。本提交把 4 套补入 ci.yml。

同时修复 test-workflow-e2e:进程退出时 uvicorn 守护线程仍在写 stderr,导致解释器收尾
出现 Fatal Python error(exit 127,CI 偶发失败)。改为 join 服务线程 + os._exit(code),
退出码确定(本地 e2e 连跑 3 次均 exit 0、断言全过)。

注意:本 PR 仅修 CI 门禁与 e2e 稳定性,**不构成 Benchmark/主链路验收**;Issue #2 保持 open。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Songhaoz666
2026-06-09 17:33:05 +08:00
co-authored by Claude Opus 4.8
parent 6bed064117
commit 6e0eca4da7
2 changed files with 28 additions and 4 deletions
+12 -4
View File
@@ -68,7 +68,8 @@ async def main():
config = uvicorn.Config(orch.app, host="127.0.0.1", port=PORT, log_level="warning")
server = uvicorn.Server(config)
server.install_signal_handlers = lambda: None # required when not on the main thread
threading.Thread(target=server.run, daemon=True).start()
server_thread = threading.Thread(target=server.run, daemon=True)
server_thread.start()
agent = StubAgent(WS, "stub-1", [
"python", "code_generation", "testing", "pytest", "technical-writing", "general",
@@ -78,7 +79,7 @@ async def main():
async with httpx.AsyncClient(timeout=10) as client:
if not await wait_health(client):
check("orchestrator started", False)
return
return 1
agent_task = asyncio.create_task(agent.run())
await asyncio.sleep(0.5) # let the agent register
@@ -120,13 +121,20 @@ async def main():
if agent_task:
agent_task.cancel()
server.should_exit = True
server_thread.join(timeout=5) # let uvicorn stop so no daemon thread lingers at exit
print()
if failures:
print(f"{len(failures)} workflow check(s) FAILED: {failures}")
sys.exit(1)
return 1
print("workflow follows the expected sequence: decompose -> dispatch -> execute -> review/iterate -> synthesize")
return 0
if __name__ == "__main__":
asyncio.run(main())
# os._exit after flushing avoids a Fatal Python error if the uvicorn daemon thread is still
# finalizing (writing to stderr) at interpreter shutdown — guarantees a deterministic exit code.
_code = asyncio.run(main())
sys.stdout.flush()
sys.stderr.flush()
os._exit(_code or 0)