跳到主要内容

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 的第一个候选版本。

此候选版本中的一个重大改变有助于通过将 Artifact 发布到 Maven Central 而不是从源代码构建来缩短构建时间。有关如何实现此目的的更多详细信息,请参阅RFC#508相关讨论

不幸的是,由于我们从模板搭建新项目的方式,这导致旧版本上的任何 Android 用户都无法构建,因为他们会开始下载 0.71.0-rc0 的新 Artifact,而不是他们在项目中使用的版本(例如 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 的最高可用版本。由于新推送到 Maven Central 的 0.71.0-rc.0 成为最高可用版本,因此在 0.71.0-rc.0 之前的 React Native 版本进行构建时,开始使用 0.71.0-rc.0 的 Artifact。本地构建(例如 0.68.0)与 Maven Central 的 Artifact(0.71.0-rc.0)之间的 React Native 版本不匹配导致这些构建失败。

有关此事件的更多技术细节,请参阅此 GitHub Issue

我们如何缓解和解决

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

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

同时,我们联系了 Sonatype,要求删除有问题的 Artifact。

11 月 8 日,当 Artifact 完全从 Maven Central 中移除时,问题得到了彻底解决。

事件时间线

此部分包含事件的简要时间线。所有时间均为 GMT/UTC +0

经验教训

虽然在许多方面,触发此事件的条件自 React Native 0.12.0 以来就已存在,但我们希望确保我们开发和发布 React Native 的基础在未来更加坚固。以下是一些经验教训以及我们如何调整流程和基础设施以在未来更快、更强地响应的行动方案。

事件响应策略

此次事件凸显了我们针对与 React Native 相关的开源问题的事件响应策略中的漏洞。

社区在不到 2 小时内迅速找到了一个解决方案。由于我们对此次问题影响范围的可见性不足,以及修复旧版本所需的复杂性,我们依赖受影响的人在 GitHub issue 上发现解决方案。

我们花了 48 小时才认识到这个问题的更大范围,并且我们不能依赖每个人都找到 GitHub issue。我们需要优先考虑更复杂的积极缓解措施,以自动修复人们的项目。

我们将重新审视我们的流程,以确定何时依赖开发者应用的解决方案与我们可以自动部署的修复。我们还将研究我们的选项,以更好地实时了解我们生态系统的健康状况。

发布支持政策

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 帮助我们移除 Artifact,感谢我们的社区,以及不知疲倦地尽快解决此问题的发布团队。