← 文章 / 云原生与基础设施
nx 1天前 · 2026-10-05 04:03:28 · 8 阅读

Legora 如何使持续集成维护成本减半

Legora 是面向法律工作的 agentic 操作系统,帮助律师在复杂案件中完成研究、审查和起草。目前已有 50 多个市场、1800 多家顶尖律所和企业法务团队的超过 10 万名法律专业人士在使用它。工程规模也在同步扩张:monorepo 一年内几乎翻倍,项目数超过 600 个,月度 CI 运行次数增长了六倍——而支撑这一切的平台团队只有三个人。他们的 monorepo 基于 Nx,主要使用 TypeScript,同时包含 43 个 Python 项目、一个 Rust crate、一个 Java 服务和 protobuf 校验,全部在一条 Nx Agents 流水线中运行。

挑战

Legora 的发展速度超出了原有 CI 架构的承载能力。当时的检查任务通过 GitHub Actions 矩阵在 Blacksmith 上运行,每个检查使用固定的 runner 规格,分片靠手工配置(功能测试 2x、验收测试 6x)。这套方案在团队规模较小时还很合适,但工作流代码在 2026 年 3 月到 5 月间从 94 行膨胀到了 621 行。仅 6 月,独立 PR 数量就增长了 35%,静态矩阵模式不仅用起来麻烦,随着公司扩张还越来越难维护。对三人的平台团队来说,手动调优成了日益沉重的负担——因为新增项目后没有任何机制自动重新平衡。团队的首要目标是稳定性:先确保快速扩张的工程组织能信任自己的流水线,再去优化其他东西。

此外,对缓存的信任也是一大障碍。到春季,团队已经禁用了生产构建的缓存,还自己写了一个校验工具——绕过缓存重新构建并对比输出校验和,因为缓存构建和全新构建的结果偶尔会不一致。

解决方案

Nx Cloud 的 task sandboxing 用每个任务实际读写文件的追踪记录取代了这种猜测。第一次完整运行就标记出 968 个任务中的 811 个存在沙箱违规。大约六周后,团队把沙箱违规清零,并首次启用了严格模式。到 6 月中旬,缓存命中率在两周内从约 50% 提升到了 73%。

我的目标就是把沙箱违规降到 0,这样才能真正信任缓存。没想到的是,这个过程还暴露出了许多其他问题:配置在悄悄互相覆盖、inputs 存在隐蔽的错误。整个仓库在这之后都变得更健康、更快了。

Sofie Thorsen,Legora 技术团队成员

随后,Legora 将核心代码检查迁移到 Nx Agents:构建、类型检查、Lint、单元测试、功能测试和验收测试这些受影响任务的扩展分布,全部运行在团队已作为远程缓存使用的 Nx Cloud 租户上。随之消失的,是那个曾经需要手工维护的、将每项检查绑定到特定 Runner 的矩阵。

需要维护的工作流配置减少了一半,而且对于分布式检查,省去了 Blacksmith 所需的手动分片、按检查项设定 Runner 规格以及必选检查的配置。随着项目的增加,系统会自动重新平衡,而 Blacksmith 则需要持续人工调优。

Sofie Thorsen,Legora 技术团队成员
Nx Agents 的工作原理

Nx Agents 的 分布式任务执行 (DTE) 是一个任务分发编排器,而非 Runner。它不会预先将特定检查分配给特定 Runner,而是持续地、按任务粒度决定由哪个 Agent 处理哪部分工作。Agent 池随时待命,每当有一个释放,它就立即领取队列中的下一个任务。没有预先确定的分片边界,也不需要手动将特定检查映射到特定规格的 Runner。

这种持续模型自带了几项好处。快速完成的任务不会等待较慢的关联任务,工作持续流向空闲的 Agent。分配规则会将高 CPU 或高内存的异常任务路由到合适的节点,避免在规格不足的 Agent 上引发内存溢出失败。当检测到任务不稳定(flaky)时,Nx 会在全新的机器上自动重试,而不是让整轮运行失败。任务沙箱机制强制隔离执行:追踪任务读写的所有文件,未声明的访问会导致任务失败,从而确保缓存结果与新构建不会悄悄产生差异。由于由 Nx Cloud 编排运行,它还会 捕获任务级利用率数据(每个任务的 CPU 和内存),用于调优和可视化,这是固定矩阵模型无法提供的。

随着代码库增长,上述机制无需重新调优:新项目和新测试直接汇入同一条持续流水线,无需人工调整分片数量或 Agent 规格。

能力编排仅 Runner
任务分配通过编排,当 Agent 空闲时自动持续分配任务静态的 GitHub Actions 矩阵,每个检查任务固定分配
机器分配根据变更规模动态调整机器资源每个检查任务使用固定大小的 Runner,需手动选择

效果

对于迁移到 Nx Agents 的检查项,CI 配置篇幅减少了一半,原本需要手动分片、手动为每个检查项指定 Runner 大小以及配置必需检查项的繁琐工作也彻底取消了。

我们的 Dx 团队只有三个人,因此 DTE 的动态持续分配机制比静态矩阵更适配我们这个规模的 monorepo,同时也消除了慢速分片导致其他节点空闲的问题。

Sofie ThorsenLegora 技术团队成员

DTE 工作流现在运行 16 个目标,涵盖 TypeScript、Python、Rust 和 Java,此外还包括 7 项全仓库级的护栏检查,而这些在 5 月份之前并不存在,包括:lockfile 漂移、生成文件同步、合规性规则、认证权限控制、翻译键检查、protobuf 兼容性验证以及 Temporal 代码包检查。所有这些功能所需的配置代码行数,比之前的矩阵模式更少。

联系我们的团队!正在寻找精简平台团队来扩展 monorepo 规模的解决方案?联系我们,了解更多关于 Nx Cloud 的信息。

原始来源: nx

评论 (0)