「【GMOペパボ x hey】iOS Meetup」にて使用した登壇資料です。 同僚が主にで進めてくれたプロジェクトを、ノウハウの共有やサポートを行う形で関わっていたk-koheyがまとめて発表しました。
©hey, IncBitriseのCredits-Basedな新プランの利用と改善 github : k-koheytwitter: k_koheyiあれBitriseでビルドすると何かが減っていくよ?!
View Slide
背景と目的● 弊社のBitriseの契約プランがCredits-Basedなプランとなりました○ 従来の並列に実行可能なビルド数に基づくプランはConcurrency-basedなプランと呼ばれます● 今回の発表では新プランを移行して得たメリットと弊チームが新プランに適応するために行った改善を紹介します🙌
BitriseのCredit-Basedなプランについて
Credit−BasedなTeamプラン |概要● 特徴(*1)○ Gen2と呼ばれる高速なマシンを利用できる○ 最大10個のMacOSで同時にビルドできる○ ビルドのタイムアウト時間が大幅に向上■ 45(90)分から4時間に○ ビルドするためにはCreditの消費が必要■ 標準的なスペックでは2credits/minを消費する■ さらに高いCreditsを消費することによってスペックの高いマシンを選択することも可能● 2021/8からの新規ユーザはCredit-Basedなプランのみ選択できる状態(*2)(*1)https://blog.bitrise.io/post/faster-more-flexible-plans-on-bitrise-introducing-teams(*2)https://devcenter.bitrise.io/en/comparing-credit-based-and-concurrency-based-plans.html#:~:text=As%20of%20August%202021%2C%20you,depending%20on%20your%20subscription%20plan.
Credit−BasedなTeamプラン|従来のConcurrency-basedプランとの比較● Gen2と呼ばれる高速なマシンを利用できる○ 従来のマシンと比較してビルド時間が短くなる■ 弊社プロダクトではテスト開始から完了までの時間が半分程度になった● ビルドするためにはCreditの消費が必要○ 従来のプランと同じ感覚でビルドを回すと不必要にCreditsを消費しお金を無駄にしてしまう可能性があるGOODBAD
Credit−BasedなTeamプラン|従来のConcurrency-basedプランとの比較● Gen2と呼ばれる高速なマシンを利用できる○ 従来のマシンと比較してビルド時間が短くなる■ 弊社プロダクトではテスト開始から完了までの時間が半分程度になった● ビルドするためにはCreditの消費が必要○ 従来のプランと同じ感覚でビルドを回すと不必要にCreditsを消費しお金を無駄にしてしまう可能性があるGOODBADBitriseにおけるビルドの実行時間の改善ニーズ 🆙🆙🆙🆙🆙
Creditsの消費量を示すメータがなるべく振り切れないようにビルド時間の改善を行いました● 期間:2週間程度● 人数:1人(たまに2人)
行った改善
下準備①|ワークフローの整理● ワークフローの整理から始めた○ 各ワークフローのビルド時間○ 各ワークフローのトリガー例)● 整理した情報はボトルネックの特定に利用○ 時間が顕著にかかっているビルドの特定○ 不必要に実行されているビルドの特定
下準備②|bitrise.yml(*)の導入● 概要○ bitriseのワークフローやスタックの設定をyml形式にて記述したもの○ リポジトリにymlを配置すると設定が反映される● メリット○ bitriseに対して行った変更をGit管理に含めることができるため今後の変更に伴う事故を防げる○ 各Branch毎に別の設定を適応できる(*)https://devcenter.bitrise.io/en/references/basics-of-bitrise-yml.html#basics-of-bitrise-yml
不要なワークフローの実行を削除● ワークフローのスケジュールやトリガーの設定を見直し、必要ないものは消去、あるいは実行頻度を下げた● 変更例○ 時間がかかるUIテスト(60分以上)の実行頻度を下げる○ pushするたびに実行されているワークフローをpull requestにて実行されるワークフローと結合して実行頻度を下げる● 技術的な挑戦は無いがワークフローの実行時間が丸ごと減るので大きな改善に繋がった
Build Phaseのスクリプトを調整● 背景○ Build Phaseにて実行しているSwiftLintやSwiftFormatのスクリプトに次のような問題があった■ 実行しなくていいタイミング(CI上)で実行されていた■ SwiftLintでは実行対象に含めなくていいソースファイル(差分が無いファイル)も対象となっていた● SwiftFormatは差分検知の仕組みがあり、この点は問題なかった
Build Phaseのスクリプトを調整● 方法○ gitのdiffがあるときだけdiffのあるソースファイルに対してコマンドを実行するようにスクリプトを変更● 結果○ CI上において毎ビルドそれぞれ1~2分かかっていた処理が0秒で終わるように改善下記issue内にあるスクリプトに修正をくわえたものコマンドの実行回数が最小になるように修正してあるhttps://github.com/realm/SwiftLint/issues/413
外部のアプリケーションの終了を待っていたワークフローの改善● 背景○ 外部のテスティングサービスを使用しており、Bitriseのワークフローからそのサービスへテスト対象のアプリのデプロイとテスト結果のSlack通知を行っていたアプリのビルドアプリのデプロイテストの実行Slack通知終了ワークフローテスティングサービス
外部のアプリケーションの終了を待っていたワークフローの改善● 問題○ テスティングサービスの結果を待つ時間が50分ほどあった○ 従来のプランは従量課金制では無かったので問題にならなかったが、Credit-Basedなプランではこの待機時間が問題にアプリのビルドアプリのデプロイテストの実行Slack通知終了ワークフローテスティングサービス
外部のアプリケーションの終了を待っていたワークフローの改善● 方法○ アプリのデプロイを終えたら即ワークフローを終了するように変更○ テスト結果はサービスから送られてくるテスト結果通知メールをhookしてSlackに流すようにした● 結果○ 無駄になっていた50分ほどの時間を節約できたアプリのビルドアプリのデプロイ終了ワークフロー
cacheの利用|仕組み- bitriseではcacheのpushとpullを行う処理(step)が簡単に使えるように用意されている- このstepをワークフローに組み込むことによって、任意のディレクトリを同じbranchで実行される別のワークフローでも使用できるようになる- branchに紐づくcacheが存在しない場合は、bitriseに設定したdefault branchのcacheが使用される- cacheを利用すると依存関係をcloneしcheckoutする時間やビルドする時間を省略でき、ビルド時間が低減すると考えられる詳細:https://devcenter.bitrise.io/en/builds/caching.html
cacheの利用|RubyGemsのcache- 背景- fastlaneやdangerをgemとして導入している- 仮説- gemがinstallされているディレクトリをcacheするように設定するとGemの依存解決処理を省略できるはず
cacheの利用|RubyGemsのcache- 方法- gemがインストールされるディレクトリのパスをcache push stepにて指定- pushのトリガーを設定できるため、Gemfile.lockの変更をトリガーに指定- cache pull stepを追加- 結果- RubyGemsの依存が少なかったこともありcacheのpushおよびpullのオーバーヘッドの方が大きくなり改善に繋がらなかった- 見積もりが甘く反省する結果となった(*)https://devcenter.bitrise.io/en/builds/caching/caching-ruby-gems.html公式ドキュメント(*)にも方法が記載されている
cacheの利用|Swift Pakcage Manager(SPM)のcache- 背景- ProjectやCommand Line ToolにSPMを利用している- Project:FirebaseやOHHTTPStubなど- Command Line Tool:SwiftLintやSwiftFormatなど- Projectの依存関係とは分けて管理- 仮説- Swift Packageされているディレクトリをcacheするように設定するとSwift Packageのソースコードをcloneしてくる時間を省略できるはず
cacheの利用|Swift Pakcage Manager(SPM)のcache- 方法- Swift Packageのソースコードがcloneされる場所を確認- Projectの依存の場合はDerivedDataに入る(*)- xcodebuildコマンドのcloned_source_packages_pathオプションで変更可能- Package.swiftで解決する依存の場合はPackage.swiftと同じディレクトリに存在する.build/の中に入っている(自分調べ。例外あるかも。)- Ruby Gemsと同じ要領でPackage.resolveの変更をhookしてソースコードがcloneされるパスをcacheとしてpushする- 結果- 期待通り1分と少しほどかかっていたソースコードのcloneを省略することができた- ビルド済みバイナリはcacheしてないのでさらなる改善にはCarthargeの導入が必要か?(*)https://asmz.hatenablog.jp/entry/cache-swift-package-manager-on-bitrise
結果- 新しいプランを利用しさらに改善を加えることで特定のワークフローのビルド時間を5割ほど削減できた- 今まで40~50分ほどかかっていたPull RequestのPushによってトリガーされるワークフローが20分前後に- Gen2が大きく削ってくれた- Pull Requestに紐づくビルドがすぐ終わるのは開発体験的な観点でもいい- ワークフローの実行頻度や実行の有無も調節したため、特定のワークフローに限らず全体のビルド時間も軽減されている
おわりに● Gen2を利用するとビルド時間を大幅に減らすことができる● 従量課金になったことにより今まで気にしてなかったようなワークフローのビルド時間も改善の必要性がでてくる● ビルド時間が短くなるとPull Requestのレビューリクエストを送る待ち時間が減ってコスト削減以外の効果も感じた● 今後もビルドパフォーマンスの改善など引き続き改善を進めていきますヘイ株式会社k-koheyBitriseのCredit-Baseな新プランの利用と改善あれBitriseでビルドすると何かが減っていくよ?!