T3 Code CI质量门槛全解:typecheck、lint、test如何在PR上层层把关(完整指南)
【免费下载链接】t3code项目地址: https://gitcode.com/GitHub_Trending/t3/t3code
T3 Code 是一个开源的"Agent 驾驶舱",让你通过手机、Web 和桌面端远程控制本机的 Claude、Codex、Cursor 等编码 Agent。它的代码质量完全交给一套严格的 CI 流水线:每一次 Pull Request(PR)都要依次闯过Check(格式 + lint + typecheck)、Test(全仓测试)、Rust 检查、移动端静态分析和Release Smoke五道关卡,全部绿灯才能合入。本文将带你逐层拆解这套 CI 质量门槛是如何工作的。
T3 Code 是什么?先看产品全貌
对新手来说,可以先直观认识一下这个项目。下图是 T3 Code 桌面端的运行界面:左侧是项目与任务列表,右侧是 Agent 的执行过程与代码变更,底部是发送指令的输入框。
而下图展示了 Agent 完成一轮修改后的"代码总览":变更文件树、逐文件的增删行数(+31/-17)以及 "View diff" 入口——这正是 CI 中各个质量门槛最终守护的对象。
CI 总入口:ci.yml 的触发时机与全局约定
整条质量流水线定义在 ci.yml 中,触发条件有两个:
- 任何PR提交(
pull_request) - 推送到main 分支(
push)
两个值得注意的工程细节:
- 并发去重:同一 PR 的多次提交会复用同一个并发组(
ci-${PR编号}),旧运行会被自动取消,避免排队浪费。 - 精简检出:所有 Job 都使用 sparse-checkout 排除
.repos/目录,减少无关文件的检出开销。
官方文档对这套门槛有简洁的总结,可参考 docs/internals/ci.md。
第一道关:Check —— 格式化、lint 与 typecheck
Check Job 是 PR 的第一道过滤网,运行在 8 核 Linux 上,限时的 10 分钟内要完成以下动作(见 ci.yml#L45-L58):
| 步骤 | 命令 | 作用 |
|---|---|---|
| 安装依赖 | vp(Vite+ 工具链) | 基于根package.json锁定 Node 版本并安装 |
| 准备 Electron | vp run --filter @t3tools/desktop ensure:electron | 下载桌面端所需的 Electron 运行时 |
| 格式 + lint | vp check | 格式化检查与 lint 规则校验 |
| 类型检查 | vpr typecheck | 整个 monorepo 的类型检查 |
| 构建桌面端 | vp run build:desktop | 提前暴露构建问题 |
| 校验 preload 包 | node apps/desktop/scripts/verify-preload-bundle.mjs | 确保 Electron 沙箱可以安全加载 preload 脚本 |
其中 lint 规则集中在根目录的 vite.config.ts:它启用了 eslint、oxc、react、unicorn、typescript 五类插件,还挂载了项目自研的 oxlint-plugin-t3code/ 规则包,包含 6 条业务自定义规则(例如t3code/no-global-process-runtime禁止全局 process 运行时、t3code/namespace-node-imports规范 Node 导入方式)。类型检查则单独由vpr typecheck承担,与 lint 解耦——这种分工让每类问题的反馈更聚焦。
第二道关:Test —— 全仓测试 + Server 分片并行
测试被拆成两个 Job,各有讲究:
- Test Job:运行
vp run --parallel --filter '!t3' test,覆盖除apps/server之外的全部 workspace,并行度限制为 4,让各包测试在 runner 上同时跑。 - Test Server Job:
apps/server开启了严格的单文件串行模式(fileParallelism: false),239 个测试文件如果串行会太慢,所以 CI 用--shard 1/3、2/3、3/3把它切成3 个分片,分到 3 台独立 runner 上跑,既保住隔离性又压缩总时长。
Server 测试还有一个彩蛋:某个测试文件会生成"线程迁移传输预算报告"(Transfer Budget Report),CI 检测到报告后会自动追加到 Job Summary 并上传为 artifact,方便维护者跨 PR 观察性能预算的变化。
第三道关:Rust 与移动端原生静态分析
这个项目并非纯 TypeScript,还有两处容易被忽略的原生代码:
- Rust Job:对 native/resource-monitor/ 执行
cargo fmt --check和cargo test --locked。它被单独拆出来,是因为在 Check/Test 的关键路径上装 Rust 工具链每次要多花 7~9 秒。 - 移动端原生检查:iOS 的 Swift 与 Android 的 Kotlin 源码需要 SwiftLint / detekt / ktlint 检查,而这必须跑在付费约 6.7 倍于 Linux 的 macOS runner上。于是 CI 设计了一个廉价的 Linux 门禁 Job(
mobile_native_changes):先只查 API 获取 PR 变更文件列表,只有当 diff 真正碰到apps/mobile下的 Swift/Kotlin 源文件、lint 配置或 scripts/mobile-native-static-check.ts 时,才启动 macOS runner 跑vp run lint:mobile。门禁采用"失败即放行检查"(fail-open)策略——只要变更文件列表解析失败或被截断,就直接执行 lint,宁可多花钱也不漏检。
第四道关:Release Smoke —— 让发布事故提前暴露在 PR 上
最巧妙的一道关是 release_smoke Job:它执行 scripts/release-smoke.ts,在一个临时目录里复制 workspace 清单文件,然后真实演练"发布前"的脚本流程——批量改写各包版本号、重算 lockfile、推导 nightly 版本号、合并 macOS/Windows 的更新清单。也就是说,只会在打 tag 时才跑的发布逻辑,每次 PR 都会先彩排一遍,发布流程的 bug 能在 PR 阶段就暴露,而不是等到正式发布时才炸。
外围防线:PR Size 标签与 Vouch 机制
质量把关不止发生在 CI 内部,仓库还用两个辅助 workflow 约束 PR 文化:
- pr-size.yml:自动统计 PR 的有效改动行数(混合 PR 中排除测试文件),打上
size:XS到size:XXL六级标签。这呼应了 PR 模板 中的告诫——小而有焦点的 PR 更受欢迎,上千行的大 PR 大概率会被拒。 - pr-vouch.yml:为提交人提供"担保"(vouch)标签,帮助维护者快速判断陌生贡献者的可信度,支持
/recheck-vouch重新校验。
合入之后:release.yml 发布流水线
当代码带着绿灯合入 main 并打上一个v*.*.*标签后,release.yml 会构建 macOS(arm64 + x64)、Linux(x64)、Windows(x64)三平台的桌面端安装包并发布。签名凭证存在时才自动启用签名(macOS 需要 Apple 团队与描述文件,Windows 走 Azure Trusted Signing);缺少凭证时仍会发布未签名产物,保证发布不中断。
小结:五道门槛的分工一览
| 门槛 | 守护对象 | 核心命令 |
|---|---|---|
| Check | 格式、lint、类型、桌面端构建 | vp check+vpr typecheck |
| Test | 业务逻辑正确性 | vp run test(Server 3 分片) |
| Rust | 原生资源监控模块 | cargo fmt+cargo test |
| Mobile Native | Swift/Kotlin 源码质量 | vp run lint:mobile(按需触发) |
| Release Smoke | 发布流程本身 | release-smoke.ts |
这套 CI 的设计哲学可以概括为三点:检查与测试分离(问题定位更快)、昂贵资源按需触发(macOS runner 只在需要时启动)、发布流程前置演练(Smoke 让事故左移)。对新手而言,这也是一个优秀的工程参考:如果你的开源项目也想给 PR 加上层层把关的质量门槛,T3 Code 的 ci.yml 几乎可以直接抄作业。
【免费下载链接】t3code项目地址: https://gitcode.com/GitHub_Trending/t3/t3code
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考