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 日 - 凌晨 03:04:打开新问题以沟通状态和解决方法。
- 11 月 6 日 - 下午 04:11:提交给 SonaType 的工单,要求删除工件。
- 11 月 6 日 - 下午 04:40:来自 @reactnative 的第一条推文,承认问题 + 链接到问题。
- 11 月 6 日 - 晚上 07:05:决定将 React Native 版本修补到 0.63。
- 11 月 7 日 - 凌晨 12:47:最后一个修补版本发布:0.63.5。
- 11 月 8 日 - 晚上 08: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 帮助我们删除工件、我们的社区以及为此事尽快解决而不懈努力的发布团队。