こんにちは、iOSアプリエンジニアの市毛です。
弥生で開発しているiOSアプリはいくつかありますが、今回はその開発を支えるCI/CDについてです。
弥生では、CI/CDサービスにXcode Cloudを採用しています。 本記事では、プロダクト開発にどのようにXcode Cloudを取り入れて運用しているかご紹介します。
ソース修正〜配布まで
ソース修正からAppStoreへ配布するまでの流れをフロー図に表しています。
graph LR ソース修正 --> プルリクエスト作成 --> ID1[Test Flightへ配布] --> masterブランチにマージ --> ID2[AppStoreへ配布] subgraph "Xcode Cloud" ID1 end subgraph "Xcode Cloud" ID2 end
Xcode Cloudの担当分野は、ソースコードのビルドと、各環境へのリリースです。 配布先はTest FlightとAppStoreの2つがあり、それぞれ別のワークフローで動いています。
ワークフロー
ワークフロー概要
こっから実際に運用しているワークフローについてです。 Test FlightとAppStoreのワークフローは共通した設定が多いので、違う部分についてはワークフロー詳細のタイミングで記載しています。
まずはワークフローの全体像です。
graph LR Gitからソース取得 --> ID1[スクリプト実行
cocoa podsのインストール
podライブラリのインストール] --> ID2[xcodebuild
archive] --> ID3[スクリプト実行
Firebase dSYMのアップロード
TestFlightのテストノートにコミットログを記載] --> 環境へ配布 --> Slack通知
ワークフロー実行時に、Xcode Cloudが用意しているActionとは別に独自の処理を入れたい場合は開発側でスクリプトを用意する必要があります。 (上記フロー図のスクリプト実行フェーズ)
今回はスクリプトについても細かくご紹介します。
カスタムスクリプト
XcodeCloudでは①Gitからソースを取得した後、②xcodebuild実行前、③xcodebuild実行後の3つのタイミングでスクリプトを実行できます。 弥生では①と③のタイミングでスクリプトを実行させています。
(引用)Writing custom build scripts
Post-clone
Gitからソースを取得した後に実行されるスクリプトです。 ここではアプリで使用しているライブラリ類のインストールを行なっています。
ライブラリのインストール
弥生ではCocoa Podsを使用してライブラリ管理をしています。 そのため、Xcode Cloudの環境にCocoa PodsのインストールとPodライブラリをインストールする必要があります。(リファレンス)
実行しているスクリプトは下記の通りです。
brew install cocoapods pod install
Post-Xcodebuild
xcodebuild実施後に実行されるスクリプトです。 ここでは下記2つを実施しています。
- FirebaseへのdSYMのアップロード
- TestFlightのテストノートにコミットログを記載
FirebaseへのdSYMのアップロード
Firebaseのクラッシュログを、人間が見やすい形にするためにdSYMファイルをアップロードします。
$CI_WORKSPACE/Pods/FirebaseCrashlytics/upload-symbols -gsp $CI_WORKSPACE/$FIREBASE_INFO_FILE_NAME -p ios $CI_ARCHIVE_PATH/dSYMs
実行ファイル「upload-symbols」を叩いて、dSYMファイルをアップロードしてます。
FIREBASE_INFO_FILE_NAME
は独自で定義した環境変数です。
開発向けと本番向けでFirebaseのプロジェクトを分けているため、独自の環境変数を使用しています。
環境変数の定義については後ほど説明します。
TestFlightのテストノートにコミットログを記載
TestFlightのテストノートにコミットログの文言を追加します。
これによって、テスト時にどういう修正が入ったビルドなのか、判断しやすくなります。
スクリプトは下記の通りです。
if [[ -d "$CI_APP_STORE_SIGNED_APP_PATH" ]]; then TESTFLIGHT_DIR_PATH=../TestFlight mkdir $TESTFLIGHT_DIR_PATH git log -1 --pretty=format:"%s" >! $TESTFLIGHT_DIR_PATH/WhatToTest.ja.txt fi
基本的にはAppleのリファレンスで案内しているコードの通りです。
リファレンスではgit fetch --deepen 3
で直近のコミットログを3つ取得していますが、この処理に4,5分かかる時もあったため、
ソースのclone時に取得している最新コミットログのみでテストノートに出力することにしました。
ワークフロー詳細
こっからワークフローの具体的な設定なども見ていきます。
Enviroment
環境は基本的には各プロダクトの要件などに合わせて設定します。
環境変数はカスタムスクリプトでも記載したように、独自の環境変数を定義しています。
このワークフローでは、 Firebaseの設定ファイルが開発環境と本番環境でファイル名が異なるため、 ワークフロー側で設定しています。
Start Conditions
設定上はBranch Changes(ブランチに変更があったら)にしていますが、自動起動の設定はOFFにしています。
理由としてはTest Flight環境へ配布不要な細かい修正もあるため、不要なタイミングでワークフローが動くことを防ぐためです。 手動実行となっていますが、Xcodeから実行できるため、簡単に実行することができます。
Actions
Actionsではアプリのアーカイブのみを実施しています。
配布先はワークフローによって設定値が変わります。
TestFlight | AppStore |
---|---|
Post-Acrtions
アーカイブが終わったら下記2つを実施して、ワークフローは終了です。
- Slackへの通知
- Testチームへの配布
Xcode Cloudを導入してみて
Xcode Cloud移行前はBitriseを使用して、リリースなどを行なっていましたが、 価格面であったり、プロビジョニングプロファイルなどのメンテナンス性を考慮して、 Xcode Cloudの移行を検討しました。
実際に移行して3ヶ月ほど運用してみた感想ですが、 Xcodeのボタン1つで配布までできることや、 ワークフロー自体の設定が簡易であること、 プロビジョニングプロファイルなどのメンテナンスから解放されることなど、 良かった点はいくつもあると感じています。
ただ、Xcode Cloudにもいくつか課題はある印象です。 例えば、ワークフローの共通化や、編集履歴の管理、複数リポジトリへのアクセス許可の設定方法など。 Xcode Cloudでより良い開発体験が得られるように、今後のAppleの更新に期待しています。