Share
Embed
Considerate App Update Delivery at DroidKaigi 2022
よくあるリリースフローが持ちがちな問題点として、日頃から見逃されがちな検証や陥りやすい構造をあげ、それらをどうやって解決していくのかを紹介します
Room Backdrop - 2022/10/06 14:05-14:30
https://droidkaigi.jp/2022/timetable/365055
What is DroidKaigi?
DroidKaigiはエンジニアが主役のAndroidカンファレンスです。
Android技術情報の共有とコミュニケーションを目的に、2022年10月5日(水)〜7日(金)の3日間開催します。
Matsuda Jumpei
October 06, 2022
Transcript
39 slides
-
よくあるリリースフローの問題点とは? 理想的なワークフローの性質を満たすテクニック アプリファイルから取得できる情報 R8 Rules のレビュー方法 リリースフローで意識すべき構成 Considerate App Update
Delivery 2 Jumpei Matsuda @red_fat_daruma DeployGate, Inc. 資料・解説置き場 jmatsu/droidkaigi-2022 -
この発表の範囲 PlayStore その他アプリストアへの配布 組織内配布などの Sideloading ✅ ❌ 4 DroidKaigi 2021
Lite の発表を 🙏 https://youtu.be/DA2ziL4qgZk 資料・解説QR -
• 受け入れテストで最終確認をし、アップロードするだけ 一般的なワークフローの概要図 6 受け入れ テスト VCS (Git etc.) ストア
リリース Lints, 自動テスト, コード レビュー 日常的な開発 Approved なアプリ リリース候補版 リリースフロー コード 変更 -
• 日常的な開発で検証すべきだった項目の受け皿に • 各ステージの In/Out がうまく利用されていない よくある悲しい現実 7 受け入れ テスト
(最後の砦) VCS (Git etc.) ストア リリース コード 変更 日常的な開発 リリースフロー 後回しにした検証 アプリの再ビルド リリース候補(?)版 Lints, 自動テスト, コード レビュー -
• リリースフローにしわ寄せ ≒ コスト化 & 高リスク ◦ 差し戻すときのコストが異常に高い ◦ 可視化しづらい非機能要件の検証が動作チェックで代替される
• ステージ間の In/Out が独立している ◦ 手動やCI変更時に成果物を取り違えるリスクの増加 ◦ 各ステージで環境を揃え、冪等性の前提を担保するという手間 期待に答えられない現実 9 -
• 動作に影響を及ぼす恐れ ◦ ライブラリアップデート時の Proguard/R8 Rule 変更 • 将来的に大変面倒くさい ◦
意図しない permission の追加 • 発覚時にビジネス判断を必要とする ◦ アプリサイズの肥大化 ◦ required feature の追加 (による対応端末の減少) ◦ automatic update を無効化する変更 ※API 22 以下 e.g. 可視化されない・後回しにされがちな検証 10 -
• ツールチェインやアプリの設定の多くは宣言的 ◦ 静的解析、それこそただの grep や diff で十分検出可能 ◦ 推移的依存で一見見えなくても、取り出せればレビュー可能
• 技術的に難しいものもある ◦ e.g. 対応端末数変化の具体的な台数の算出 ▪ Google さん、デバイスカタログAPI作ってくださいお願いします ◦ 端末依存の挙動差異など、実際に動かすことで確定する部分 実行しなくてもリスク検出が可能なものは多い 12 -
• それまでのステージで非機能要件などが検証されている ◦ アプリファイルに含まれる情報の監視 ◦ R8 Rules のレビュー • 各ステージの成果物がリレーされ、再生成しないで済む
• (手動であっても)安全な作業が可能 リリースフローが期待している状態 15 -
• それまでのステージで非機能要件などが検証されている ◦ アプリファイルに含まれる情報の監視 ◦ R8 Rules のレビュー • 各ステージの成果物がリレーされ、再生成しないで済む
• (手動であっても)安全な作業が可能 リリースフローが期待している状態 16 -
17 様々なファイル情報を取得するメリット • ビジネス要件やミス防止に関わりやすい ◦ ファイルサイズの肥大化はインストール率の低下に (諸説有) ◦ バージョン名に判別子を入れておけば容易に環境を判断できる •
日頃から監視することで異常に気づきやすい ◦ e.g. APK 10MB の違和感が薄いが、3MB -> 10MB の変化は異常 リリースフローが期待している状態 > 非機能要件の検証 > アプリファイルに含まれる情報の監視 -
アプリ情報は AAB を対象にした検査がオススメ - 1/2 • APKとAABで取得できる情報量に少し差がある ◦ APK は実行ファイルで、AAB
はパッケージファイル • AAB の情報 = APK - 最終署名 + α ◦ e.g. PlayStoreの機能提供に必要な情報 18 e.g. Proguard Mapping アップロード署名 中間・最終署名情報 AAB ✅ ✅ ❌ APK ❌ ❌ ✅ ✅ 含む ❌ 含まない リリースフローが期待している状態 > 非機能要件の検証 > アプリファイルに含まれる情報の監視 -
アプリ情報は AAB を対象にした検査がオススメ - 2/2 • APKだとResourcesの参照が簡単にいかないことも ◦ Remap されたファイルパス
(case-sensitive) の復元 ※1 ▪ e.g. drawable-hdpi/ic_launcher.png ↔ res/_3.png ◦ AndroidManifest や他XML の decode が必要 ▪ ただし non-XML 形式なら aapt/aapt2 で閲覧可能 • 3rd party ツールを利用すればできるが、今回は skip ◦ 興味があれば参考リポジトリの 3rd party ツール集を 19 ※1: AGP 4.2 辺りのAAPT2から基本的に適用されてしまう リリースフローが期待している状態 > 非機能要件の検証 > アプリファイルに含まれる情報の監視 -
• google/bundletool ◦ PlayStore で利用されている実ツール • 取得できる値 ◦ AndroidManifest の内容、各種リソース名・値(module別)
◦ APK のサイズ(要APKS生成) • 取得できない値 ◦ その他XMLの内容 20 現状、AAB からデータを取るなら bundletool 一択 リリースフローが期待している状態 > 非機能要件の検証 > アプリファイルに含まれる情報の監視 -
21 最低限 bundletool で収集しておくといい値 リリースフローが期待している状態 > 非機能要件の検証 > アプリファイルに含まれる情報の監視 資料・解説QR
• ビルド環境が判断できる・できそうな値 ◦ package name, version code, version name • アプリ挙動に影響する値 ◦ target sdk version の変更 • ビジネス要件に関係する値 ◦ min sdk version の変更 ◦ uses-features(required) の追加 ◦ uses-permissions の追加・削除 ◦ 実際に配信されることになる APK のサイズの増加 詳細な取り方や 取得スクリプトはこちらで🙏 GitHub: jmatsu/droidkaigi-2022 -
• ビルド環境が判断できる・できそうな値 ◦ package name, version code, version name •
アプリ挙動に影響する値 ◦ target sdk version の変更 • ビジネス要件に関係する値 ◦ min sdk version の変更 ◦ uses-features(required) の追加 ◦ uses-permissions の追加・削除 ◦ 実際に配信されることになる APK のサイズの増加 22 最低限 bundletool で収集しておくといい値 リリースフローが期待している状態 > 非機能要件の検証 > アプリファイルに含まれる情報の監視 資料・解説QR -
• チームによってはこれらもリリースブロッカーになりうる • パフォーマンス影響 ◦ AppStartup の meta data の増加
◦ Content Provider の増加 • セキュリティ面 ◦ exported=true なコンポーネントの追加 ◦ 自分のパッケージ空間外のコンポーネントの追加 23 発展: 余裕があればさらに見ておくといい値 リリースフローが期待している状態 > 非機能要件の検証 > アプリファイルに含まれる情報の監視 -
NOTE: ここまでの値を実行時に検証する必要はない 24 • Package Manager APIはベンダー依存 💀 < THIS
IS ANDROID ◦ 例えば一部APIでFire OSの挙動が大きく異なる • そのアプリ自身に関するAPIに挙動差はないけれど・・・ ◦ DeployGateなどを利用してもインストールの手間はしんどい ▪ アップデートすらできないと再署名・再ビルドから手戻り リリースフローが期待している状態 > 非機能要件の検証 > アプリファイルに含まれる情報の監視 -
• それまでのステージで非機能要件などが検証されている ◦ アプリファイルに含まれる情報の監視 ◦ R8 Rules のレビュー • 各ステージの成果物がリレーされ、再生成しないで済む
• (手動であっても)安全な作業が可能 リリースフローが期待している状態 25 -
• アプリの挙動に直結する ◦ 受け入れテスト(ないしは動作テスト)で差し戻されるとつらい ◦ ライブラリのアップデート時に稀によくある • 低コストで確認できて、かつ「なぜ」が可視化されるべき ◦ ❌
実際に動かすテストの機会を増やす ◦ ✅ Rule 記述自体の変更をレビューできるようにする R8 の Rule は必ずレビュー対象するべき 26 リリースフローが期待している状態 > 非機能要件の検証 > R8 Rules のレビュー -
• オプションを足すだけでいい ◦ -printconfiguration proguard-merged-config.txt • ただし実行ユーザー依存の値をトリミングする必要がある ◦ minify${variant}WithR8 タスクに
hook する ◦ 正規表現による置換で対応可能 最終的な Rule を保存し、VCS 管理化に置く 27 リリースフローが期待している状態 > 非機能要件の検証 > R8 Rules のレビュー -
• 他にも可視化オプションがある ◦ -printseeds <file path> : どの entry が
keep されたか ◦ -printusage <file path> : どの entry が remove されたか • 意図しない差分がある ⇒ R8 の breaking changes or bug ◦ AGP の更新や最新の R8 を使うときの検査として応用可能 ◦ Google Issue Tracker に全力で質問しにいきましょう R8 の Breaking changes / Bug の判断 (Advanced) 29 リリースフローが期待している状態 > 非機能要件の検証 > R8 Rules のレビュー -
• それまでのステージで非機能要件などが検証されている ◦ アプリファイルに含まれる情報の監視 ◦ R8 Rules のレビュー • 各ステージの成果物がリレーされ、再生成しないで済む
• (手動であっても)安全な作業が可能 リリースフローが期待している状態 30 -
• 開発フロー内 ◦ アプリファイルは基本変化し続ける ◦ 常に最新のアプリファイルに価値がある • リリースフロー内 ◦ アプリファイルそのものを変更することはない
◦ その時のアプリファイルに価値がある 開発フローとリリースフローを明確に分ける 31 リリースフローが期待している状態 > ステージ間の成果物リレー -
開発フローからの成果物を保存する Pool で分断 32 GitHub Release, S3, GCS, GDrive コード変更
etc. リリースフローが期待している状態 > ステージ間の成果物リレー > 開発フローとリリースフローを明確に分ける 受け入れ テスト ストア リリース リリースフロー 日常的な開発 リリース候補版 リリース候補版(?) VCS (Git etc.) -
リリースフロー内は Pool を対象として再定義 33 GitHub Release, S3, GCS, GDrive 受け入れ
テスト Approve Reject コード変更 etc. VCS (Git etc.) リリース候補版 (approved) リリース候補版 (approve待ち) リリースフローが期待している状態 > ステージ間の成果物リレー > 開発フローとリリースフローを明確に分ける ストア リリース -
• それまでのステージで非機能要件などが検証されている ◦ アプリファイルに含まれる情報の監視 ◦ R8 Rules のレビュー • 各ステージの成果物がリレーされ、再生成しないで済む
• (手動であっても)安全な作業が可能 リリースフローが期待している状態 34 -
手段が目的化すると自動化はリスクになる Gradle やコマンドラインで完結させたい Web console の操作が面倒くさいので自動化したい ビルド環境の依存性や属人性を減らしたい 人的ミスや Secrets 管理リスクを減らして安全性を高めたい
❌ ❌ ✅ ✅ 35 リリースフローが期待している状態 > 安全な手動の実現 -
自動化は Pool -> アップロードの部分だけにする • すでに存在する成果物を対象にできるものだけ選ぶ ◦ PlayStore なら Triple-T/gradle-play-publisher
(GPP) • 自然とアップロードの設定だけになるので複雑化しない ◦ Web コンソールに入力する値とほぼ1対1対応になる 36 リリースフローが期待している状態 > 安全な手動の実現 ビルドをさせないようにする設定はたった 1行だけ -
• Web コンソールであれば表示される警告が見えない ◦ e.g. dangerous permission の追加、配布対象端末数の変化 • 手動手順を復元しづらいことがある
◦ ビルド方法や設定の切り替えが絡むとタスクの独立性がガタ落ち GPP を利用する上での認識すべき危うさ 37 リリースフローが期待している状態 > 安全な手動の実現 -
• Web コンソールであれば表示される警告が見えない ◦ e.g. dangerous permission の追加、配布対象端末数の変化 • 手動手順を復元しづらいことがある
◦ ビルド方法や設定の切り替えが絡むとタスクの独立性がガタ落ち GPP を利用する上での認識すべき危うさ 38 今回紹介したテクニックが適用されていれば無視できる リリースフローが期待している状態 > 安全な手動の実現 -
リリースフローに日頃やるべき検証を押し付けない bundletool を使って AAB ファイルからデータを取り出す R8 のレビューは低コストで実現できる リリースフローとそれまでのフローは明確に分ける GPP などで自動化すべきはアップロード操作だけ
まとめ 01 02 03 04 05 39 Jumpei Matsuda @red_fat_daruma DeployGate, Inc. 資料・解説置き場 jmatsu/droidkaigi-2022