iOSで構築しているCIのWorkflow紹介

こんにちは。iOS担当の荒井です。 今回はiOSチームで構築しているCI/CDのWorkflowについて紹介します。

CI/CD環境

はじめに、ZOZOテクノロジーズのiOSチームがどのようなCI/CD環境を整えているかを簡単に説明します。ZOZOテクノロジーズではZOZOTOWNやWEAR、プライベートブランドZOZOなど様々なサービスを運営しています。プロダクトによりCI/CD環境は違うのですが、多くのプロダクトでBitrise + DeployGateという構成をとっています。今回お話するWorkflowもBitriseを例に紹介していきます。

Bitrise

多くのCIサービスが存在していますが、以下の理由でBitriseを選定しています。

  • 導入時、利用目的に対して価格面が見合っていた
  • Xcodeバージョンアップへの対応速度
  • 日本市場に注力

日本市場に注力していくという話もあり、今後サポートに期待が持てます。 最近では日本語の記事も掲載されています。

DeployGate

TestFlightやFabricを使っている方も多いと思いますが、弊社のiOSチームはDeployGateを選択しています。元々CI/CDの環境が整っていないプロダクトが多かったため、環境構築を進めるにあたり、会社としてAndroidチームで運用実績があるDeployGateにしました。プロダクトをまたいでテストを行うチームが存在するため、ツールは統一しようといった理由があります。

Workflow

それではWorkflowの話に移ります。 WorkflowはStepと呼ばれる定義済みスクリプトをまとめたものです。例えば「Carthageコマンドを実行する」には「Carthage」というStepを設定します。BitriseではGUIで簡単にSetpを追加し目的に応じたWorkflowを組むことができます。今回は以下のようなフローを例に、自動化する際どのようなWorkflowを組んでいるかを紹介します。

  1. エンジニアがGitHubにコードをPush
  2. GitHubへのPushをWebhook
  3. Workflowの実行
  4. DeployGateへのアップロード
  5. Slackへ完了通知

よくある「エンジニアがコードを書いてGitHubにPushしたら、テストが実行され、アーカイブしてQAに配布する。終わったらSlackに通知する」というものです。実運用ではPushのたびに配布をしていたら頻度が高いため、PullRequestの生成タイミングなど、目的に応じてトリガーを設定しています。

上記のようなフローを構築する場合、Bitrise上で以下のようなWorkflowが考えられます。

  1. SSH keyの登録
  2. リポジトリのクローン
  3. ビルドキャッシュのダウンロード
  4. 証明書のインストール
  5. Carthageコマンドの実行
  6. キャッシュの更新
  7. スクリプトの実行
  8. テストの実行
  9. アーカイブ
  10. DeployGateへのアップロード
  11. Slack通知

しかし弊社ではこれらのStepのほとんどをfastlaneに任せています。

fastlane

fastlaneはアプリの様々な作業を簡単に解決してくれるツールです。冒頭のフローを実装するのに必要となる「ビルドに必要な証明書類の管理」「DeployGateへのアップロード」などはすべてfastlaneで行なっています。fastlaneを使用すると以下のようなWorkflowになります。

  1. SSH keyの登録
  2. リポジトリのクローン
  3. ビルドキャッシュのダウンロード
  4. Carthageコマンドの実行
  5. キャッシュの更新
  6. スクリプトの実行
  7. fastlaneの実行

fastlane以外のStepスクリプトを使用しない理由は、CIサービスの移行を容易にするためです。他のCIサービスに魅力的な機能が出たり、何かしらの理由でCIサービスを変更しなくてはいけない場合でもfastlaneに処理を寄せておけば移行がスムーズになります。Bitrise上ではCode Signingの設定もせず、出来ることは可能な限りfastlaneにしています。サンプルのフローを例にSlackへ通知するまでのfastlaneの実装を紹介します。

証明書のインストール

iOSに関わる証明書などのファイルは暗号化されGitHubで管理しています。fastlaneではアクションという形で様々な機能が提供されており、証明書の管理はfastlaneのmatchというアクションを使って実装しています。今回は詳しく触れませんが、証明書の管理はGitHubにしておくと何かと便利です。まだすべてのプロダクトで使用しているわけではないので現在対応を進めています。

テスト

テストにはscanというアクションを使用します。 fastlaneの処理はFastfileという設定ファイルに記述して実装していきます。

lane :test do
  scan(scheme: "SCHEME-NAME", clean: true, skip_slack: false)
end

FastfileはRubyで記述していくことになりますが、ドキュメントも充実しており、Rubyに馴染みのないiOSエンジニアでも記述に困らないと思います。Swiftでの記述もサポートがあるため、こちらを試しても良いかもしれません。

アーカイブ

アプリケーションのビルドサンプルです。ビルドにはgymというアクションを使用しています。

private_lane :build do
  match # 証明書のダウンロード
    gym(scheme: "SCHEME-NAME",
      configuration: "InHouse",
      clean: true,
      export_method: "enterprise"
    )
end

DeployGateへのアップロード

DeployGateへのアップロードもfastlaneです。私たちはDeployGateを使用していますが、TestflightやFabricなどのアクションも揃っています。

private_lane :deploy_gate do | options |
  target = options[:release] ? "release" : "development"
  deploygate(
    api_token: ENV["DEPLOYGATE_API_TOKEN"],
    user: "DEPLOYGATE-USER",
    ipa: "./#{target}.ipa",
    message: last_git_commit[:message]
  )
end

Slack通知

全員が業務でSlackを使用しているため、何かの処理が終わった場合にはSlackで通知するように組んでいます。プロダクトに影響しない処理はサービス間で同じ設定を使うこともあります。 手元のテストでSlack通知が行われないように、CI上のみで通知をすることが多いです。

before_all do
  ENV["SLACK_URL"] = "WEBHOOKURL"
end

after_all do | lane |
  if is_ci?
     slack(message: "Test Successfully")
  end
end

error do | lane, exception |
  if is_ci?
    slack(
      message: exception.message,
      success: false
    )
  end
end

Bitriseに設定するlane

Bitriseに設定するlaneを作成します。

lane :deliver_qa do
  build
  deploy_gate(release: false)
end

今回はビルドとデプロイのみにしていますが、 他にもビルドバージョンやGitタグなどもfastlaneで自動化できます。

fastlane運用をしてみての利点

すでにCircleCIからBitriseに移行したサービスがありますが、基本的にfastlaneで書いてあったため移行はとてもスムーズでした。CI上の細かな設定を確認せずとも、fastlaneの設定ファイルであるFastfileを確認すれば処理の流れが把握出来るのも利点だと思います。また、fastlaneによるコードでの記述を行なっていれば、プロダクトをまたいで設定ファイルを簡単に共有できるメリットもあります。CI上でGUIによるWorkflow構築は簡単ですが、コードで記述していくメリットも十分あるように感じています。

まとめ

今回はiOSチームで構築しているWorkflowについて紹介しました。CI/CD環境は随時改善を進めており、どのチームも自動化を目指しています。まだまだ改善の余地があり今後も注力していきたいと思います。CI/CDに興味があり、自動化が好きな方下記よりご応募お待ちしております。

www.wantedly.com

カテゴリー