跳到主要内容

React Native 0.71-RC0 Android 故障事后分析

·阅读约8分钟
Nicola Corti
Nicola Corti
Meta 软件工程师
Lorenzo Sciandra
洛伦佐·夏安德拉(Lorenzo Sciandra)
微软高级软件工程师

现在 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 issue中找到。

我们如何缓解和解决

11月4日,我们一发现问题,社区就找到了并分享了一个手动解决方案来解决问题,该方案会将 React Native 固定到特定的版本,从而纠正错误。

接着,在11月5日和6日的周末,发布团队发布了所有以前的React Native版本(最低至0.63)的补丁版本,这些补丁会自动应用修补程序,以便用户可以更新到React Native的修复版本。

与此同时,我们联系了 Sonatype,要求删除有问题的构建产物。

11月8日,当所有构建产物从 Maven Central 完全移除时,问题得到了彻底解决。

事件时间线

本节包含事件的简要时间线。所有时间均为格林威治标准时间/协调世界时 +0

经验教训

尽管导致此次事件的条件自 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 帮助我们移除构建产物,感谢我们的社区,以及不懈努力尽快解决此问题的发布团队。