[译] DefinitelyTyped 的自动化管理改造

Posted on:  at 

原文地址:https://devblogs.microsoft.com/typescript/changes-to-how-we-manage-definitelytyped/
原文发布于:2020年5月29日

缩写定义
DT:Definitely Typed 仓库的缩写
PR:Pull Request 代码拉取请求的缩写

托管在 github 上的 Definitely Typed(下文统一简称DT)项目是 Github 年度 octoverse 报告 上的常客,是贡献者数最多的前十个仓库之一。如果你没有听说过 DT 的话,它是一个存储了成千上万个 JavaScript 项目的类型声明文件(.d.ts文件)仓库,并且你可能已经通过使用 @types/something 命名方式的模块来使用过这个仓库的产物了。

最开始完全由社区驱动的方式来进行的类型定义工作对 TypeScript 生态的作用变得越来越重要,以至于 TypeScript 团队承担起了主要的维护 DT 项目的工作。而 TypeScript 团队也非常认真的对待维护 DT 项目的职责,自 2016年年中 以来,团队实行这样的轮换制度:被轮换到的成员在一周时间内会专注于合并 PR 和 DT 项目的维护。我们和其他 DT 项目的维护者合作,每周处理约 250 个 PR 请求,直至上周,超过90%的请求都已经被处理了。

在过去的一年里,我们一直致力于开发配套的工具,为了在保证 DT 生态系统稳定性的同时,为维护者贡献代码提供更加精简的体验——定义作者现在可以自己将 PR 合并到他们的模块上了!

我们是怎么做到的?

我们为 DT 项目建立了一些保证安全性的手段,这为团队提供了更多系统稳健性方面的信心。

我们会对每一次变更执行性能和集成测试

性能检查会检查两点:

  • 该变化是否增加了编译文件时的内存使用;
  • 它们是否会减慢编辑器的操作,比如“转到定义”和代码补全。

性能很重要,因为我们看到过因为一个库的变化导致依赖它的模块的编译时间急剧增加的例子。通过在 PR 过程中提供有用的性能反馈,维护者可以了解性能变化并权衡这些变更的必要性。

集成测试会同时验证这两点:

  • 你导出的类型定义和使用 dts-critic 的 JavaScript 的类型定义导出能够大致相同。这能够让开发者对所定义的类型说明是否适配目标 JavaScript 模块更有自信。
  • 该改变不会破坏该类型定义库所依赖的下游依赖。

TypeScript 开发环境验证

TypeScript 的升级有可能会破坏你在 DT 中的类型定义。这可能是改进编译器控制流分析导致的,或者是通过修复一个不小心引入的依赖导致的。

TypeScript 开发团队不希望发布了一个新版本之后才发现它破坏了大量 DT 中的类型定义。目前有两个系统来防止这一情况。

第一个是我们简化了测试流程,能够使用开发中(WIP)的编译器对所有 DT 测试用例进行测试。如果新代码会导致 DT 中的报错,那么这个编译器 mr 的作者有责任在 mr 被合并之前在 DT 这边进行相关修复。

第二个是 DT 每晚都会拉取 TypeScript 的 master 分支自动测试。

这能帮助团队尽早发现问题,并将修复问题的责任转移给进行语言修改的人。

dtslint为基于模块的测试提供支持

DT 中的模块总是和它的测试文件一起被提交的。这些测试文件以 .ts.tsx 结尾,测试最终提供给用户的 .d.ts 文件。我们建议模块的测试文件从测试库的一些使用示例代码开始,以测试模块的核心使用场景,然后随着被新增到 .d.ts 的新类型逐步添加测试用例。

这些测试用例可以验证 .d.ts 是否准确的描述了对应的 JavaScript 模块,也可以用于验证新的修改不会破坏旧的版本。

有了这些系统,我们能够更容易扩大每日能够容载的 mr 数量,减少了审核时长。这便是为什么我们最近让定义作者可以自己合并 PR 的原因!

哪些 PR 是定义作者有权合并的

对所有对 DT 项目提交的 PR 而言,存在这三组关联方:

  • DT 维护者们,目的是维护整个 DT 生态稳定性。
  • 定义作者,目的是保持他们的模块有最新的、合适的代码提示。
  • 普通开发者,尽管不是模块作者,但自发的想要维护该模块的定义。

在之前,只有 DT 维护者们才可以合并 PR 请求。通过新的 github 机器人,我们把能力下放到定义作者,使他们能够自行合并他们的变更。

在判断一个 PR 能否被定义作者合并时,我们把对 DT 的变更分为两类:

  • PR 添加的是新模块的类型定义,这将需要由 DT 维护者们进行验证和合并,这种请求不能由定义作者自行合并。
  • 对原有模块的 PR

针对第二类 PR,我们又根据该模块的影响力分为了两类:

  • 影响到的是极受欢迎的库,如:Node、React、Lodash 或 Jest 等
  • 其他库

在 npm 上每月下载量达 500 万以上的极受欢迎的库的改动也不能直接由定义作者进行合并,同样需要 DT 维护者们参与验证和进行合并。不过,这种改动是少见的,我们收到的大部分 PR 都是对较小的库的快读修改。

什么时候 PR 能够由它的作者合并

在判断了一个 PR 能够被定义作者合并之后,我们的机器人会引导 PR 的作者去完成合并过程。我们为 PR 合并设定了四个条件:

  • 没有合并冲突
  • CI 已经通过了这个模块和它的依赖的自动化测试
  • 这次变更都有在 d.ts 中编写相应的测试用例
  • 最近一次的提交是由定义作者或者是 DT 维护者审批通过的

随着 PR 经历上述阶段,机器人会自动发送相应的评论描述当前自动合并的状态。

这样做的原因是我们试图让机器人为自动合并可能出现的各种状态分支进行对应的引导,并就下一步该做什么进行反馈,为贡献者提供修订文档的链接。

image.png
image.png
image.png
image.png
我们开始看到每天大约有 20 个 PR 请求通过这个新系统被社区合并。由定义作者合并的 PR 通常会在一天内处理完毕,并且不会因为 TypeScript 团队的轮值值班人员的精力不足而被阻止。例如,theme-ui 发现了一个类型定义的缺陷,发现者发起了一个 PR 来进行修复,定义作者进行了审批并在一个小时内完成了合并。这是一个完美的例子,说明我们为什么要完善 PR 机制。

在我们思考我们应该如何维护这么一个变化频繁的项目的时候,我们认为它结合了谨慎的自动化流程和大量的人力贡献。DefinitelyTyped 是一个大规模的社区项目,有上万人参与贡献,我们真的为它所取得的成就感到骄傲,也要为了下一万个贡献者能够更轻松而努力。

原作者:
Orta Therox
Engineer on the TypeScript Compiler
https://devblogs.microsoft.com/typescript/author/ortammicrosoft-com/