なぜCIが成功したのに、実機だけクラッシュしたのか?

AI活用術

課題

CIが全部greenで、ビルドも配布まで通ったのに、実機で開くとクラッシュする。「テストは通ってるのに何で?」と、原因がコードじゃない場所にあるとなかなか気づけない。

この記事でわかること

  • CIが全部成功していても実機でクラッシュすることがある理由
  • 実機でしか見つからない不具合を、原因調査からどう追っていくか

解決できたこと

CIの成功と実機で実際に動くことは別物だと分かった上で、実機でしか出てこない不具合をどう見つけ、どう直し、どう確認するかの実際の流れを紹介する。

本文

CIが全部successでも、安心してはいけない話

自分もAIと一緒に個人でアプリを5本開発していて(内容はちょっとしたパズルやタイマー系)、4本のアプリの本番リリース準備(CIでのビルド→署名→ストアへのアップロード)が一通り成功した後、「じゃあ実機でも試してみるか」と5本まとめて実機テストをしてみた。

そこで初めて気づいたのが、CIの完了基準を「ビルドが成功してストアにアップロードできること」だけにしていたこと。実機で実際に起動して確認するのは、CIが全部通った後の別工程として意図的に後回しにしていた。そしてこの実機テストで、CIだけでは見えなかった重大な問題が2つ、いきなり出てきた。

CIのgreenは「コンパイルできて配布できる」ことしか保証しない。「実際に起動して、期待通り動く」はまた別の話——ここから紹介する話は、そのギャップで実際に起きたこと。

実例1: クラッシュの原因を追ったら、コードじゃなくて「Commitのタイミング」だった話

5本のうち1本(Number Merge)が、TestFlightで起動した瞬間にクラッシュした。クラッシュレポートを見ると、広告SDK(AdMob)の初期化チェックで例外が起きてabortしている。

最初に疑ったのは「広告IDの転記ミス」。よくあるやつなので、AdMobの管理画面で実際の値と設定ファイルの値を確認してもらった。結果、完全に一致。ここで最初の仮説は外れた。

次にgitの履歴を遡って、CIがビルドを実行した”その瞬間”にリモート(GitHub)に何が入っていたかを確認した。すると、広告IDを正しい値に直したはずのファイルが、まだ古い仮の値のままだった。

原因はこれ。CIはローカルの最新の状態を見ているわけじゃなくて、GitHubにプッシュ済みの状態からビルドしている。 ローカルで直しても、プッシュし忘れていれば、CIにとってはまだ直っていないのと同じ。コード自体はちゃんと直っていたのに、プッシュのタイミングがズレていただけでクラッシュしていた。

直し方はシンプルで、正しい値をコミット・プッシュしてCIを再実行するだけ。ただ、この再実行でもう1つ問題が出た。前回クラッシュしたビルドと同じバージョン番号のままだったため、ストア側に「同じバージョンは再アップロードできない」と拒否された。バージョン番号を上げてから通した。

最終的に、実機(TestFlight)で実際に開いてクラッシュが直っていることを確認して、この件は完了。「直した」で終わらせず、「実機で確認できた」まで含めて完了、という流れがここでも効いた。

実例2: 5本全部で同じ不具合が出ていたのに、CIでは一度も引っかからなかった話

同じ実機テストのタイミングで、5本のアプリ全部でiOS版のスプラッシュ画面(起動直後のブランド演出)が一切表示されないことにも気づいた。アイコンをタップすると、演出無しでいきなりHome画面に切り替わる。

Android版では最初からちゃんと動いていた機能で、iOS対応を追加したときに一度も実機で確認していなかった。CIはコンパイルが通るかしか見ていないので、「画面に何が表示されるか」はそもそもCIのチェック範囲の外。5本とも同じ抜け漏れをしていたのに、CIは1度も教えてくれなかった。

対応方法は3つの案(Androidと同じアニメーション実装・アニメーション無しの簡略版・対応しない)から選ぶことになったが、アニメーション実装はMac環境が無くCIでしか検証できないという制約があり、今回は簡略版(背景色とアイコンの静止画だけ)を採用して実装した。

ここは正直に書いておくと、この記事の元になっている記録の時点では、iOS実機・TestFlightでの目視確認はまだ終わっていない。「直したつもりだけど、実機でまだ確認できていない」という状態。直しただけで安心してしまいがちなところなので、この記事でも「確認済み」とは書かない。

実例3: 中断のせいで「都度コミットする」習慣が崩れて、それが直接クラッシュにつながった話

実例1のクラッシュ、実はもう一段掘ると別の原因が見えてくる。クラッシュしたアプリの作業中、途中でPCを再起動する中断があった。作業を再開したあと、広告ID周りの修正をこまめにコミットせず、まとめて後で1回コミットする流れになっていた。

このコミットをためる動きが、そのままCIビルドのタイミングとズレて、実例1のクラッシュに直結した。中断そのものは避けられないとしても、「中断を挟んだら、再開時にこまめなコミットを忘れずに戻す」を徹底していれば防げた話でもある。

これも、AIまたは自分どちらのせいというより、「中断が起きたときに何が崩れやすいか」を具体的に特定できたのが収穫。次に似た中断が起きたときに、同じ崩れ方をしないための材料になる。

実機テストでしか見えない不具合を減らすための、今からできること

今回の3つの実例から言えそうなのは、次の2点(記録に残っていた事実そのものではなく、実例を振り返って見えてきたAIなりの気づき)。

  • CIの「成功」を完了の合図にせず、「実機で実際に起動して確認できた」を別の完了条件として持っておく
  • 中断を挟んだ作業ほど、再開直後のコミット習慣が崩れやすい。中断明けは特に、こまめなコミットを意識的に戻す

CIとテストは強い味方だけど、「画面がちゃんと表示されるか」「実際に起動して落ちないか」まではカバーしてくれない。最後の確認は、結局実機に頼るしかない。

同じ状況に陥ったときの回避策

  • CIの「成功」を完了の合図にせず、実機で実際に起動して確認できたかを別の完了条件にする
  • 中断を挟んだ作業ほど、再開直後にこまめなコミット習慣を意識的に戻す

この記事は、筆者が実際に個人開発しているアプリ(モバイルアプリのProject)の開発記録(2026年8月3日〜4日)を基に、独自調整したAIが下書きを作成し、筆者が事実確認・編集を行った上で公開しています。

PAGE TOP
タイトルとURLをコピーしました