Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Considerate App Update Delivery at DroidKaigi 2022

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
Tweet

More Decks by Matsuda Jumpei

Other Decks in Programming

Transcript

  1. • 受け入れテストで最終確認をし、アップロードするだけ 一般的なワークフローの概要図 6 受け入れ テスト VCS (Git etc.) ストア

    リリース Lints, 自動テスト, コード レビュー 日常的な開発 Approved なアプリ リリース候補版 リリースフロー コード 変更
  2. • 日常的な開発で検証すべきだった項目の受け皿に • 各ステージの In/Out がうまく利用されていない よくある悲しい現実 7 受け入れ テスト

    (最後の砦) VCS (Git etc.) ストア リリース コード 変更 日常的な開発 リリースフロー 後回しにした検証 アプリの再ビルド リリース候補(?)版 Lints, 自動テスト, コード レビュー
  3. • リリースフローにしわ寄せ ≒ コスト化 & 高リスク ◦ 差し戻すときのコストが異常に高い ◦ 可視化しづらい非機能要件の検証が動作チェックで代替される

    • ステージ間の In/Out が独立している ◦ 手動やCI変更時に成果物を取り違えるリスクの増加 ◦ 各ステージで環境を揃え、冪等性の前提を担保するという手間 期待に答えられない現実 9
  4. • 動作に影響を及ぼす恐れ ◦ ライブラリアップデート時の Proguard/R8 Rule 変更 • 将来的に大変面倒くさい ◦

    意図しない permission の追加 • 発覚時にビジネス判断を必要とする ◦ アプリサイズの肥大化 ◦ required feature の追加 (による対応端末の減少) ◦ automatic update を無効化する変更 ※API 22 以下 e.g. 可視化されない・後回しにされがちな検証 10
  5. • ツールチェインやアプリの設定の多くは宣言的 ◦ 静的解析、それこそただの grep や diff で十分検出可能 ◦ 推移的依存で一見見えなくても、取り出せればレビュー可能

    • 技術的に難しいものもある ◦ e.g. 対応端末数変化の具体的な台数の算出 ▪ Google さん、デバイスカタログAPI作ってくださいお願いします ◦ 端末依存の挙動差異など、実際に動かすことで確定する部分 実行しなくてもリスク検出が可能なものは多い 12
  6. 17 様々なファイル情報を取得するメリット • ビジネス要件やミス防止に関わりやすい ◦ ファイルサイズの肥大化はインストール率の低下に (諸説有) ◦ バージョン名に判別子を入れておけば容易に環境を判断できる •

    日頃から監視することで異常に気づきやすい ◦ e.g. APK 10MB の違和感が薄いが、3MB -> 10MB の変化は異常 リリースフローが期待している状態 > 非機能要件の検証 > アプリファイルに含まれる情報の監視
  7. アプリ情報は AAB を対象にした検査がオススメ - 1/2 • APKとAABで取得できる情報量に少し差がある ◦ APK は実行ファイルで、AAB

    はパッケージファイル • AAB の情報 = APK - 最終署名 + α ◦ e.g. PlayStoreの機能提供に必要な情報 18 e.g. Proguard Mapping アップロード署名 中間・最終署名情報 AAB ✅ ✅ ❌ APK ❌ ❌ ✅ ✅ 含む ❌ 含まない リリースフローが期待している状態 > 非機能要件の検証 > アプリファイルに含まれる情報の監視
  8. アプリ情報は 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から基本的に適用されてしまう リリースフローが期待している状態 > 非機能要件の検証 > アプリファイルに含まれる情報の監視
  9. • google/bundletool ◦ PlayStore で利用されている実ツール • 取得できる値 ◦ AndroidManifest の内容、各種リソース名・値(module別)

    ◦ APK のサイズ(要APKS生成) • 取得できない値 ◦ その他XMLの内容 20 現状、AAB からデータを取るなら bundletool 一択 リリースフローが期待している状態 > 非機能要件の検証 > アプリファイルに含まれる情報の監視
  10. 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
  11. • ビルド環境が判断できる・できそうな値 ◦ package name, version code, version name •

    アプリ挙動に影響する値 ◦ target sdk version の変更 • ビジネス要件に関係する値 ◦ min sdk version の変更 ◦ uses-features(required) の追加 ◦ uses-permissions の追加・削除 ◦ 実際に配信されることになる APK のサイズの増加 22 最低限 bundletool で収集しておくといい値 リリースフローが期待している状態 > 非機能要件の検証 > アプリファイルに含まれる情報の監視 資料・解説QR
  12. • チームによってはこれらもリリースブロッカーになりうる • パフォーマンス影響 ◦ AppStartup の meta data の増加

    ◦ Content Provider の増加 • セキュリティ面 ◦ exported=true なコンポーネントの追加 ◦ 自分のパッケージ空間外のコンポーネントの追加 23 発展: 余裕があればさらに見ておくといい値 リリースフローが期待している状態 > 非機能要件の検証 > アプリファイルに含まれる情報の監視
  13. NOTE: ここまでの値を実行時に検証する必要はない 24 • Package Manager APIはベンダー依存 💀 < THIS

    IS ANDROID ◦ 例えば一部APIでFire OSの挙動が大きく異なる • そのアプリ自身に関するAPIに挙動差はないけれど・・・ ◦ DeployGateなどを利用してもインストールの手間はしんどい ▪ アップデートすらできないと再署名・再ビルドから手戻り リリースフローが期待している状態 > 非機能要件の検証 > アプリファイルに含まれる情報の監視
  14. • アプリの挙動に直結する ◦ 受け入れテスト(ないしは動作テスト)で差し戻されるとつらい ◦ ライブラリのアップデート時に稀によくある • 低コストで確認できて、かつ「なぜ」が可視化されるべき ◦ ❌

    実際に動かすテストの機会を増やす ◦ ✅ Rule 記述自体の変更をレビューできるようにする R8 の Rule は必ずレビュー対象するべき 26 リリースフローが期待している状態 > 非機能要件の検証 > R8 Rules のレビュー
  15. • オプションを足すだけでいい ◦ -printconfiguration proguard-merged-config.txt • ただし実行ユーザー依存の値をトリミングする必要がある ◦ minify${variant}WithR8 タスクに

    hook する ◦ 正規表現による置換で対応可能 最終的な Rule を保存し、VCS 管理化に置く 27 リリースフローが期待している状態 > 非機能要件の検証 > R8 Rules のレビュー
  16. • 他にも可視化オプションがある ◦ -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 のレビュー
  17. • 開発フロー内 ◦ アプリファイルは基本変化し続ける ◦ 常に最新のアプリファイルに価値がある • リリースフロー内 ◦ アプリファイルそのものを変更することはない

    ◦ その時のアプリファイルに価値がある 開発フローとリリースフローを明確に分ける 31 リリースフローが期待している状態 > ステージ間の成果物リレー
  18. 開発フローからの成果物を保存する Pool で分断 32 GitHub Release, S3, GCS, GDrive コード変更

    etc. リリースフローが期待している状態 > ステージ間の成果物リレー > 開発フローとリリースフローを明確に分ける 受け入れ テスト ストア リリース リリースフロー 日常的な開発 リリース候補版 リリース候補版(?) VCS (Git etc.)
  19. リリースフロー内は Pool を対象として再定義 33 GitHub Release, S3, GCS, GDrive 受け入れ

    テスト Approve Reject コード変更 etc. VCS (Git etc.) リリース候補版 (approved) リリース候補版 (approve待ち) リリースフローが期待している状態 > ステージ間の成果物リレー > 開発フローとリリースフローを明確に分ける ストア リリース
  20. 自動化は Pool -> アップロードの部分だけにする • すでに存在する成果物を対象にできるものだけ選ぶ ◦ PlayStore なら Triple-T/gradle-play-publisher

    (GPP) • 自然とアップロードの設定だけになるので複雑化しない ◦ Web コンソールに入力する値とほぼ1対1対応になる 36 リリースフローが期待している状態 > 安全な手動の実現 ビルドをさせないようにする設定はたった 1行だけ
  21. • Web コンソールであれば表示される警告が見えない ◦ e.g. dangerous permission の追加、配布対象端末数の変化 • 手動手順を復元しづらいことがある

    ◦ ビルド方法や設定の切り替えが絡むとタスクの独立性がガタ落ち GPP を利用する上での認識すべき危うさ 37 リリースフローが期待している状態 > 安全な手動の実現
  22. • Web コンソールであれば表示される警告が見えない ◦ e.g. dangerous permission の追加、配布対象端末数の変化 • 手動手順を復元しづらいことがある

    ◦ ビルド方法や設定の切り替えが絡むとタスクの独立性がガタ落ち GPP を利用する上での認識すべき危うさ 38 今回紹介したテクニックが適用されていれば無視できる リリースフローが期待している状態 > 安全な手動の実現