アプリのipaサイズをslackに通知する
この記事は TimeTree Advent Calendar 2025 の9日目の記事です。
こんにちは、TimeTreeでiOSアプリ開発をしていますNeganです。
はじめに
iOS アプリを継続的に開発していると、アセットの追加やライブラリの更新などによって、気づかないうちに ipa ファイルのサイズが肥大化してしまうことがあります。アプリが不必要に重くなると、ダウンロードやアップデートに時間がかかるだけでなく、ビルドや配信パイプラインにも影響が出るため、できる限り軽量な ipa を維持することはプロダクト品質を保つうえで重要です。
かつて iOS にはセルラー回線でダウンロードできるアプリサイズの上限があり、一定サイズを超えると Wi-Fi 接続が必須となっていました。この制限自体は現在撤廃されていますが、ユーザーの端末設定によっては、大容量アプリをモバイル回線でダウンロードしようとした際に確認ダイアログが表示される場合があります。
これはユーザーを通信量の過剰消費などから守る仕組みですが、大きなアプリはダウンロード完了までに時間がかかり、通信容量も多く消費するため、ダウンロードを控えられる要因になりえます。開発側にとってもアプリサイズの増加は放置できないポイントです。
そこで私たちは、CI(Bitrise)で社内配布向けのビルドを生成する際に ipa のサイズを計測し、Slack に通知する仕組みを導入しました。通知先には、iOS 関連の情報が集まり、メンバー全員が日常的に目を通している Slack の専用チャンネルを指定しています。これにより、サイズ増加の兆候にすばやく気づけるようになり、意図せず重くなったビルドを早期に発見できるようになりました。
本記事では、この仕組みの概要と実際の実装方法について紹介していきます。
社内アプリ配布フローの全体像
シーケンス図で示したとおり、本仕組みは GitHub → Bitrise → Slack を中心に動作します。ここでは、その流れを簡潔に整理します。
まず、GitHub で Pull Request がマージされると、Bitriseでテスト用のビルドを作成するジョブが起動します。ビルド完了後に生成された ipa ファイルは Firebase App Distribution にアップロードされ、そのまま社内向けに配信されます。同時に、CI 側では ipa のサイズを取得し、Slack に通知します。(Firebase App Distribution へのアップロードはシーケンス図から省略しています)
なお、このビルドフローは Slack Bot を使った手動実行にも対応しています。
手動ビルドの場合も、PR マージ時と同様に ビルド → ipa 生成 → サイズ通知 の流れは変わりません。
ipaファイルのサイズをどのように取得するか(App Thinning Size Report の活用)
iOS アプリのサイズを CI 上で把握する方法はいくつかあります。もっとも直接的なのは、生成された ipa ファイルの物理サイズをそのまま計測する方法です。しかし ipa は複数デバイス向けのバイナリや不要なアセットを含んだ “Universal パッケージ” であり、ユーザーが実際に App Store や TestFlight からダウンロードするサイズとは一致しないという問題があります。
そこで Apple は、アプリのエクスポート時に デバイスごとに最適化された「アプリのバリアント」ごとのサイズ を計測できる仕組みを提供しています。ここでいう「バリアント」とは、
特定のデバイス(例:iPhone 16)
特定の OS バージョン(例:iOS 23)
に最適化された構成のことで、実際にユーザーへ配信されるアプリはこの “バリアント” が選択されます。
つまり、ユーザーが受け取る実サイズを知りたいなら、ipa ではなくバリアントサイズを確認するのが本質的に正しいわけです。
App Thinning Size Report を生成する方法
本プロジェクトでは、CI 上でのビルドを Fastlane を用いて実行しています。Fastlane の gym アクションは、Xcode のビルドおよびエクスポート処理をラップしたもので、通常の Xcode アーカイブ/エクスポートと同様の成果物を得ることができます。
さて、ユーザーに実際に配信されるアプリサイズ(バリアントサイズ)を取得するには、Xcode のエクスポート処理に thinning オプション を指定する必要があります。Fastlane では、この Xcode の設定を export_options 経由でそのまま渡すことができ、次のように指定するだけで App Thinning Size Report が生成されます。
export_options = {
thinning: "<thin-for-all-variants>"
}
このオプションを有効にすると、Apple のエクスポート処理によって以下のサイズ情報が
App Thinning Size Report.txt として出力されます。
- デバイス/OS ごとに最適化された各「バリアント」
- Universal バリアント(すべてのアセットを含む構成)
このレポートには、App Store で実際に配信されるサイズに近い値が記録されるため、ipa ファイルの物理サイズを直接測るよりも実利用に即した指標として扱うことができます。
Bitrise 上では、このレポートを CI の成果物として取得し、正規表現で Universal バリアントのサイズを抽出して Slack 通知に活用しています。テキスト形式で構造が安定しているため、パース処理は比較的シンプルに実装できます。
このように、Fastlane(gym)を通じて Xcode のエクスポート機能を拡張し、ユーザーが受け取るサイズに近い値を CI で自動計測できる仕組みを構築しています。
具体的なApp Thinning Size Report.txt
App Thinning Size Report.txtの中身は以下のとおりです。
App Thinning Size Report for All Variants of サンプルアプリ-Sandbox
Variant: サンプルアプリ-2EE2A35A-E380-4C7B-B25B-03A4E92045AA.ipa
Supported variant descriptors:
[device: iPhone12,8, os-version: 18.0],
[device: iPhone12,1, os-version: 17.0],
[device: iPhone11,8, os-version: 17.4],
...
App + On Demand Resources size: 57.7 MB compressed, 126.4 MB uncompressed
App size: 57.7 MB compressed, 126.4 MB uncompressed
On Demand Resources size: Zero KB compressed, Zero KB uncompressed
...
Variant: サンプルアプリ.ipa
Supported variant descriptors: Universal
App + On Demand Resources size: 80 MB compressed, 154.6 MB uncompressed
App size: 80 MB compressed, 154.6 MB uncompressed
On Demand Resources size: Zero KB compressed, Zero KB uncompressed
実際のレポートは全デバイス/OS バリアント分の行が含まれてかなり長くなるため、ここでは一部のみを抜粋し、最後の Variant: サンプルアプリ.ipa(Universal)のサイズを Slack 通知に利用しています。
gym が内部で呼び出す xcodebuild -exportArchive によって生成されたApp Thinning Size Report.txtはipaと同じ出力ディレクトリ に配置されます。
Thinning レポートは export_method によっては生成されない点に注意
この仕組みには 1 点注意があります。
export_method: "app-store"(TestFlight・App Store 配布向け)でエクスポートした場合、
App Store 側で最終的に App Thinning が行われるため、ローカルでは App Thinning Size Report.txt が生成されません。
そのため、
Ad Hoc 配布向けのビルド → レポート生成される
TestFlight / App Store 向けビルド → レポート生成されない
という動作になります。
本記事で紹介している方法は、Ad Hoc 配布向けのビルドパイプラインにおいて特に有効です。
App Thinning Size Report をパースして Slack に通知する
App Thinning Size Report の生成が行われたら、続いてそのレポートをパースし、Universalのサイズ情報を抽出して Slack に通知します。これを実現するために、Fastlane の中に ヘルパーレーンとなる private_lane を用意しています。
このレーンでは、App Thinning Size Report.txt を読み取り、次の処理を行います:
- レポート内から Universal Variant を表すブロックのみを抽出
- 該当ブロックから "App size: ..." の行をパース
- 圧縮サイズを MB 単位で取得
- あらかじめ設定した閾値と比較して判定
- Slack 通知用の本文を整形して送信
実際のコードでは Slack への送信処理や各種メッセージ整形も行っていますが、ここではレポートパースに関わる主要な部分のみ要点を抜粋すると、以下のような流れになります。
# --- ユニバーサル版のみ抽出 ---
text = File.read(report_path)
blocks = text.split(/Variant:/).drop(1)
is_over_app_size_limit = false
# "Supported variant descriptors: Universal" を含むブロックを選択
uni_block = blocks.find { |b| b.include?("Supported variant descriptors: Universal") }
# App size の行を抜き出し
size_line = uni_block[/App size:\s*([^\n]+)/, 1]
# 例: "80 MB compressed, 154.6 MB uncompressed"
if size_line =~ /([\d.]+)\s*(MB|GB)\s+compressed/
size_value = $1.to_f
size_unit = $2
compressed_size = size_unit == 'GB' ? size_value * 1024 : size_value
if compressed_size >= APP_SIZE_LIMIT_MB
is_over_app_size_limit = true
end
end
このように、レポート内の “Universal” のサイズだけを対象とすることで、実際にユーザーが App Store からダウンロードするサイズに近い指標 を Slack へ通知しています。
また、圧縮サイズが設定した閾値 APP_SIZE_LIMIT_MBを超過した場合には、アラートメッセージを付与して通知し、サイズ増加を即座に検知できるようになっています。
Slack 通知でアプリサイズを継続的に可視化する
ここまで紹介してきたように、Bitrise のビルドプロセスと Fastlane のヘルパーレーンを組み合わせることで、アプリサイズを解析し、Slack に通知する仕組みを構築できました。
ビルドごとに App Thinning Size Report をパースし、Universal バリアントの実質的な配信サイズを抽出することで、「いつのまにかアプリが重くなっていた」という事態を未然に防ぐことができます。
アセット追加やライブラリ更新によるサイズ増加にも早期に気づくことができ、開発チーム全体の品質意識向上にもつながります。
以下が実際のSlack通知です。

おわりに
本記事では、CI 上で ipa サイズを計測し、Slack に通知する仕組みについて紹介しました。この仕組みを導入したことで、日々のビルドサイクルの中でアプリサイズを継続的に把握できるようになり、意図しないサイズ増加の早期検知が可能となりました。
また、ビルド結果とあわせてサイズ情報が定期的に可視化されることで、開発メンバーが自然とサイズ推移を意識するようになり、アセット追加やライブラリ更新時の影響を確認しやすくなりました。特別な運用を追加せずとも、既存のワークフローに組み込むだけでサイズ監視が標準化された点は有用でした。
このように、アプリサイズという変更の影響が見えづらい項目を CI で、共有可能な形に落とし込むだけでも、開発プロセス全体の透明性が向上します。今後も必要に応じて計測対象や通知内容を拡張しつつ、継続的な品質維持に役立てていく予定です。
ここまで読んでいただき、ありがとうございました!
それでは、良いお年を!!
TimeTreeのエンジニアによる記事です。メンバーのインタビューはこちらで発信中! note.com/timetree_inc/m/m4735531db852
Discussion