見出し画像

Xcode Cloud を試してみたけど、まだダメだった

おはようございます。note の watura です。WWDC で Apple Developer Program 契約者向けに公開された Xcode Cloud を試してみました。
結論からかきますと、現状では note で Xcode Cloud をメイン CI/CD に据えることはできないとなりました。


投稿前なのに追記:この記事を下書きに保存して、さあ投稿するぞ!という気分になっていたときにサブスクリプションができるようになりました。 サブスクリプションのみではなく若干AppStoreConnect側のUIも変わっていそうな雰囲気なので、バギーだった部分がどうなっているのかとか調査中です。

https://developer.apple.com/news/?id=5hlzzu3u

Xcode Cloud とは

Xcode Cloudは、Xcodeに組み込まれた継続的インテグレーションおよびデリバリーサービスで、Appleデベロッパのために設計されたものです。Appの構築、複数の自動テストの並列実行、テスターへのAppの配信、ユーザーフィードバックの表示と管理に役立つ、クラウドベースのツールをまとめて提供することで、高品質のAppの開発と配信を高速化します。

Xcode Cloud とは↑だそうです。Circle CI や Bitrise などにかわるかもしれない Apple の CI/CD になります。

現在のnoteのCI/CD環境

note iOS では以下の環境で CI/CD を動かしています。

  • CircleCI

    • メインです。基本的にほとんどすべてのCI処理をしています

  • Github Actions

    • Danger 専用

  • Zapier

    • Slack などから Cicle CI をトリガーするために利用

CIで行っている処理は以下の通りです。

テスト(※)やビルドには、Fastlane を使っています。(※ ユニットテストや、 MagicPod をつかったテストの呼び出しなども含む)

  • テスト

  • Firebase AppDistribution 配信

  • ストア用ビルド & 配信

  • バージョンアップ用 Pull Request の作成

  • Danger

Xcode Cloud でやりたい処理

Circle CI で行っているテストのうち、以下の3つを Xcode Cloud 移行できるといいなと考えています。

  1. ユニットテスト

  2. TestFlight 配信

  3. ストア配信

をやるようにしました。

実際には1, 2を行うことにしました。Xcode Cloud のワークフローをポチポチやっていくだけでほぼほぼできたので、導入自体の操作は簡単でした。(後ほど実行してみたときの苦労ポイントを紹介します)

  • Slack と連携

  • 特定のファイルが更新されたら実行

  • 特定のブランチが更新されたら実行

ただ、テストでつかう端末の設定が、Xcode からだとリセットされるパターンがあったので、そこだけは App Store Connect から設定したりしました。基本的にドキュメントはまとまっていますし、Xcode Cloud はなかなかいいヤツでした。

Xcode Cloud で実行するメリット

Xcode Cloud に移行するメリットとして以下の2つがあります。ほかにも、 Xcode 上で結果をみたりできるとかはありますが、わざわざ移行するほどの理由にはなっていないと考えています。

  1. 費用

  2. Provisioning や Certificate 管理の簡略化

それでは、説明していきます。

1. 費用

以下の Zaim さんの記事にいろいろな iOS 関連で使える CI の料金がのっています。

この記事では、6,000 分/月 という数値で試算されていました。たとえば、Bitrise で 6,000分つかうと、$725 くらいだそうです。
さて、ここで Xcode Cloud の料金表を見てみましょう。

Xcode Cloud の料金表

先ほどの試算が 6000 分なので、hours に換算すると 6000 / 60 = 100 hours です。 Bitrise だと $725 かかるところが、 $49.99 ですんでしまうのです。1/10 未満です。
ただし、Xcode Cloud は iOS/Mac アプリに関する内容、かつ、Test や Deploy など必ず実行するワークフローであるというような制限があります。
なので、Fastlane などをつかって各社に最適化されたワークフローを実行するよ!みたいな用途には使えません。

2. Provisioning や Certificate 管理の簡略化

Fastlane をつかっている場合、 Match や Cert などをつかって証明書/プロビジョニングの管理をしなければなりません。Fastlane をつかってデプロイとかの自動化をやる上で、このあたりの管理はだいぶましになったものの、今もややこしいです。

しかし、 Xcode Cloud では AppStore Connect と統合されているため、デプロイにかかわる面倒な証明書関係を丸投げできます。
とくに、何も考えずにワークフローを設定していくだけで TestFlight に登録できます。

Xcode Cloud で 「Test Flight 配信」、「テスト」を実行したときの苦労ポイント

XcodeGen

note では、XcodeGen をつかって xcodeproj を管理しています。

xcodeproj は毎回生成されるので、Git には含めていません。そのため、Xcode Cloud でも XcodeGen をつかって生成する必要があります。
ci_scripts/ci_post_clone.sh というファイルをつくると、Git Clone したあとにスクリプトを実行できるので、clone 後に XcodeGen, Cocoapods をインストールしています。

mkdir gem
export GEM_HOME=$(pwd)/gem
export PATH=$GEM_HOME/bin:$PATH
gem install cocoapods --no-document
pod repo update

git clone --depth 1 https://github.com/yonaskolb/XcodeGen.git
cd XcodeGen
swift run xcodegen -r $CI_WORKSPACE -s $CI_WORKSPACE/project.yml

xcodegenやcocoapodsを brewを使ってインストールするのが定番だと思うのですが、brew の更新がはいったりするため、非常に遅いです。そのため、今は 直接インストールするという方法をとっています。

Files you create with a custom build script aren’t available to other custom build scripts, and Xcode Cloud deletes any files a custom build script creates. As a result, downloadable Xcode Cloud build artifacts don’t include files you create with custom build scripts.

スクリプトでつくったファイルは別のフェーズには残らないそうなので、注意が必要です。xcodeproj とかも消えてしまうのではないか?と思っているんですが、よく確認していません。少なくとも、うごいているようなので大丈夫なのかな?という認識で動かしています。

こちらも、詳細がわかりきっていないのですが、手元やGym では問題なくビルドできるし、デプロイできるのに Xcode Cloud では以下のエラーが発生するというパターンに悩まされていました。

ITMS-90334: Invalid Code Signature Identifier. The identifier "SwiftDate-55554944c4f0bf16d4d834a0b292bfb48fddd14a" in your code signature for "SwiftDate" must match its Bundle Identifier "SwiftDate"

複数のターゲットで SwiftDate を依存関係にいれていたので、一番根元となるターゲットでのみ、SwiftDate をリンクするようにして、それ以外のターゲットでは以下のように設定したところ動くようになりました。
ただしい、設定方法があればしりたいです。

      - package: SwiftDate
        product: SwiftDateStatic
        embed: false
        codeSign: false
        link: false

Snapshot Testing

note ではアプリのテストの一環として Snapshot Testing を行っています。

上記のスクリプトがつくったファイルとかは消すぜ!の一環の影響とおもわれるのですが、snapshot testing で使う画像がみつからないという問題がありました。

Gist 内のリンクにあるコードをベースにいじったコードとなっています。

  1. SnapshotTestArtifacts 以下にスナップショット画像を保存するように変更

  2. ci_scripts/SnapshotTestArtifacts に SnapshotTestArtifacts への symbolic link を作成

  3. CI から assertSnapshot を呼び出すと、ci_scripts/SnapshotTestArtifacts からスナップショット画像を取得する

という流れになっています。

結論

Xcode Cloud をつかって「Test Flight 配信」と「テスト」を実行したときにでてきた、苦労ポイントについて書いてみました。
将来的には、リリース用ビルドを行ったりしていきたいと考えています。
残念ながら、本記事の時点では Xcode Cloud に課金する仕組みが用意されておらず、25時間しかつかえません。
Push ごとや PR ごとにテストを行うとまったくたりない状態になってしまい、本番運用はまだまだできない状態となってしまいました。

というわけで、 Xcode Cloud をためしてみましたが、25時間では少なすぎて使えませんでした。という結論になります。

もりもり課金ができるようになったら、Circle CI から移行を本格的に考えていきたいと思っています。ただし、Xcode Cloud では任意の処理をなんでもできるというわけではなく、アプリのテストや配信といった処理を必ず行う必要があるので、完全移行とはならないと考えています。

追記:25時間以上つかえるようになったので、Xcode Cloud のテストが安定稼働してくれているか確認したらサブスクリプション契約してください!ってお願いすると思います。



それでは、いつもの定番

note は iOSDC Japan 2022 に協賛しているのですが、実家の珈琲を note グッズとして準備しました。おいしいコーヒーですので、iOSDC に参加する方は飲みながらテックxトークを楽しんでください。

 

 
 


note コーヒー のとしはる珈琲もよろしくおねがいします。
購入時の備考欄に iOSDC の記事みたよ!とか note コーヒーのんで買いました!書いてくださったらおまけがつきます!
また、うちでもオリジナルデザインのドリップパックとか作りたいんだけど!っていうお話があれば、ぜひ、私に連絡をとってください。デザインはできませんが、コーヒーグッズ作り協力します!