React Native 0.71-RC0 Android 故障事后分析
现在 0.71 版本已发布,我们想分享一些关于事件的关键信息,该事件在 2022 年 11 月 4 日为 React Native 和 Expo Android 构建发布第一个 0.71 候选版本时,破坏了所有 React Native 版本的 Android 构建。
最近,帮助解决此事件的贡献者参加了一个事后分析会议,详细讨论了事件的经过、我们从中吸取的教训以及我们将来将采取哪些措施来避免类似的故障。
事件经过
2022 年 11 月 4 日,我们在多个公共仓库中发布了 React Native 的版本 0.71.0-rc0
,这是 0.71 的第一个候选版本。
此候选版本中的一项重大更改是通过将工件发布到 Maven Central 而不是从源代码构建它们来帮助缩短构建时间。有关如何完成此操作的更多详细信息,请参阅 RFC#508 和 相关讨论。
不幸的是,由于我们从模板搭建新项目的方式,这导致任何使用旧版本的 Android 用户构建失败,因为他们会开始下载 0.71.0-rc0
的新工件,而不是他们项目中使用的版本(如 0.68.0
)。
事件原因
React Native 模板提供了一个 build.gradle
文件来构建 Android 应用。此文件包含对 React Native Android 库的依赖,如下所示:implementation("com.facebook.react:react-native:+")
。
重要的是,此依赖项的 +
部分(Gradle 动态版本)告诉 Gradle 选择 React Native 的最高可用版本。使用 Gradle 动态版本被认为是一种反模式,因为它使用户面临不太可重现的构建。
我们意识到动态版本可能导致的问题,因此在 0.71
中,我们清理了新的应用模板并删除了所有 +
依赖项。但是,使用旧版本 React Native 的用户仍在使用 +
版本。
这导致使用 0.71.0-rc.0
之前版本的 React Native 构建查询所有仓库,以查找 React Native 的最高可用版本。由于新推送的 0.71.0-rc.0 在 Maven Central 上成为最高可用版本,因此使用 0.71.0-rc.0 之前版本的 React Native 构建开始使用来自 0.71.0-rc.0 的工件。本地构建(例如 0.68.0
)和 Maven Central 中的工件 (0.71.0-rc.0
) 之间的 React Native 版本不匹配导致这些构建失败。
有关此事件区域的更多技术详细信息,也可在 此 GitHub 问题 中找到。
我们如何缓解和解决
在 11 月 4 日我们确定问题后,社区立即找到并分享了一个手动解决方法来修复该问题,该解决方法会将 React Native 锁定到特定版本,从而纠正错误。
然后,在 11 月 5 日和 6 日的周末,发布团队为所有之前的 React Native 版本(低至 0.63)发布了补丁版本,这些版本会自动应用补丁,以便用户可以更新到已修复版本的 React Native。
与此同时,我们联系了 Sonatype,要求删除有问题的工件。
当工件于 11 月 8 日完全从 Maven Central 中删除时,问题已完全解决。
事件时间线
本节包含事件的简要时间线。所有时间均为 GMT/UTC +0
- 11 月 4 日 - 下午 5:06:0.71-RC0 发布。
- 11 月 4 日 - 下午 6:20:第一个构建问题报告被打开。
- 11 月 4 日 - 晚上 7:45:社区识别出问题。
- 11 月 4 日 - 晚上 9:39:解决方法已沟通,Expo 为所有用户部署修复程序。
- 11 月 5 日 - 凌晨 3:04:新问题已打开,以沟通状态和解决方法。
- 11 月 6 日 - 下午 4:11:向 SonaType 提交工单,要求删除工件。
- 11 月 6 日 - 下午 4:40:来自 @reactnative 的第一条推文,确认问题 + 问题链接。
- 11 月 6 日 - 晚上 7:05:决定将 React Native 版本回溯修补到 0.63。
- 11 月 7 日 - 凌晨 12:47:最后一个修补版本发布:0.63.5。
- 11 月 8 日 - 晚上 8:04:Maven Central 上的工件被完全删除。
- 11 月 10 日 - 上午 11:51:关于事件的问题已关闭。
经验教训
虽然在许多方面,触发此事件的条件自 React Native 0.12.0 以来就已存在,但我们希望确保我们开发和发布 React Native 的基础在未来更加强大。以下是一些经验教训以及关于我们将如何调整流程和基础设施以在未来更快更强地做出响应的可行措施。
事件响应策略
此事件突显了我们在与 React Native 相关的开源问题的事件响应策略方面的差距。
社区在不到 2 小时内迅速找到了解决方法。由于我们对该问题影响范围的可见性不足,以及修复旧版本所需的复杂性,我们依赖于受影响的人员在 GitHub 问题上发现解决方法。
我们花了 48 小时才认识到此问题的更大范围,并且我们不能依赖每个人都找到 GitHub 问题。我们需要优先考虑更复杂的主动缓解措施,以自动修复人们的项目。
我们将重新审视我们的流程,以确定何时依赖开发者应用解决方法,何时依赖我们可以自动部署的修复程序。我们还将研究我们获取生态系统健康状况的更好实时脉搏的选项。
发布支持策略
如 rn-versions 工具 中可视化所示,为了覆盖事件发生时超过 90% 的 React Native 开发者群体,我们必须发布一直到 0.63 版本的补丁。
我们认为这是由 React Native 升级体验造成的,该体验在历史上充满了摩擦。我们目前正在研究改进升级体验的方法,使其更顺畅、更快速,以缓解生态系统的这种碎片化。
发布较新版本的 React Native 绝不应影响旧版本用户,对于给您的工作流程造成的中断,我们深感抱歉。
同样,我们也要强调及时更新您的依赖项和 React Native 的最新版本的重要性,以便从我们引入的改进和保障措施中受益。此事件发生在官方发布支持策略正在定义但尚未广播或执行的时期。
将来,我们将在我们的沟通渠道上沟通我们的支持策略,我们将考虑在 npm 上弃用旧版本的 React Native。
改进的测试和第三方库的最佳实践
此事件突显了拥有更好的发布测试和更好的第三方库指南的重要性。
在测试方面,由于我们现在为稳定版本提供的自动化和测试不足,发布低至 0.63.x
的版本被证明具有挑战性。我们认识到我们的发布和测试基础设施的重要性,并且我们将在未来对其进行更多投资。
具体而言,我们现在鼓励和支持第三方库测试作为 react native 发布的一部分。我们还在核心贡献者 Discord 服务器中添加了一些新渠道和角色。
除此之外,我们还开始与 create-react-native-library 的维护者 Callstack 进行更紧密的合作,以改进库模板并确保其遵循与 React Native 项目集成所需的所有最佳实践。较新版本的 create-react-native-library
现在与 0.71 项目完全兼容,同时仍提供向后兼容性。
结论
对于此次事件给全球开发者的工作流程带来的中断,我们深感抱歉。如上所述,我们已经开始采取行动来加强我们的基础 - 并且还有更多工作要做。
我们希望分享这些见解将帮助大家更好地了解此事件,并且您可以利用我们的经验教训在您自己的工具和项目中应用更好的实践。
最后,我们再次感谢 Sonatype 帮助我们删除工件,感谢我们的社区以及为尽快解决此问题而不知疲倦地工作的发布团队。