React Native 0.71-RC0 Android 故障后分析
现在 0.71 已可用,我们想分享一些关于导致所有 React Native 版本的 Android 构建中断的事件的关键信息,该事件发生在 2022 年 11 月 4 日发布 React Native 和 Expo Android 构建的第一个 0.71 版本候选版本时。
最近参与解决此事件的贡献者参加了事后分析会议,详细讨论了事件发生的经过、我们从中吸取的教训以及我们将采取哪些措施避免将来发生类似的故障。
事件经过
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 的用户仍在使用 +
版本。
这导致了 React Native 版本早于 0.71.0-rc.0
的构建查询所有存储库以获取 React Native 的最高可用版本。由于新推送到 Maven Central 的 0.71.0-rc.0 成为可用的最高版本,因此 React Native 版本早于 0.71.0-rc.0 的构建开始使用来自 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,要求删除有问题的工件。
当工件完全从 Maven Central 中删除时,问题于 11 月 8 日完全解决。
事件时间轴
本节包含事件的简要时间轴。所有时间均为格林尼治标准时间/协调世界时 +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 的新版本不应该影响旧版本的用户,我们对给您的工作流程带来的干扰表示歉意。
同样,我们也想要强调保持依赖项和 React Native 处于最新版本的重要性,以便从我们引入的改进和安全措施中受益。此事件发生在一个官方的 发布支持策略 正在定义但尚未广泛传播或执行的时间。
将来,我们将在我们的沟通渠道中传达我们的支持策略,并将考虑 在 npm 上弃用旧版本的 React Native。
改进第三方库的测试和最佳实践
此事件突出了拥有更好的发布测试和对第三方库的更好指导的重要性。
在测试方面,发布回溯到 0.63.x
的版本证明具有挑战性,因为我们现在在稳定版本中实施的自动化和测试不足。我们认识到我们的发布和测试基础设施的重要性,并且将来会进一步投资。
具体来说,我们现在鼓励并支持将第三方库测试作为 React Native 发布 的一部分。我们还在 核心贡献者 Discord 服务器 中添加了一些新的渠道和角色。
最重要的是,我们开始与 Callstack(create-react-native-library 的维护者)进行更紧密的合作,以改进库模板并确保它遵循与 React Native 项目集成的所有必要最佳实践。create-react-native-library
的新版本现在与 0.71 项目完全兼容,同时仍然提供向后兼容性。
结论
我们对由此给全球开发人员的工作流程带来的干扰表示歉意。如上所述,我们已经开始采取行动来加强我们的基础 - 还有更多工作要做。
我们希望分享这些见解将帮助大家更好地理解此事件,并且您可以利用我们的经验教训在您自己的工具和项目中应用更好的实践。
最后,我们再次感谢 Sonatype 帮助我们删除了工件,感谢我们的社区,以及不遗余力地尽快解决此问题的发布团队。