指南 · Orbi 的 CI 门禁如何工作 · 引擎源码核实于 2026-09-12

CI 里放什么,Orbi 就保证什么

Orbi 的两道门禁——评审门禁和发版门禁——只读一样东西:每个 GitHub check run 的 conclusion。它们不认识 pytest,也不认识 Playwright:successneutralskipped 放行,其余一律拦下。所以你在 CI 里放什么测试,Orbi 就在每次交付里替你保证什么——而一个 check run 都没有时,两道门禁都放行,这是下文的第一条边界。这一页给出机制、两份可直接复制的 workflow、四条边界,每条都能指回引擎源码。

Is your Issue ai-ready? The 12 factors

两道门禁,一个输入:check run 的 conclusion

评审门禁在合并之前用 PR head 的 check run 把守;发版门禁在冻结 SHA、打 Tag 之前用发版 commit 的 check run 把守。两处都向 GitHub Checks API 查询该 commit 的 check run,然后只看 conclusion 字段决定放行还是拦下。以下代码逐字引自交付引擎 src/orbi/runner.pycheck_review_ci)与 src/orbi/release.pycheck_release_gates):

src/orbi/runner.py — check_review_ci(评审门禁)
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)"
src/orbi/release.py — check_release_gates(发版门禁)
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。

你的测试决定「保证」二字的意思

门禁保证的是 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 官方文档为准。

.github/workflows/ci.yml — pytest
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
.github/workflows/e2e.yml — Playwright 业务流程
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 保证的那道闸

选好你想保证的那一层——逻辑、集成、还是业务闭环——把对应的测试放进 CI。从下一次交付开始,Orbi 会在每个 PR head 和每个发版 commit 上检查它,红了就拒绝 merge、拒绝打 Tag。