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.68.0)ではなく、0.71.0-rc0の新しいアーティファクトをダウンロードし始めてしまい、ビルドエラーが発生しました。
なぜこれが起こったのか
React Nativeテンプレートは、Androidアプリをビルドするためのbuild.gradleファイルを提供します。このファイルには、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からのアーティファクトを使用し始めました。ローカルビルド(例: 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から完全に削除され、問題は完全に解決されました。
イベントのタイムライン
このセクションには、イベントの簡単なタイムラインが含まれています。すべての時間は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分: ステータスと回避策を伝える新しいissueがオープンされる。
- 11月6日 - 午後4時11分: Sonatypeへのチケットが、アーティファクトの削除を要求してオープンされる。
- 11月6日 - 午後4時40分: @reactnativeからの最初のツイートで、確認とissueへのリンクが投稿される。
- 11月6日 - 午後7時05分: React Nativeのバージョン0.63までパッチを適用することが決定される。
- 11月7日 - 午前0時47分: 最後のパッチリリースがリリースされる: 0.63.5。
- 11月8日 - 午後8時04分: Maven Central上のアーティファクトが完全に削除される。
- 11月10日 - 午前11時51分: インシデントに関するissueがクローズされる。
学んだこと
このインシデントを引き起こす条件はReact Native 0.12.0以降多くの点で存在していましたが、私たちは今後React Nativeを開発しリリースする基盤がより強固なものになるようにしたいと考えています。以下に、学んだ教訓と、将来より迅速かつ強力に対応するためにプロセスとインフラストラクチャをどのように適応させるかについての具体的な行動をまとめます。
インシデント対応戦略
このインシデントは、React Nativeに関連するオープンソースの問題に対する私たちのインシデント対応戦略におけるギャップを浮き彫りにしました。
コミュニティは2時間以内に迅速に回避策を発見しました。しかし、この問題の影響範囲に関する私たちの可視性の欠如、および古いバージョンで修正するために必要な複雑さのため、私たちは影響を受けた人々がGitHubのissueで回避策を発見することに依存していました。
私たちはこの問題のより大きな範囲を認識し、誰もがGitHubのissueを見つけることに依存できないことに気づくまでに48時間かかりました。私たちは、人々のプロジェクトを自動的に修正するためのより複雑な積極的な軽減策を優先する必要がありました。
私たちは、開発者が適用する回避策に依存するか、自動的に展開できる修正に依存するかについてのプロセスを見直す予定です。また、エコシステムの健全性についてより良いリアルタイムの情報を得るための選択肢も検討します。
リリースサポートポリシー
rn-versionsツールで視覚化されているように、インシデント発生時のReact Native開発者ベースの90%以上をカバーするためには、バージョン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、そしてこの問題にできるだけ早く対処するために tireless に働いてくれたコミュニティとリリースチームに改めて感謝いたします。

