XcodeサーバーとのiOS継続的インテグレーションの説明
公開: 2022-03-11序章
Xcode 9より前は、Appleの継続的インテグレーションツールを使用することは、追加のmacOSServerアプリの購入とインストールを必要とする退屈で複雑なプロセスでした。 これにより、多くの開発者はiOSプロジェクトの継続的インテグレーションのアイデアを放棄するか、サードパーティのソリューションに頼るようになり、成功のレベルは大きく異なります。
ただし、2017年9月にXcode 9.0がリリースされた後、自動コード署名のオプションを含め、プロセスが大幅に簡素化され、Xcodeに完全に統合されました。 したがって、追加のアプリやツールは必要ありません。
Fastlane、Bluepillなどのサードパーティソリューションは非常に役立ち、多くの面倒な作業を行うことができますが、この記事では、継続的インテグレーションのニーズにXcodeとAppleツールを単独で使用する機能について説明します。 また、多くの人にとって問題になることが多いため、手動のコード署名も使用します。また、複数のビルド構成に関しては、自動署名も最適なソリューションではない傾向があります。
注:この記事はXcode 9.4.1に基づいており、iOSアプリの開発に焦点を当てていますが、その多くはXcode 10(現在ベータ5ビルドとして利用可能)およびmacOSアプリの開発に適用できます。
Xcodeサーバーのセットアップ
Xcode 9は、実際の統合プロセスを簡素化するだけでなく、Xcodeサーバーのセットアッププロセスも簡素化しました。
CIサーバーとして指定されているmacOSマシンでXcodeアプリを起動し、[設定]を開きます。
サーバーとボットと呼ばれる最後のタブに移動します。
右上隅のスイッチをクリックして、Xcodeサーバーの機能をオンにします。 次に、このマシンでビルドスクリプトを実行および実行するユーザーを選択するように求められます。 既存のユーザーを使用するのではなく、この目的のためだけに専用のユーザーを用意することをお勧めします。
Xcodeボットを実行するには、このユーザーがシステムにログインしている必要があることに注意してください。 ログイン後、ユーザー名の横に緑色の円が表示されます。
それでおしまい! Xcodeボットを詳しく見てみましょう。
Xcodeボットを構成する方法
これで、このサーバーで実行するXcodeボットの構成を開始する準備が整いました。 これは、サーバーと同じネットワークに接続されている任意の開発マシンで実行できます。
開発マシンでXcodeを開き、トップメニューから[ Xcode]>[設定]をクリックします。 次に、[アカウント]タブに移動し、左下隅にある[ + ]アイコンをクリックします。 表示されるダイアログからXcodeサーバーを選択します。
ボットを作成するには、Xcodeでプロジェクトを開き、トップメニューから[製品]>[ボットの作成... ]オプションを選択します。 ボットのセットアップにはいくつかの手順があり、次のセクションでそれらについて説明します。
アプリ配布の自動化
iOSアプリビルド自動化の最も頻繁なアプリケーションの1つは、TestFlight、FabricなどのiOS配信プラットフォームにアプリをアップロードするようにボットを構成することです。
前に説明したように、この記事では、App Store Connectへのアップロードと、Xcodeサーバーからの直接ダウンロードについてのみ説明します。これらはAppleのiOSアプリ配布用のネイティブツールです。
Xcodeを使用したAppStoreConnectディストリビューション
ボットを構成する前に、アプリ開発プロジェクトのバンドルIDと一致するAppStoreConnectアプリレコードがあることを確認してください。 また、各ビルドには、ビルドバージョンとビルド番号で構成される一意の識別子が必要であることに注意してください。 後でXcodeボットの設定について説明するときに、これらの条件が満たされていることを確認する方法について説明します。
ステップ1:正しいビルド構成をセットアップすることは、必要なものを取得するための重要なステップです。 AppStoreConnectにアップロードするアプリを作成するスキームと構成を選択してください。 これには、ビルド構成で、チームのApple Developerポータル(コード署名に使用)およびApp Store Connectポータル(アプリの自動アップロードに使用)に登録されている適切なバンドルIDが使用されていることを確認することが含まれます。 。
ステップ2: [構成]タブを表示したまま、エクスポートオプションを指定する必要があります。 エクスポートオプションのプロパティリストを調べますので、[カスタムエクスポートオプションのリストを使用する]が選択されていることを確認してください。
ステップ3:今がエクスポートオプションのプロパティリストを作成するときです。 xcodebuild --help
と入力すると、このファイルで使用されるキーの完全なリストが利用可能になりますが、このボット構成で使用されるキーについては、ここで説明します。
-
compileBitcode
–ビットコードは、アプリのソースコードに対するAppleの暫定出力形式です。 つまり、特定のアーキテクチャのマシンコードにコンパイルされる前にソースコードが変換される形式です。 これは、命令セットで最適化が行われた場合にさらに最適化できる単一のコードコンテナーを持ち、この同じ形式から将来のアーキテクチャーにコンパイルできるようにすることを目的としています。 ただし、これはアプリケーションに影響を与えません。 有効にするかどうかはあなた次第です。 -
method
–この引数は、エクスポートする製品の種類を指定します。 Appleは、指定されたオーディエンスによって製品を区別します。開発では、プロビジョニングプロファイルで指定されたデバイスにのみ製品をインストールできます。エンタープライズでは、すべてのユーザーが製品をインストールできますが、アプリを実行する前に、この開発プロファイルを明示的に信頼する必要があります。 AppStoreまたはAppStoreConnectに配布するため、この値を使用します。 -
provisioningProfiles
–これは自明です。 ただし、ここで注意すべき点がいくつかあります。エクスポートオプションのプロパティリストのプロビジョニングプロファイルは、キーが製品のバンドルIDに対応し、値がコード署名に使用されるプロビジョニングプロファイルの名前に対応する辞書です。 -
signingCertificate
–もう1つの自明の議論。 このフィールドの値は、完全な証明書名またはSHA-1ハッシュにすることができます。 -
teamID
–もう1つの自明の議論。 これは、AppleDeveloperプログラムにサインアップしたときにAppleが組織に発行した10文字の長さの識別子です。 -
uploadBitcode
–ビットコードをアップロードするかどうか(コンパイルすることを選択した場合)。これにより、AppStore Connectで使用して、新しい最適化されたビルドまたは将来のアーキテクチャ用のビルドを生成できます。 -
uploadSymbols
–デバッグシンボルをアップロードして、メモリダンプとアセンブリスタックだけでなく、意味のあるクラッシュレポートを取得できるようにします。
したがって、エクスポートオプションのプロパティリストは次のようになります。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>compileBitcode</key> <false/> <key>method</key> <string>app-store</string> <key>provisioningProfiles</key> <dict> <key>com.bundle.id</key> <string>ProvisioningProfileName</string> </dict> <key>signingCertificate</key> <string>Signing Certificate Exact Name or SHA-1 hash value</string> <key>teamID</key> <string>??????????</string> <key>uploadBitcode</key> <false/> <key>uploadSymbols</key> <true/> </dict> </plist>
ステップ4:エクスポートオプションのプロパティリストとして作成した.plistを選択します。
ステップ5:次は[スケジュール]タブです。好みに応じて設定します。
ステップ6: [署名]タブで、[証明書とプロファイル]ページで、[Xcodeサーバーに証明書とプロファイルの管理を許可する]オプションをオフにし、一致する署名証明書とプロビジョニングプロファイルを自分でアップロードします。
ステップ7:アプリをテストするのではなくアップロードするため、[デバイス]タブはそのままにしておく必要があります。
ステップ8: [引数]タブでは、ビルドまたは統合前および統合後のスクリプトで使用できるxcodebuild引数または環境変数を明示的に設定できます。
ステップ9:最後に、[トリガー]タブが表示されます。このタブは、Xcode継続的インテグレーションボットを構成するための最後のタブでもあります。 これは、Xcodeサーバーの兵器庫で最も強力なツールです。 手始めに、統合前のスクリプトとして次の2つのコマンドを追加します。

#!/bin/sh set printenv
最初のものは、Xcodeサーバーが現在の統合実行で使用するすべての変数とそれらの値を出力します。 2つ目は、すべての環境変数とその値を出力します。 予想どおり、これはスクリプトのデバッグに役立つ可能性があるため、適切に「デバッグ情報」という名前を付けます。
App Store Connectにアップロードされる各ビルドには、一意のビルドバージョンとビルド番号のペアが必要であることを確認する必要があることを説明したことを思い出してください。 組み込みのPlistBuddyツールを使用できますが、一意のビルド番号を設定する方法も必要です。 Xcodeサーバーの統合中に常に存在するものの1つであり、便利なことに一意であるのは、自動インクリメントされるため、統合番号です。 毎回一意のビルド番号を確実に取得できるように、次の内容で「setbuildnumber」という名前の別の統合前スクリプトを作成します。
#!/bin/sh buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${PROJECT_DIR}/${INFOPLIST_FILE}") buildNumber=$XCS_INTEGRATION_NUMBER /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "${PROJECT_DIR}/${INFOPLIST_FILE}"
CocoaPodsを使用していて、PodsディレクトリをDVCSにコミットしないことを選択した場合は、次の内容の統合前スクリプトも含める必要があります。
#!/bin/sh cd $XCS_PRIMARY_REPO_DIR pod install
ステップ10:ほぼ完了しましたが、ビルドをAppStoreConnectにアップロードする場所またはアカウントを指定していません。 この目的のために、統合後のスクリプトと、ApplicationLoaderと呼ばれる別の組み込みツールを追加します。 スクリプトに次のように記述します。
#!/bin/sh /Applications/Xcode.app/Contents/Applications/Application\ Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Support/altool --upload-app -f $XCS_PRODUCT -u $TESTFLIGHT_USERNAME -p $TESTFLIGHT_PASSWORD
$XCS_PRODUCT
はXcodeServer変数であり、現在の統合実行で作成されたアプリへのパスが含まれています。 ただし、 $TESTFLIGHT_USERNAME
と$TESTFLIGHT_PASSWORD
は、システム変数でもXcodeサーバー変数でもありません。 これらはあなたが設定し、あなたのAppleIDとパスワードの値を持っている必要があります。 残念ながら、AppleはAppStoreConnectビルドアップロード用のAPIキーの生成のサポートを終了しました。 これは機密情報であるため、Xcodeサーバーのボット構成ではなく、環境変数としてMacサーバーに直接設定することをお勧めします(これは自分のものであると想定しています)。
Xcodeサーバーの配布
Xcodeサーバー配布ボットは、統合後のスクリプトを除いて、実際にはAppStoreConnect配布の構成と同じ構成を使用します。 ただし、アプリケーションをダウンロードしてインストールするのは難しい場合があります。 アプリに署名したプロビジョニングプロファイルで、使用しているデバイスにアプリをインストールできることを確認する必要があります。
これが整ったら、iOSデバイスでSafariを開き、サーバーのXcodeサーバーWebダッシュボードに移動する必要があります。 たとえば、サーバーの名前が「Mac server」の場合、サーバーと同じネットワーク上にある場合は「mac-server-name.local/xcode」にあります。 そこには、すべてのXcodeボットのリストとそれらの最新の統合の統計があります。
ダウンロードするアプリをビルドしたものを選択します。 次の画面には、 [インストール]と[プロファイル]の2つのボタンがあります。 このサーバーから初めてダウンロードする場合は、[プロファイル]をクリックして、その証明書を信頼できるソースのリストに追加する必要があります。 その後、同じページの[インストール]ボタンをクリックすると、iOSの確認ダイアログ「デバイスに*をインストールしてもよろしいですか?」が表示されます。 [はい]をクリックして確認すると、アプリがインストールされ、ホーム画面から実行できるようになります。
iOS 10.3以降の場合、「*。localに接続できません」で失敗する理由は、テストデバイスの[設定]で自己署名証明書を手動で信頼する必要があるためです。
次の手順を実行します:
ステップ1: iPhoneのXcodeサーバーのボットページから自己署名証明書をインストールします。
手順2: iPhoneの[設定]>[一般]>[バージョン情報]>[証明書の信頼設定]に移動します。
手順3:[ルート証明書の完全信頼を有効にする]セクションでサーバーの自己署名証明書を見つけ、スイッチをオンにします。
ステップ4: Xcodeサーバーのボット統合ページに戻り、[インストール]をクリックします。
Xcodeサーバーの自動アプリテスト
Xcodeサーバーのもう1つの優れた用途は、ユニットテストであろうとUIテストであろうと、自動アプリテストです。 これを行うには、プロジェクトに適切なターゲットを設定する必要があります。 つまり、目標に応じて、ユニットテストまたはUIテストを実行するターゲットが必要です。
セットアッププロセスは前のプロセスと同じですが、異なるオプションを選択します。 最初の大きな違いは、[構成]タブにあります。 明らかに、それが私たちの主な目標であるため、「分析」ボックスと「テスト」ボックスをチェックします。 また、このボットを使用して製品をアーカイブしたりエクスポートしたりしないことをお勧めします。 同じボット構成でテストと配布の両方を実現できます。 ただし、これら2つのシナリオは、出力とスケジュールが異なります。 多くの場合、配布はサイクルの最後に実行されます。
スクラム、かんばん、またはその他のフレームワークで作業しているかどうかに関係なく、事前定義された時間駆動型またはイベント駆動型のサイクルがあり、その最後に製品をエクスポートして使用できるようにする必要があります。 一方、テストボットは、リグレッションに対する最初の防御線であるため、コミットごとに実行する必要があります。 テストボットは明らかに頻繁に実行されるため、これら2つのボットを1つのボットにマージすると、サーバーのディスク領域がすぐに使い果たされる可能性があります。 また、各統合が完了するまでにさらに時間がかかります。
これで、[スケジュール]タブに移動します。これについては、前の段落ですでに説明しました。 したがって、次の関心のあるトピックはコード署名です。 テストターゲットで、プロジェクト設定ページにプロビジョニングプロファイルが不要であると記載されている場合でも、ホストアプリケーションと同じチームと署名証明書を使用するように設定する必要があることに注意してください。 これは、シミュレーターだけでなくiOSデバイスでアプリをテストする場合に必要です。 この場合、テストに使用されたiOSデバイスが非アクティブでロックされないようにする必要があります。これにより、通知なしに統合の実行が無期限にハングする可能性があります。
これで、特に説明する必要のない[デバイス]タブが表示されます。 コードをテストするデバイス(iOSおよびシミュレーター)を1つ、複数、またはすべて選択するだけです。 複数のデバイスでテストを並行して実行するか、順次実行するかを確認することもできます。 これを設定するには、プロジェクトのニーズ(特定のデバイスのセットをターゲットにしているのか、サポートされているすべてのiOSデバイスをターゲットにしているのか)とサーバーのハードウェアリソースを考慮する必要があります。
[引数]タブ。 組み込みの環境変数のみを使用するため、明示的に指定する必要はありません。
最後に、[トリガー]タブで、1つの統合前スクリプトと1つの統合後スクリプトを紹介します。 1つ目は、問題が発生した場合に備えてデバッグを支援するためのものです。 これは実際に私たちがすでに使用したものです:
#!/bin/sh set printenv
2つ目は、現在の統合で1つ以上のテストが失敗した場合に通知するものです。 テストが失敗した場合にのみ実行するように設定されていることを確認してください。 そして、次のように入力します。
#!/bin/sh echo "$XCS_TEST_FAILURE_COUNT test(s) failed for $XCS_BOT_NAME bot on build $XCS_INTEGRATION_NUMBER" echo "You can see bot integration at:" echo "https://$HOSTNAME/xcode/bots/$XCS_BOT_TINY_ID/integrations/$XCS_INTEGRATION_TINY_ID"
ここで説明する必要があることがいくつかあります。 まず、$ HOSTNAME変数は、computer-name.localの形式の値を格納します。 明らかに、リンクは、ローカルネットワーク経由でそのサーバーに到達できる場合にのみ機能します。 また、このリンクは信頼できない宛先へのhttps接続であるため、このリンクにアクセスすると、ブラウザからセキュリティ警告が表示される可能性があります。 最後に、これは「テストの失敗」スクリプトの開始点にすぎません。 開発チーム全体にメールを送信するか、APIリクエストまたは最も適切で生産的であると思われるその他の方法でJIRAの問題を開くことができます。
まとめ
うまくいけば、この記事が、単にアプリを構築するだけでなく、時間をかけてXcodeサーバーの機能を探求することをお勧めします。 この投稿は、あなたが望んでいた、または期待したとおりには役に立たなかったかもしれませんが、目標は、組み込み環境とXcodeサーバー変数を使用してより高いレベルの自動化を実現するオープンマインドな方法を紹介することでした。
より多くの機能を有効にし、Fabric、Bluepill、Fastlaneなど、より多くの作業を実行できるサードパーティのサービスがたくさんあります。 ただし、必然的に、サードパーティに依存すると、プロジェクトに新しい依存関係が導入され、場合によっては単純な、場合によっては複雑なセットアップと構成が必要になります。 ここで説明する手法では、すべてのMacにすでにインストールされているツールのみが必要であるため、自動ビルドを実行するボットを構成する以外に、セットアップ時間は必要ありません。