メインコンテンツにスキップ

React Native 0.71-RC0 Android 障害の事後分析

·7 分で読める
Nicola Corti
Nicola Corti
Metaのソフトウェアエンジニア
Lorenzo Sciandra
Lorenzo Sciandra
Microsoftのシニアソフトウェアエンジニア

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日の週末に、リリースチームは0.63までの以前のすべてのReact Nativeバージョンのパッチリリースを出荷し、パッチを自動的に適用しました。そのため、ユーザーは修正されたバージョンのReact Nativeにアップデートできました。

同時に、Sonatypeに連絡を取り、問題のあるアーティファクトの削除を依頼しました。

11月8日にアーティファクトがMaven Centralから完全に削除されたことで、問題は完全に解決されました。

イベントのタイムライン

このセクションには、イベントの簡単なタイムラインが含まれています。すべての時間はGMT/UTC +0です

学んだ教訓

多くの点で、このインシデントを引き起こす条件は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、コミュニティ、そしてできるだけ早くこれに対処するために精力的に取り組んだリリースチームに改めて感謝申し上げます。