CodemagicでiOSのネイティブアプリをCIに載せる
Flutter専門のCI/CDサービスとして開始されたCodemagicはアップデートによりネイティブアプリでも同等に扱えるようになりました。この記事ではcodemagic.yaml
ファイルを使ったネイティブアプリのCI/CD設定方法を説明します。
GUIで直接AndroidやiOSのネイティブアプリをビルドすることはできませんが、ネイティブアプリをビルドするためにcodemagic.yaml
を使って簡単に設定することができます。
導入
- Codemagic - CI/CD for Flutter and mobile app projectsにログインします。
- Applications overviewで任意のプロジェクトを選択(ここではネイティブのiOSアプリのプロジェクトを選択してください)します。そして
Set up build
を選択してください。 - Select a starter workflowページに遷移するので、Continuous Integration workflowsのiOS Appを選択します。
- 初めてのネイティブのアプリでのCodemagicの利用になる場合には手短なガイドモーダルが表示されます。
デフォルトのYAMLファイルについて
ガイド用のモーダルは合計で4ステップあり、それに従い設定していくことでbuildのみを行える環境の構築が可能です。Download or copy the configuration file example
ではプロジェクトのルートディレクトリに設置する設定ファイルの雛形が提供されます。yamlファイルのコメントにある通り、iOSネイティブアプリ用のyamlファイルについての詳しい情報が知りたい場合はBuilding a native iOS app - Codemagic Docsを参照します。
また、テンプレートの{}
部分を適した値に更新するように指示されています。ダウンロードが良いと思いますが、今回は説明も兼ねているのでクリップボードにコピーして新規ファイル作成します。以下のようなコードになります。
# Check out https://docs.codemagic.io/yaml/building-a-native-ios-app/ for more information # Please review and update values in curly braces workflows: ios-app: name: iOS App environment: vars: XCODE_WORKSPACE: "{{ ADD WORKSPACE NAME HERE }}" XCODE_SCHEME: "{{ ADD SCHEME NAME HERE }}" xcode: latest cocoapods: default scripts: - xcodebuild build -workspace "$XCODE_WORKSPACE.xcworkspace" -scheme "$XCODE_SCHEME" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO artifacts: - $HOME/Library/Developer/Xcode/DerivedData/**/Build/**/*.app - $HOME/Library/Developer/Xcode/DerivedData/**/Build/**/*.dSYM
デフォルトのワークフローIDとワークフロー名が指定されていることがわかりますが、好きなように変更することができます。ワークフローはXcodeとCocoaPodsの両方の最新バージョンを使用しています。
プロジェクトに合った正しいフォルダ構造とツールのバージョンを選択してください。ファイルには、依存関係、変数、その他の関連データを必ず含めてください。
プロジェクトのニーズに合わせて codemagic.yaml を調整し終わったら、プロジェクトリポジトリのお好みのブランチにプッシュしてください。
値を更新したyamlファイルは以下になります。
# Check out https://docs.codemagic.io/yaml/building-a-native-ios-app/ for more information # Please review and update values in curly braces workflows: ios-app: name: iOS App environment: vars: XCODE_WORKSPACE: "CodeMagicTestSample" XCODE_SCHEME: "FileterHB" xcode: latest cocoapods: default scripts: - xcodebuild build -workspace "$XCODE_WORKSPACE.xcworkspace" -scheme "$XCODE_SCHEME" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO artifacts: - $HOME/Library/Developer/Xcode/DerivedData/**/Build/**/*.app - $HOME/Library/Developer/Xcode/DerivedData/**/Build/**/*.dSYM
変更をブランチにプッシュして問題ないことを確認した後、モーダルの最後のステップ、Check for uploaded configuration file
で、Check for configuration file
をクリックします。
codemagic.yamlファイルが任意のブランチに存在することが確認できたらダイアログが表示されるのでStart your first build
をクリックします。
クリックするとbuild configurationの設定画面に遷移します。
ビルドが始まったら結果が反映されるまで待機します。
このプロジェクトでは数分後に成功したことを確認しました。
ここまでで.app
ファイルを生成するworkflowを通したネイティブアプリのビルドは終了です。
コードサイニング
.ipa
ファイルを生成するにはcode-signingが必要になります。
- Certificate
- Provisioning profile
個人利用のためにipaファイルをpublishする場合、iOS Development Ceritificateを使います。また、App Store ConnectにpublishするためにはiOS Distribution Certificateが必要になります。リリース用のiOS Distribution Certificateを作成したい場合にはこちらを参照してください。作成済みのProvisioning profileとCeritificateのダウンロードの取得方法を紹介します。
Xcodeを開いて設定画面に遷移した後、Accountsタブで任意のアカウントを選択して右カラムのDownload Manual Profile
を選択します。ここでダウンロードしたものは~/Library/MobileDevice/Provisioning Profiles/
に配置してあります。
Ceritificateの取得方法も説明します。Download Manual Profiles
の右側のManage Certificates...
をクリックします。
Certificateの管理画面ダイアログが表示されるのでエクスポートしたいCertficateにマウスオーバーしてコンテキストメニューを開きます。するとExport Certificate
をクリックします。
.p12
ファイルの名前やパスワードを設定して任意のディレクトリに保存することができます。
以上で設定済みの証明書とprovisioning profileの取得の説明は終わりです。
codemagic.yamlファイルへの反映
テンプレートとして予め提供されているcodemagic.yamlファイルは.app
ファイルを生成するwolkflowを通してビルドを行うだけなので、.ipaファイル
を生成したい場合はこのファイルにいくつかの環境変数をcode-signing用に追加しなければいけません。
証明書とプロビジョニングプロファイルを暗号化された形で、codemagic.yamlファイルの環境変数セクションにキーと値のペアとして追加する必要があります。
- CM_CERTIFICATE (encrypted version of the certificate)
- CM_CERTIFICATE_PASSWORD (encrypted version of the certificate password)
- CM_PROVISIONING_PROFILE (encrypted version of the provisioning profile)
プロジェクトの設定画面に移動します。遷移先のEncrypt environment variables
というリンクをクリックします。
リンクをクリックするとEncrypt environment variables for YAML configuration
というモーダルが表示されます。Choose a file or drag it here
にファイルをドラッグすると暗号化された文字列が表示されるのでコピーしておきましょう。codemagic.yamlファイルに環境変数を設定する時に使用します。もう一つ、証明書のパスワードについても環境変数に設定しておきたいので、ダイアログのPaste the value of the variable here
というプレースホルダーが書いてあるテキストエリアにパスワードを押してEncrypt
ボタンをクリックします。ファイルをドラッグした時と同じように暗号化された文字列が出力されるのでコピーしておきましょう。
codemagic.yamlに証明書とprovisioning profile、および.p12ファイルに設定したパスワードを環境変数として設定します。YAMLファイルは以下のようになりました。
# Check out https://docs.codemagic.io/yaml/building-a-native-ios-app/ for more information # Please review and update values in curly braces workflows: ios-app: name: iOS App environment: vars: XCODE_WORKSPACE: "CodeMagicTestSample" XCODE_SCHEME: "CodeMagicTestSample" xcode: latest cocoapods: default CM_CERTIFICATE: Encrypted(...) # 証明書ファイルの暗号化文字列 CM_PROVISIONING_PROFILE: Encrypted(...) # provisioning profileの暗号化文字列 CM_CERTIFICATE_PASSWORD: Encrypted(...) # .p12ファイルに指定したパスワードを暗号化した文字列 # ... 以下略
scriptの更新
ipaファイルの生成やテストの実行を行うために環境変数の設定以外に、scriptの変更が必要になります。
まずは keychain を初期化します。
- keychain initialize
Provisioning profileをデコードし、code-signingのプロセス間でアクセスできるようにフォルダに配置します。
PROFILES_HOME="$HOME/Library/MobileDevice/Provisioning Profiles" mkdir -p "$PROFILES_HOME" PROFILE_PATH="$(mktemp "$PROFILES_HOME"/$(uuidgen).mobileprovision)" echo ${CM_PROVISIONING_PROFILE} | base64 --decode > $PROFILE_PATH echo "Saved provisioning profile $PROFILE_PATH"
Certificateをデコードしてキーチェーンに追加します。
echo $CM_CERTIFICATE | base64 --decode > /tmp/certificate.p12 keychain add-certificates --certificate /tmp/certificate.p12 --certificate-password $CM_CERTIFICATE_PASSWORD
テスト実行用のコマンドも追加します。
- | # run tests xcodebuild \ -workspace "CodeMagicTestSample.xcodeproj" \ -scheme "CodeMagicTestSample" \ -sdk iphonesimulator \ -destination 'platform=iOS Simulator,name=iPhone 11 Pro Max,OS=13.4' \ clean build test CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO
ここで指定している-destinationの値と、project.pbxprojeの
IPHONEOS_DEPLOYMENT_TARGET`とのバージョンが一致していることを確認してください。
.ipaファイル生成コマンドもこのタイミングで追加します。
- | # build ipa xcode-project use-profiles xcode-project build-ipa --workspace "CodeMagicTestSample.xcodeproj" --scheme "CodeMagicTestSample"
私の環境に合わせて設定後のcodemagic.yamlファイルを掲載しておきます。
# Check out https://docs.codemagic.io/yaml/building-a-native-ios-app/ for more information # Please review and update values in curly braces workflows: ios-app: name: iOS App environment: vars: XCODE_WORKSPACE: "CodeMagicTestSample" XCODE_SCHEME: "CodeMagicTestSample" xcode: latest cocoapods: default CM_CERTIFICATE: Encrypted() CM_CERTIFICATE_PASSWORD: Encrypted(...) CM_PROVISIONING_PROFILE: Encrypted(...) CM_CERTIFICATE_PASSWORD: Encrypted(...) scripts: - xcodebuild build -workspace "$XCODE_WORKSPACE.xcworkspace" -scheme "$XCODE_SCHEME" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO artifacts: - $HOME/Library/Developer/Xcode/DerivedData/**/Build/**/*.app - $HOME/Library/Developer/Xcode/DerivedData/**/Build/**/*.dSYM # You can get more information regarding the YAML file here: # https://docs.codemagic.io/building/yaml # Workflow setup for building Native iOS project workflows: # The following workflow is for generating a debug build (.app) ios-project-debug: # workflow ID name: CodeMagicTestSampleDebug # workflow name environment: xcode: latest cocoapods: default scripts: - | # run tests xcodebuild \ -workspace "CodeMagicTestSample.xcworkspace" \ -scheme "CodeMagicTestSample" \ -sdk iphonesimulator \ -destination 'platform=iOS Simulator,name=iPhone 11 Pro Max,OS=13.4' \ clean build test CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO - | # build .app xcodebuild build -workspace "CodeMagicTestSample.xcworkspace" -scheme "CodeMagicTestSample" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO artifacts: - $HOME/Library/Developer/Xcode/DerivedData/**/Build/**/*.app publishing: email: recipients: - xxx@gmail.com # enter your email id here # The following workflow is for generating a release build (.ipa) ios-project-release: # workflow ID name: CodeMagicTestSample # workflow name environment: vars: CM_CERTIFICATE: Encrypted(...) # enter the encrypted version of your certificate CM_PROVISIONING_PROFILE: Encrypted(...) # enter the encrypted version of your provisioning profile xcode: latest cocoapods: default scripts: - keychain initialize - | # set up provisioning profiles PROFILES_HOME="$HOME/Library/MobileDevice/Provisioning Profiles" mkdir -p "$PROFILES_HOME" PROFILE_PATH="$(mktemp "$PROFILES_HOME"/$(uuidgen).mobileprovision)" echo ${CM_PROVISIONING_PROFILE} | base64 --decode > $PROFILE_PATH echo "Saved provisioning profile $PROFILE_PATH" - | # set up signing certificate echo $CM_CERTIFICATE | base64 --decode > /tmp/certificate.p12 keychain add-certificates --certificate /tmp/certificate.p12 --certificate-password $CM_CERTIFICATE_PASSWORD - | # run tests xcodebuild \ -workspace "CodeMagicTestSample.xcodeproj" \ -scheme "CodeMagicTestSample" \ -sdk iphonesimulator \ -destination 'platform=iOS Simulator,name=iPhone 11 Pro Max,OS=13.4' \ clean build test CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO - | # build ipa xcode-project use-profiles xcode-project build-ipa --workspace "CodeMagicTestSample.xcodeproj" --scheme "CodeMagicTestSample" artifacts: - build/ios/ipa/*.ipa - /tmp/xcodebuild_logs/*.log publishing: email: recipients: - xxx@gmail.com # enter your email id here
codemagic.yamlの変更を行ったcommitをpushした後、管理画面からStart new build
をクリックしてビルドを開始します。
記載されたテストの実行やPublishingが成功したことを確認しました。
GitHubを見るとリポジトリにもテストの結果が反映されています。
まとめ
CodemagicはFlutter向けのCI/CDサービスとして開始されましたが、現在は各種ネイティブアプリのサポートも進められているとのことでしたが、確かに簡単に設定が出来ました。ただ、現状Codemagic以前から存在するサービスの方が古参なだけあって情報も豊富なので基本的にはFlutter用のCI/CDサービスとして使用しそうだなという感想を持っています。 FlutterでのCI/CDに載せる設定手順は公式ブログの以下の記事がわかりやすいです。
個人アプリで使用しているのでもう少し知見が溜まったら記事にしてみようかなと思っています。