指南 · Orbi 的 CI 门禁如何工作 · 引擎源码核实于 2026-09-12
CI 里放什么,Orbi 就保证什么
Orbi 的两道门禁——评审门禁和发版门禁——只读一样东西:每个 GitHub check run 的 conclusion。它们不认识 pytest,也不认识 Playwright:success、neutral、skipped 放行,其余一律拦下。所以你在 CI 里放什么测试,Orbi 就在每次交付里替你保证什么——而一个 check run 都没有时,两道门禁都放行,这是下文的第一条边界。这一页给出机制、两份可直接复制的 workflow、四条边界,每条都能指回引擎源码。
机制
两道门禁,一个输入:check run 的 conclusion
评审门禁在合并之前用 PR head 的 check run 把守;发版门禁在冻结 SHA、打 Tag 之前用发版 commit 的 check run 把守。两处都向 GitHub Checks API 查询该 commit 的 check run,然后只看 conclusion 字段决定放行还是拦下。以下代码逐字引自交付引擎 src/orbi/runner.py(check_review_ci)与 src/orbi/release.py(check_release_gates):
failed = [
check for check in check_runs
if check.get("conclusion") not in ("success", "neutral", "skipped")
]
if failed:
check = failed[0]
reference = check.get("html_url") or check.get("details_url") or "no run URL"
raise RuntimeError(
f"review gate: CI check '{check.get('name')}' failed on PR head "
f"{commit} ({reference})"
)
if not check_runs:
evidence = f"CI on review head {commit}: no check runs (nothing to gate)"
for check in check_runs:
name = check.get("name")
status = check.get("status")
conclusion = check.get("conclusion")
if status != "completed" or conclusion not in (
"success", "neutral", "skipped",
):
raise RuntimeError(
f"release gate: CI check '{name}' is {status}/{conclusion} "
f"on the release commit {release_commit}"
)
两段均逐字引用,核实于 2026-09-12。pending 的 check 不会被提前判定:两道门禁都会轮询到每个 check 跑完为止,等待超出预算则门禁失败——排队的测试是拦下,不是放行。conclusion 的取值是 GitHub 自己的枚举(Checks API):success, failure, neutral, cancelled, skipped, timed_out, action_required, stale;门禁的通过集是其中子集 success, neutral, skipped。
门禁看不见测试名、看不见框架、也看不见覆盖率数字。它看到的只是每个 check run 的一位信息——过或不过。所以定义「保证」的是你 CI 里的内容,不是 Orbi。
Orbi 因此保证什么
你的测试决定「保证」二字的意思
门禁保证的是 CI 里已有的验证——不会更多,也不会更少。层级是叠加的:每加一层,绿色交付能证明的就更多。
| CI 里放了什么 | Orbi 于是每次交付都保证什么 |
|---|---|
| 只有单测 | 这些单测覆盖到的代码逻辑是对的。破坏它们的交付合不进来——这就是全部的保证。 |
| + 集成测试 | 模块在集成测试覆盖到的边界上也能对得上。 |
| + 业务流程 e2e(Playwright) | 业务闭环是通的。用户真实跑的那条流程——打开应用、做完操作、看到结果——每次交付都会被真实执行并通过。 |
放 pytest 单测,Orbi 保证代码逻辑正确;放 Playwright 业务流程 e2e,Orbi 保证业务闭环是通的。这不是修辞——就是上面代码的字面含义。
复制即用
两份完整 workflow,可直接提交
完整文件,不是片段——任何一份都是完整的 .github/workflows/*.yml。都在 pull_request(让评审门禁看到 PR head)和 push 到交付分支(让发版门禁看到发版 commit)时触发。push.branches 必须包含 Orbi 交付的分支;Playwright 那份假设你的 playwright.config 自己拉起应用(webServer)——那部分以 Playwright 官方文档为准。
name: CI
on:
pull_request:
push:
branches: [main]
jobs:
tests:
name: pytest
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip
- run: pip install -r requirements.txt
- run: pytest
name: E2E
on:
pull_request:
push:
branches: [main]
jobs:
e2e:
name: playwright
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npx playwright install --with-deps chromium
- run: npx playwright test
从下一次交付开始,Orbi 会在每个 PR head 和每个发版 commit 上检查这些 check run——红了就拒绝 merge、拒绝打 Tag。每次交付跑这些测试花多少钱是实测过的,不是估的:成本页给出均值约 $0.06–0.12(DeepSeek 牌价)。
先读边界
这一页不承诺的四件事
-
边界一 · 无 CI 时放行
一个 check run 都没有,两道门禁都放行
没有 CI 的仓库能跑通整个交付流程。引擎的证据行说得很直白:
no check runs (nothing to gate)。什么都不会被拦下——什么也不会被验证,因为唯一的自动化验收闸门根本没有装。一个细节,同一段代码:已知有 CI 的仓库(冻结 base 上出现过 check)刚 push 的发版 commit 上列表为空时,含义是「还没注册」,门禁会等第一个 check 出现,而不是放行。fail-open 只属于完全没有 CI 的仓库,不属于还没来得及说话的 CI。 -
边界二 · 跳过 ≠ 跑过
neutral 和 skipped 同样算通过
通过集字面上就是
success, neutral, skipped。被if:条件跳过的 e2e job、被paths:过滤掉的 workflow,conclusion 是skipped——不会拦住合并。没跑的 job 就是没失败的 job。把触发器指向对的路径,别给合并依赖的 job 挂条件。 -
边界三 · 测试是 agent 自己写的
覆盖率证明测试碰过这些代码,不证明代码做对了业务
写功能的是同一个 agent,写测试的也是它。Playwright 能证明按钮渲染出来了、点了有反应;证明不了按钮该不该放在那个屏幕上,也证明不了报错文案够不够温和。小的 UX 偏差正是这些门禁抓不住的——对手感做判断的仍然是人,绿色 check run 不是 UX 签收。
-
边界四 · 进度展示的已知限制
进度评论里的测试数字是 pytest 专属
交付进度评论里的
tests passed / tests failed一行来自解析仓库的测试日志,解析器按 pytest 的总结行(1 failed, 155 passed in 4.43s)调校。Playwright 的总结行不会被解析出数字,非 Python 仓库可能完全不显示这一行。这只是进度展示的已知限制,不是门禁行为:门禁只看 check run,从不读测试日志。
出处
来源与核实日期
本页每一条引擎行为声明都在 2026-09-12 对照交付引擎源码核实过——引的是代码原文,不是文档转述。
-
orbi-build/orbi — src/orbi/runner.py,
check_review_ci— 评审门禁:通过集success/neutral/skipped,任一 check 失败即抛错,无 check run 记为 “nothing to gate” 核实于 2026-09-12 github.com/orbi-build/orbi -
orbi-build/orbi — src/orbi/release.py,
check_release_gates— 发版门禁:同样的 conclusion 判定、已知有 CI 仓库的等注册逻辑、以及 “nothing to gate” 证据行 核实于 2026-09-12 github.com/orbi-build/orbi -
GitHub Checks API — check runs — 门禁过滤的
conclusion枚举 核实于 2026-09-12 docs.github.com -
orbi-build/orbi — src/orbi/runner.py,
read_test_result— pytest 专属的进度评论解析器(边界四) 核实于 2026-09-12 github.com/orbi-build/orbi
一次提交之外
装上你想让 Orbi 保证的那道闸
选好你想保证的那一层——逻辑、集成、还是业务闭环——把对应的测试放进 CI。从下一次交付开始,Orbi 会在每个 PR head 和每个发版 commit 上检查它,红了就拒绝 merge、拒绝打 Tag。