Yodeee's Tech Diary

日々の開発や勉強したことをつれづれなるままに

AWS CodeCommitとJenkinsでiOSのCI/CD環境を作る

始めに

最近、iOSアプリ開発に関わることになり、とある事情からiOSのCI/CD環境をローカルのMac端末で構築する必要がありました。

類似の事例をWebで探したのですが、該当する事例は少なかったので、備忘のためにも手順を本記事で紹介したいと思います。

1. iOSのCI/CDについて

現在、iOSアプリのCI/CDとして、利用できそうな方法は以下のとおりです。

特に制約がなければ、SaaSに記載したサービスを使用すれば十分です。

しかし、今回リポジトリ管理で使用してAWS CodeCommitをサポートするSaaSが存在しなかったことや、とある理由からでSaaSが使用できないという制約が存在したことから、泣く泣くCI/CDを時前で構築することとなりました...

 

このような背景から、必然的にMac OSがインストールされたサーバの用意が不可欠となり、Xcode Cloud、MacインスタンスMac端末から選択する必要がありました。

まずXcode Cloudについてですが、こちらもSaaSの理由と同様にCodeCommitとの連携がサポートされていなかったため、今回は候補から外しました。

次にMacインスタンスについてですが、自前でCI/CD環境を一から作る必要があるものの、CodeCommitとの連携もJenkinsを使用すれば可能です。

しかし、問題としては料金がかかりすぎてしまうことで、Macインスタンスの最小割当期間が24時間と設定されており、一回起動あたり最低でも約4000円ほどかかってしまいますMacインスタンスは、実際には物理マシン自体が割り当てられているので、この料金も頷けます)。

 

上記の理由から、消去法でローカルのMac端末上でJenkinsでCI/CD環境を構築する方針となりました。

次に、この方針に沿って実際に構築した内容を紹介したいと思います。

2. 全体構成

全体構成は以下の通りです。 CodeCommitにソースがPushされると、

Mac上のJenkinsサーバのジョブが更新を検知後、大きく分けて、下記の順番で処理が実行されます。

 

ソースを取り込み → 単体テスト → UIテスト → ビルド → Firebaseにアップロード

 

上記のフローの中で、単体テスト完了後にCoverage情報をSlackに通知するようにしており、

UIテストで取得したアプリ画面のキャプチャ情報はS3にアップロードするようにしています。

最後にFirebaseにアップロードが完了するとSlackに通知されるようにしています。

3. 手順

3-1. 前提

  • Apple Developer Programに登録してあること(有料版ではないとビルドファイルが作成できません)
  • Apple Developer内でAd hoc配信用の証明書、プロビジョニングプロファイルを作成済みであること
  • Mac端末を用意していること
  • Macに以下がインストール済みであること
    • java (java -versionで確認)
    • HomeBrew
    • Git (未インストールでがあればこちらを参照)
  • AWSアカウントを用意してあること
  • AWS CodeCommitでリポジトリが作成済みであること

3-2. Firebaseの設定

今回はFirebase App Distributionを使用して配信します。

まずはFirebaseをAppleプロジェクトに追加します。

こちらの公式の記事を参考にしてください。

3-3. Fastlaneファイルの作成

次にfastlaneの設定を行います。

設定はこちらの公式の記事を参考にしてください。

ここで注意いただきたいのが、今回自動で配信を行うため、

手順2のFirebaseの認証方法はサービスアカウントの認証情報を使用するにしてください。

またご参考までに私が作成したFastfileは以下の通りです。

3-4. (オプション)fastlane snapshotの追加

XCUIテストを実行し、各アプリ画面のスクリーンショットを作成したい場合、 fastlane snapshot機能を使用します。

導入の手順は以下が参考になります。 an.hatenablog.jp

また私は証跡をS3にアップロードするようにしています。

fastlaneのすべての処理が終わったタイミングでS3に本日の日付のディレクトリを作成し、 アップロードするようにしておりました(下のソースのshの箇所)。

※S3にアップロードするためには事前にバケットを事前に作成しておく必要があります。

3-5. Jenkinsのセットアップ

次にJenkinsのセットアップを行います。 Jenkinsをインストールをインストールすために、 Terminalを開き以下のコマンドを実行します。

brew install jenkins

Jenkinsを起動するために以下のコマンドを実行します。

brew services start jenkins

http://localhost:8080にアクセスすると準備中の画面が表示されます。

画面の中部に記載されているパスにパスワードが保存されているため、 以下のコマンドで表示されたパスワードをフォームに入力する。

$ cat /Users/[username]/.jenkins/secrets/initialAdminPassword

Customize JenkinsはInstall suggested pluginsのままで。 後ほどGit, CodeCommit用のプラグインをインストールします。

 

次に進むと、セットアップのステータスが表示されます。

 

セットアップが終了すると、ユーザ登録画面に移りますので、

ユーザ情報を入力します。

 

次の画面では必要があればJenkinsのURLを変更します。 特に変更する必要がないのでこのままで次に進みます。

 

Start using Jenkinsをクリック

 

ホーム画面に遷移します。 まずは環境設定を行います。

 

左のメニューから「Jenkinsの管理」を選択 管理画面で「システムの設定」をクリック

 

システム設定ページでグローバルプロパティにて環境変数を選択→追加ボタンをクリック。

キーにはPATHを値には$PATH:/usr/local/binを入力する。

※git-remote-codecommitが格納されているディレクトリのパスを指定する必要があります。わからなければ以下を実行。

which git-remote-codecommit

 

入力後「保存」をクリック。

3-6. Jenkinsでジョブの作成

トップページに戻り、「Create a job」を入力

 

ジョブ名を入力します。

ビルドの種類は「フリースタイル・プロジェクトのビルド」を選択したまま、「OK」をクリック。

 

Generalには特に設定は不要。

 

ソースコード管理ではGitを選択後、リポジトリURLにはcodecommit://[リポジトリ名]を入力。

ビルドするブランチには今回のビルド対象となるブランチ名を入力してください。

その他の設定はデフォルトで大丈夫です。

 

ビルド・トリガには今回は定期的にCommitがあるかをポーリングする方式にするため SCMをポーリングを選択して、Cron式を入力します。

今回は2分に一度ポーリングする方式にしたため、H/02 * * * *としました。

 

ビルド環境はデフォルトのままです。

 

次にビルドするために必要なコマンドを設定します。

「ビルド手順の追加」→「シェルの実行」を選択

GOOGLE_APPLICATION_CREDENTIALSのパスはfirebase-app-dist.jsonを格納したパスに変更してください。 

 

export LANGUAGE=en_US.UTF-8
export LC_ALL=en_US.UTF-8
export GOOGLE_APPLICATION_CREDENTIALS=/PATH/firebase-app-dist.json

fastlane ios setup
# 不要であればコメントアウト
fastlane snapshot
# 不要であればコメントアウト
fastlane ios upload_screenshots
# 不要であればコメントアウト
fastlane ios unit_test
fastlane ios distribute

3-5. CodeCommit, S3へのアクセス設定

CodeCommitにアクセスするためにgit-remote-codecommitを使用します。 git-remote-codecommitの導入手順は以下をご確認ください。 Git 認証情報を使用した HTTPS ユーザーのセットアップ - AWS CodeCommit

またS3へのアクセスはIAMプロファイルの設定を行う必要がありますが、上記の手順で プロファイルの設定も行うため、個別設定は不要となります。

検証

それではどのように動作するのかをお見せいたします。

CodeCommitのブランチにPushをすると、 Jenkins上で対象のプロジェクトを確認すると右下の履歴でジョブが実行中であることがわかります。

ジョブが失敗していた場合は、対象の履歴からコンソール出力を見ることでデバッグログを見ることができます。

ジョブの完了後、Firebase App Distributionにアップロードされているかを確認します。

Firebaseコンソールにログインをして、App Distiributionを開くと、最新版がアップロードことが確認できました!

またFastlane内で指定したメールアドレスにも配信メールが届いており、 そのリンクからアプリをダウンロードすることができました!

ちなみにSlackにはこのように各プロセスが完了すると通知が届くようになっています。

xcovを設定しているとUIテストのカバレッジも通知してくれます。

まとめ

今回はMac端末をビルドサーバとするような構成でのiOS CI/CDパイプラインを紹介いたしました。 本来であれば、手間の少ないSaaSを使うことがベターだと思いますが、 SaaSを使えないような制約がある場合は、今回の構成が参考になるかもしれません。