はじめに
Kotlin Multiplatform(KMP)をiOSプロジェクトに導入すると、CI/CDでのビルド時間が課題になることがあります。
プロジェクトの規模にもよりますが、KMPのビルドだけでも10-20分以上かかることもあります。
今回はBitriseのキャッシュ機構を使い、キャッシュ活用時はKMPのビルドをスキップするための方法を記載していきます。
前提
今回は以下の要件であるとします。
- SPMでの配信ではなく、
Git Submoduleによって管理されていること
Bitriseのキャッシュ機構について
今回検討したBitriseのキャッシュ機構はBranch-based cachingとKey-based cachingの2つになります。
それぞれ下記のような特徴があります。
| 項目 | Branch-based caching |
Key-based caching |
|---|---|---|
| 概要 | Bitriseがブランチごとに自動管理 デフォルト推奨方式 |
開発者が明示的にキーを指定して管理 高度な制御が必要な場合に使用 |
| メリット | • 設定がシンプル • フォールバック機能あり(親ブランチから復元) • 依存関係ファイルベースのキャッシュに最適 |
• 正確なキャッシュ管理(Commit Hash等)• 複数の独立したキャッシュを並行管理可能 • キャッシュの有効期限を自分で制御 |
| デメリット | • ブランチごとに1つのキャッシュのみ • 複数の独立したキャッシュを管理できない • キャッシュキーの細かい制御ができない |
• キーの設計が複雑 • キーが一致しない場合は完全にミス • フォールバック機能なし |
今回はCommit HashをキーとしたKey-based cachingを選択しています。
Branch-based cachingはCommit Hashが同じでもブランチ間でのキャッシュの共有ができず、無駄なビルドが増えてしまうため却下しています。
対応方法
1. Commit Hashの取得
Git SubmoduleのCommit Hashを取得し、環境変数に格納
_get_kmp_commit_hash:
steps:
- script@1.2.1:
title: Check KMP Hash
inputs:
- content: |-
#!/usr/bin/env bash
set -ex
# SubmoduleのCommit Hashを参照するためSubmoduleのパスに移動
cd /path/to/submodule_path
# 今参照しているCommit Hashを保持
envman add --key KMP_COMMIT_HASH --value "$(git rev-parse HEAD)"
2. キャッシュの復元
取得したCommit Hashを元にキャッシュを保存している一意なキーを指定し、キャッシュの復元を実施
※ 一意なキーとして kmp-cache-${KMP_COMMIT_HASH}としていますが、基本的にはKMP_COMMIT_HASHで一意性が担保できていればなんでも大丈夫です
_restore-cache:
steps:
- restore-cache@2.5.0:
inputs:
- key: |-
kmp-cache-{{ getenv "KMP_COMMIT_HASH" }}
3. キャッシュ存在チェックによる条件付きビルド
_check_kmp_cacheでキャッシュが復元されているかどうかを確認し、結果を環境変数に格納
_build_kmpではキャッシュの存在有無の環境変数を確認し、キャッシュが存在していなければビルド、存在していればビルドしないようにする
_check_kmp_cache:
steps:
- script@1.2.1:
title: Check KMP Cache
inputs:
- content: |-
#!/usr/bin/env bash
set -ex
if [ -d "/path/to/shared.xcframework" ]; then
envman add --key KMP_CACHE_EXISTS --value "true"
else
envman add --key KMP_CACHE_EXISTS --value "false"
fi
_build_kmp:
steps:
- set-java-version@1:
inputs:
- set_java_version: '${java_version}'
run_if: '{{ getenv "KMP_CACHE_EXISTS" | eq "false" }}'
- script@1.2.1:
inputs:
- content: |-
#!/usr/bin/env bash
set -ex
${kmp_build_command}
title: Build KMP Package
run_if: '{{ getenv "KMP_CACHE_EXISTS" | eq "false" }}'
4. キャッシュの保存
取得したSubmoduleのCommit Hashを元に一意なキーを作成してキャッシュを保存する
is_key_uniqueをtrueに設定することで一意性を担保
_save-cache:
steps:
- save-cache@1.4.0:
inputs:
- key: kmp-cache-{{ getenv "KMP_COMMIT_HASH" }}
- paths: /path/to/shared.xcframework
- is_key_unique: 'true'
5. ワークフロー統合
最後にワークフローを統合し、既存のワークフローに入れ込む。
kmp_settings:
before_run:
- _get_kmp_commit_hash # 1. KMPコミットハッシュ取得
- _restore-cache # 2. KMPキャッシュ復元
- _check_kmp_cache # 3. キャッシュ存在確認
- _build_kmp # 4. 必要な場合のみビルド
- _save-cache # 5. KMPキャッシュ保存
test_workflow:
before_run:
- kmp_settings
steps: ...
まとめ
今回はBitriseのKey-based cachingを使用したキャッシュの運用についてまとめてみました。
上記の設定をすることで、キャッシュ作成時以外はKMPに関連する設定やビルドを完全にスキップすることができます。
開発効率も上がると思いますので、もし同じような課題を感じられている方がいらっしゃいましたらその手助けになると嬉しいです。