跳到主内容
@wquguru
精选85Irrational Exuberance(Will Larson · RSS)组织与管理

Imprint通过small-change机制将PR审查提速10倍

Speeding up code review with `small-change`

原文
发到 X
推荐理由

给出具体的工程流程参数与判据,独立开发者或小团队可直接参考其自动化审查与分级管理的思路来优化协作效率。

Imprint’s average engineer is merging 4x more PRs than 2 years ago. Yay. Aggregated behind the average is something even more interesting: we have two teams that are merging 10x their PRs over that period. One engineer is merging 25x the PRs per week of our average engineer two years ago, and a number are merging 10x. That’s pretty neat, and the slope of the line suggests our average in a year is going to look much closer to today’s p90 than today’s p50. Even more importantly, we aren’t just shipping more, our quality has improved: incidents are down 42% half-over-half, and critical incidents are down 78% half-over-half. I think we’ve always known the quality/velocity tradeoff wasn’t a particularly useful construct, but that’s undeniable today.

Imprint 的平均工程师合并的 PR 数量是两年前的 4 倍。太棒了。在平均值背后隐藏着更有趣的数据:有两个团队在此期间合并的 PR 数量是其原来的 10 倍。有一位工程师每周合并的 PR 数量是两年前我们平均工程师的 25 倍,还有多位工程师达到了 10 倍。这非常棒,且曲线的斜率表明,一年后的平均水平将更接近今天的 p90,而非今天的 p50。更重要的是,我们不仅交付量增加了,质量也有所提升:事故数量环比下降 42%,严重事故数量环比下降 78%。我想我们一直都知道质量与速度的权衡并非一个特别有用的概念,但今天这一点已是不争的事实。

As we’ve walked this path, we–like everyone else progressing down it–have run into the problem of pull request review. The p50 pull request review took about 33 minutes to complete 2 years ago, but now takes us about 77 minutes. The slope here correlates tightly with the number of pull requests getting merged. Tightly enough that addressing it became one of my priorities for the week.

在这条道路上前行时,我们——和其他沿着这条路前进的人一样——遇到了拉取请求(pull request)审查的问题。两年前,中位数拉取请求审查耗时约 33 分钟完成,而现在则需要约 77 分钟。这里的斜率与合并的拉取请求数量紧密相关。相关性之高,使得解决这一问题成为我本周优先事项之一。

We solved it! Just kidding, we’ve absolutely not solved it, but I think our current approach is an interesting one, which we call the small-change.

我们解决了它!开玩笑的,我们绝对没有解决它,但我认为我们目前的方法很有趣,我们称之为“小变更”(small-change)。

The work discussed here was shaped and done by many folks at Imprint including Dan, Joy, Daniel, Lenny, Taylor, Ted, and Annie, among many others.

本文讨论的工作由 Imprint 的许多同事共同塑造和完成,包括 Dan、Joy、Daniel、Lenny、Taylor、Ted 和 Annie 等,以及众多其他人。

Why review pull requests?

为什么要审查拉取请求?

There are four reasons we review pull requests:

我们审查拉取请求有四个原因:

  • Knowledge sharing between author and reviewer – software engineering is generally learned via apprenticeship, and reviews are a primary mechanism of experienced engineers teaching others what good software looks like. We believe the current volume means that this knowledge sharing will have to move towards operating on clusters of pull requests, rather than individual pull requests
  • Preventing errors – review has always been an expensive time to catch errors, and we believe that effective CICD along with harness verification techniques like poteto’s pstack are more effective mechanisms for preventing errors than review
  • Preventing malicious behavior – my experience is that even careful code review will generally miss competent malicious behavior, although fortunately most malicious behavior is incompetent. We believe both sorts of behavior are best identified using a combination of fixed rules (modifying these specific objects/classes/files requires review), anti-abuse mechanisms that we’ve refined in our LLM-based member support experiences, auditing, and audit log inspection
  • Compliance obligations in our documented controls – these can be changed, but today they require that an independent human reviews changes in a subset of our repositories
  • 作者与审查者之间的知识共享——软件工程通常通过学徒制学习,而审查是有经验的工程师向他人展示优秀软件样貌的主要机制。我们认为,当前的审查量意味着这种知识共享将不得不转向基于拉取请求集群进行操作,而不是针对单个拉取请求。
  • 防止错误——审查一直是发现昂贵错误的环节,我们认为有效的 CI/CD 结合像 poteto 的 pstack 这样的验证技术,是比审查更有效的防止错误的机制。
  • 防止恶意行为——我的经验是,即使经过仔细的代码审查,通常也会漏掉有能力的恶意行为,尽管幸运的是大多数恶意行为都是无能的。我们认为,这两类行为最好通过结合固定规则(修改这些特定对象/类/文件需要审查)、在我们基于 LLM 的成员支持经验中不断优化的反滥用机制、审计以及审计日志检查来识别。
  • 我们文档化控制措施中的合规义务——这些可以更改,但今天它们要求由独立的人工对部分仓库中的更改进行审查。

In the modern development paradigm, we think there is a better solution for each of these problems. But, we also want to make these changes very cautiously.

在现代开发范式中,我们认为针对这些问题有更好的解决方案。但是,我们也希望非常谨慎地进行这些更改。

Small steps with small-change

小步前进,微小变更

We believe we move fast by finding narrow, contained ways to validate new practices, so to iterate our way into an effective solution, we’ve developed the concept of a small-change. Here’s how it works:

我们相信,通过找到狭窄且受限的方式来验证新实践,我们可以快速推进,因此为了迭代出有效的解决方案,我们提出了“微小变更”的概念。其工作原理如下:

  • When a pull request is marked ready, CICD determines whether it is eligible to be a small-change. This is represented as a passing Github check. There is also a label for visibility, but it is the check itself, managed by the build and not human modifiable, that determines eligibility. (The label is used for initial filtering, but the check is still independently verified.)
  • Something is a small-change if it meets all of these criteria:
  • It is less than 1,000 lines of code
  • There are no p1 or p2 findings from our ai-code-review automated review bot
  • The author has “experience” in the service or application, defined as 10+ prior merged pull requests into that service or application’s directories. For changes working across multiple services or applications, the author must have experience in all of them to qualify
  • Impacts fewer than N distinct services or applications. N is 1 on our frontend monorepo, and N is 3 in our backend monorepo, where typical changes will modify both a gRPC service and a common HTTP gateway
  • Shared libraries and utilities files are not eligible for small-change
  • Each repository has a .small_change file which allows per-path customization while we continue to tune the behaviors. For example, a service dealing with money movement can be excluded
  • Our Slack automation tags every reference to a pull request with reacji labeling the state of that pull request, for example if it has failing tests, if it has been approved but tests are still running, or if it is ready to merge. We added a small-change reacji that indicates which of those pull requests meet the small-change criteria
  • In our internal skills repository, we created two skills that have been distributed across harnesses:
  • review-small-change which takes a list of repositories and reviews all open, non-draft, small-changes, including providing approval if they meet the review’s criteria (all checks pass including small-change check, and not touching on sensitive topics such as payments and security).
  • Importantly, this skill has only two options: approve or ignore. It never comments on the PR to avoid the proliferation of “meat proxy review” which has become a bottleneck-pretending-to-be-a-solution on some teams
  • review-pr-cluster which reviews batches of pull requests to identify common themes that came up, and suggest opportunities for discussion and adding verifications
  • We set the social expectation that any error caused by a small-change is a failure in our system, and has to be solved at the system level: improvements to ai-code-review, to our verification mechanisms, to our CICD, to our harness, etc.
  • 当拉取请求被标记为就绪时,CICD 会判断其是否有资格成为微小变更。这表现为一个通过的 Github 检查。还有一个用于可见性的标签,但决定资格的是构建管理的检查本身,而非人工可修改的标签。(该标签用于初始过滤,但检查仍会独立验证。)
  • 如果满足以下所有条件,则视为微小变更:
  • 代码行数少于 1,000 行
  • 我们的 ai-code-review 自动化审查机器人没有产生 p1 或 p2 级别的问题发现
  • 作者在相关服务或应用中具有“经验”,定义为在该服务或应用目录中有 10+ 次已合并的拉取请求。对于跨多个服务或应用的更改,作者必须在所有这些服务或应用中都有经验才有资格
  • 影响少于 N 个独立的服务或应用。在前端 monorepo 中 N 为 1,在后端 monorepo 中 N 为 3,其中典型更改将同时修改 gRPC 服务和通用 HTTP 网关
  • 共享库和工具文件不符合微小变更的资格
  • 每个仓库都有一个 .small_change 文件,允许在继续调整行为的同时进行每路径定制。例如,处理资金流动的服务可以被排除在外
  • 我们的 Slack 自动化将每个对拉取请求(pull request)的引用标记为 reacji,以标注该拉取请求的状态,例如:如果测试失败、如果已获批准但测试仍在运行,或者如果已准备好合并。我们添加了一个小型变更 reacji,用于指示哪些拉取请求符合小型变更标准
  • 在我们的内部技能库中,我们创建了两个已分发到 harnesses 的技能:
  • review-small-change:接收一个仓库列表,并审查所有开放的、非草稿状态的小型变更,包括在它们符合审查标准时提供批准(所有检查均通过,包括小型变更检查,且不涉及支付和安全等敏感主题)。
  • 重要的是,此技能只有两个选项:批准或忽略。它永远不会在 PR 上发表评论,以避免“肉代理审查”(meat proxy review)的泛滥,后者在一些团队中已成为一种伪装成解决方案的瓶颈
  • review-pr-cluster:审查一批拉取请求,以识别出现的共同主题,并提出讨论和添加验证的机会
  • 我们确立了这样的社会期望:任何由小型变更引起的错误都是我们系统的失败,必须在系统层面解决:改进 ai-code-review、我们的验证机制、CI/CD、我们的 harness 等。

This took about two days of infrequent attention to implement and rollout, although I imagine we will be tuning the knobs here for a long time. Maybe forever.

实施和部署这项工作大约花费了两天时间,且只需偶尔关注,尽管我想象我们会长期调整这里的参数。也许永远如此。

Meat proxy review

肉代理审查

I mentioned this in 4.1 above, but meat proxy review has become an interesting bottleneck for many teams. It’s a particularly difficult bottleneck because it initially looks like a solution, but it makes things worse. The pattern is roughly:

我在上面的 4.1 节中提到过这一点,但肉代理审查已成为许多团队的一个有趣瓶颈。这是一个特别困难的瓶颈,因为它起初看起来像是一个解决方案,但实际上会让情况变得更糟。大致模式如下:

  • Team is overwhelmed with reviews
  • Team decides to review pull requests with their local harness
  • Pull requests get a large number of comments, some of which make sense, and some of which don’t. It’s unclear which is which without study, and you don’t know which comments reflect the reviewer’s point of view. So you end up having to do substantial work to disprove comments that the reviewer may not even agree with
  • Those teams then start using harnesses to respond to the harness-generated comments, making the entire review process an illusion that doesn’t facilitate learning, and most importantly could be done without the involvement of the other team members
  • 团队被审查任务压得喘不过气
  • 团队决定使用本地 harness 来审查拉取请求
  • 拉取请求收到大量评论,其中一些有道理,另一些则没有。如果不深入研究,很难分清哪些是有道理的,而且你也不知道哪些评论反映了审查者的观点。因此,你最终不得不投入大量工作去反驳那些审查者可能甚至不同意的评论
  • 这些团队随后开始使用 harnesses 来回应由 harness 生成的评论,使得整个审查过程成为一种不促进学习的幻觉,最重要的是,整个过程无需其他团队成员参与即可完成

In every case that meat proxy review is performed, the team would get better outcomes by investing into the centralized review mechanism, the harness’ loop for addressing the centralized review’s feedback, and simply stamping approval.

在每次执行肉类代理审查(meat proxy review)的情况下,团队通过投资集中式审查机制、用于处理集中式审查反馈的 harness 循环,以及简单地盖章批准,都能获得更好的结果。

fleet: centrally orchestrated harness

fleet:集中编排的 harness

I’ll briefly mention our other approach to reducing code review volume, which anchors on our centrally-orchestrated harness, fleet. (Which is similar to Stripe’s Minions although not following the one-shot approach in particular). We rely on fleet to implement and verify software in a highly controlled harness running in the cloud, with independent evaluation mechanisms to identify the correct number of independent reviewers for any given change. That number can be as low as one (e.g. fleet writes, one human reviews) for changes evaluated as safe.

我将简要提及我们减少代码审查量的另一种方法,该方法以我们集中编排的 harness fleet 为基础。(这与 Stripe 的 Minions 类似,尽管并未特别遵循一次性方法)。我们依赖 fleet 在云端运行的高度受控 harness 中实施和验证软件,并拥有独立的评估机制,以确定任何给定变更所需的独立审查者数量。对于被评估为安全的变更,该数量可能低至一人(例如,fleet 编写代码,一名人类进行审查)。

Results / next steps / reception

结果 / 后续步骤 / 反响

更进一步:量化金融体系

看懂新闻只是起点——沿量化金融路径,把它变成能交付的工程能力

进入量化体系 →

相似阅读

关联信息,但可能不是同一事件