この記事は、リレーブログ企画「CI/CDリレーブログ」の記事です。
はじめに
初めまして!
マイ ニフティチームの寺島です。
普段はスマートフォン向けのアプリケーション開発に携わっています。
ブログ運営チームのメンバーでもあります!
今回はリレーブログのアンカーとして、ブログチーム代表として走らせていただきます!
CI/CDのリレーブログを盛り上げるという大いなる目的のために、前々から気にはなっていたのだけれど中々重い腰を上げられなかった、Xcode CloudのCI/CDを体験してそれをブログにしてみました!
一石二鳥ですね!!
そもそもXcode Cloudとは
Xcodeと呼ばれるApple製のIDEを利用して、CI/CDを簡単に行えるようにするサービスや仕組みのことです。
Xcode Cloudは、Xcodeに組み込まれた継続的インテグレーションおよびデリバリーサービスで、Appleデベロッパのために設計されたものです。アプリのビルド、複数の自動テストの並列実行、テスターへのアプリの配信、ユーザーフィードバックの表示と管理に役立つ、クラウドベースのツールを一か所で利用できるため、高品質なアプリの開発と配信が高速化されます。
https://developer.apple.com/jp/xcode-cloud/
目指す形
TestFlightの公開まで目指します!
コード変更→mainへ反映→反映の検知→テストの実行→TestFlight公開
の流れにしたいと思います。
今回は、iOSアプリで確認したいと思います。
前提条件
- GitHubを利用します
- ブランチはmainブランチのみを利用します
- Xcode Cloudを利用します
- Apple Developer Programに参加したアカウントを利用します
- iOSアプリの作成を確認します
事前準備
- 新しいプロジェクト(iOSアプリ用)を立ち上げます。
- GitHubのリポジトリも新規に用意します。
- 簡単な表示を行うViewと、表示に使用するメソッドのテストを作成します。
- 作成したコードは用意したリモートリポジトリにPushします。
初回は、リポジトリの紐付けを行うとWorkflowが実行されBuildされます。
初回以降は、mainブランチの変更を検知or手動でWorkflowが実行されるようになります。
ディレクトリ構成(完成系イメージ)
こちらはあくまでイメージとなります。
Xcode上で表示されるファイルと合わせた形になります。
またInfo.plistは設定を入れていないと表示されないので、プロジェクト立ち上げ時になくても問題ありません。
後の手順で設定を行うと出てきます。
1 2 3 4 5 6 7 8 9 10 |
. ├── SampleProject006 │ ├── Info.plist │ ├── Preview Content │ ├── Assets.xcassets │ ├── ContentView.swift │ └── SampleProject006App.swift └── SampleProject006Tests └── SampleProject006Tests.swift |

利用コード
ContentView
helloメソッドの戻り値をTextでViewに表示するようにしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import SwiftUI struct ContentView: View { var body: some View { VStack { Text(hello()) } } } func hello() -> String { return "Hello, Swift!" } #Preview { ContentView() } |

SampleProject006Tests
helloメソッドの戻り値がHello, Swift!
であることを確認するテストです。
1 2 3 4 5 6 7 |
import Testing struct SampleProject006Tests { @Test("一致することをテスト") func match() { #expect(hello() == "Hello, Swift!") } } |

GitHubへ反映
今回はmainをそのまま変更→Pushする形で確認します。
リモートブランチへ新しいプロジェクトをPushしておきます。

Xcode Cloudを試してみる
- Xcode Cloudをリモートリポジトリへ紐づける
- Buildを確認する
Xcodeとリポジトリの紐付け
- XcodeからXcode Cloudを利用したいプロジェクトを選択します
- Workflowはデフォルト設定のままにします
- 利用している開発者アカウントをXcode Cloudが利用できるようにします
- 開発者アカウントとGitHubの組織を紐づけます
- 紐づけた組織内のリポジトリと連携します
Xcodeのサイドバーから「Get Started…」を選択します。

新しいウィンドウが立ち上がるのでプロダクトを選択し、「Next」を選択します。

Workflowの詳細設定についての項目が選択できるウィンドウが表示されますが、今回こちらはデフォルトのまま先に進めます。(後ほどweb上で設定を行います。)
「Next」を選択します。

ここでリポジトリを選択するウィンドウが表示されます。
「Grant Access…」を選択します。(次からXcode以外での設定になります。)
自動でブラウザが立ち上がってきます。

まずはApp Store Connectへログインします。

Xcode CloudをGitHubに接続する画面が表示されます。
ここから、具体的なアカウントへGitHubへの接続の許可と、リポジトリの紐付けを行なっていきます。
「GitHubでステップ1を終了する」を選択します。

今度はGitHubのページが開きます。
Xcodeをインストールしたい組織を選択します。
ここで選択するのは、先ほど作成したリポジトリの所属する組織です。

さらに、リポジトリを選択します。
「All repositories」ですべてのリポジトリへのアクセスを許可するか、「Only select repositories」で特定のリポジトリのみに権限を与えるかを選択します。
今回は、Allで与える理由が特にないので先ほど用意したリポジトリのみに許可を与えます。
選択したら「Install」を実行します。

「Install」選択後、正常に接続されましたと表示したら完了です。

Xcodeに戻って、先ほど紐付けを行ったリポジトリに緑のチェックマークが入っていることが確認できます。

アプリを一度もApp Store Connectへ連携していないと、初回に作成を確認するダイアログが表示されます。
作成しないとXcode Cloudは利用できないので、「Complete」で作成を許可します。

最後に、「Start Build」で完了です!
これで、Xcode Cloud上でBuildが走ります。
今回は特にWorkflowを設定していないので、シンプルなBuildが実行されて終了します。

App Store Connectで確認すると下記のような画面になります。
ステータスに緑のチェックマークが入っていれば無事にBuild完了です。
Xcode CloudとGitHubのリポジトリが正しく連携できています。


Xcode Cloudの設定を変えて試してみる
無事に連携できたので、色々試してみたいと思います。
- TestFlightへ自動で公開するように設定を変更します
- Build時にテストを実行するように設定を変更します
- テストの項目を増やします
- 変更内容をmainへpushします
- 実行内容を確認します
- TestFlightへの公開が失敗しているので、修正して再度Buildします
- 実行内容を確認します
App Store ConnectのXcode Cloudタブのサイドバーから「ワークフローの管理」を選択します。
今回作成したワークフローである「Default」を選択します。

Defaultワークフローの設定ページへ遷移するので、アクションセクションの中からアーカイブ項目を選択します。
デフォルトでは配信準備が「なし」に設定されていますので、今回の目標である「TestFlight(内部テストのみ)」を選択します。

続いてテストの実行を追加します。
アクションセクションのタイトルの横にある「+」マークをクリックして「テスト」を選択します。

新しい、テストに対する入力欄が追加されるので必要項目を入力していきます。
下記の画像のようになるようにします。
基本的には、最初に作成したテストについて適用していく形になります。

テストコードを追加します。
helloメソッドの返す値が一致しないことを確認するテストを追加します。
1 2 3 |
@Test("一致しないことをテスト") func doesNotMatch() { #expect(hello() != "Hello, World!") } |

変更をcommitしてmainブランチをpushします。
mainブランチ以外で作業している場合は、mainブランチへmargeします。
mainが更新されるとWorkflowが実行されて、先ほど追加した「TestFlight」への公開と「テストの実行」が行われます。

今回は失敗します。
失敗の原因を確認します。

ステータスの赤丸バツ印マークをクリックすると詳細ページへと遷移します。
先ほど追加したテストは問題なく実行が完了してそうです。
Archiveでエラーが出ているみたいなので、「Archive – iOS」をクリックして中身を確認します。

中身を確認すると詳細なエラー内容が表示されます。
今回は、TestFlightに公開を行うのにアプリケーションにアイコンを設定していないのが原因のようです。

AssetsからApplconを追加します。

再度、変更をリモートリポジトリのmainブランチに反映するとWorkflowが実行されます。
今度は成功することが確認できます。
ですが…

TestFlightへの公開は行われていないようです。

アプリの暗号化書類について、予め選択していないと公開までは進みません。

今回は、独自のアルゴリズムで暗号化を行っていないので、Info.listに設定を追加して、TestFlightまで公開されるようにします。App Uses Non-Exempt Encryption
を追加して、値を「NO」にします。

変更をリポジトリのmainへ反映します。
DefaultのWorkflowを確認してみると、Buildは成功しています。

TestFlightの方も見てみると、公開までされていることが確認できます。

さいごに
以上で、Xcode Cloudの基本的な動作の体験は終わりになります。
お付き合いいただきありがとうございました。
全てのCI/CD設定がGUIで完了するのは分かりやすくとても良いと思いました。
今回の体験を基に複雑な処理など追加して、CI/CDをより使いやすくカスタマイズして、アプリ開発の効率を上げていきたいですね。(願望)
リレーブログ企画「CI/CDリレーブログ」は、この記事で終了となります。執筆に協力していただいた皆さん、見てくださった皆さん、ありがとうございました。