Studyplus Engineering Blog

スタディプラスの開発者が発信するブログ

fastlaneでCode Signing StyleをAutomaticからManualに変更する

はじめに

Studyplus開発部のiOSエンジニアの id:kurotyann です。2015年に入社してもうすぐで3年になろうとしています。

今回の開発者ブログは、弊社のiOSアプリ「Studyplus」 のCI環境について紹介しながら、fastlaneでCode Signing Styleを変更する方法を説明します。

Studyplus iOSのCI環境

図で説明すると下記のような構成です。他にもツールを使用していますが、基本的な流れはこのような感じです。

CI環境の構成

Code Signing Styleについて

Code Signing Styleは、XcodeのプロジェクトのBuild Settingsから確認でき、AutomaticとManualの2種類を選択できます。Automaticの場合、Xcodeが適切なタイミングで開発に必要な証明書やProvisioning Profileの関係を解決してくれます。Manualの場合、開発者が任意の証明書やProvisioning Profileを指定することが可能になります。

XcodeのCode Signing Style

Code Signing StyleをAutomaticからManualに変更したい理由

Appleが推奨する設定は、Automaticです。しかし、AutomaticのままだとCI環境で意図したとおりに証明書やProvisioning Profileを参照してくれないことがあります。

またCIサービスが不調で動作しないとき、ローカルからfastlaneを起動したいことがたまにあります。そのときMacに複数の証明書やProvisioning Profileがあると、適切な証明書やProvisioning Profileを参照しないことが起きます。

このようなあらゆる事態に対応できるようにfastlaneで確実に任意の証明書やProvisioning Profileを指定させたい。Code Signing Styleのローカル環境とCI環境の切り替えをスムーズに管理したい、というのが今回のブログの主旨です。

ローカル環境(デフォルト設定)をAutomaticにしておき、fastlaneを使ってManualに変更するメリットは以下のようなものが考えられます。

  • fastlane matchで取得したProvisioning Profileを確実にManualで指定すると、ビルドエラーの可能性を減らせる
  • デフォルト設定はAutomaticなのでDebugで開発する場合、証明書を共有する必要がない
  • 外部から短期で開発に参加するエンジニアをApple Developerのmember権限でTeamに追加できる
    • デフォルト設定をManualにすると証明書の共有や権限の変更などが必要になる
    • adminは権限が大きすぎて短期で開発に参加する人の権限としてふさわしくはない

fastlaneでCode Signing Styleを変更する

必要な処理を書いたFastfileを書きます。

このFastfileは、Debugの証明書とProvisioning Profileをmatchで取得して、Code Signing StyleをManualに変更します。その後、Debugビルドでエクスポートしてcrashlyticsのbetaに送信します。

default_platform(:ios)

platform :ios do
  before_all do |lane, options|
    ENV["CRASHLYTICS_API_TOKEN"] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
    ENV["CRASHLYTICS_BUILD_SECRET"] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
    ENV["FASTLANE_USER"] = "test@example.com"
    ENV["FASTLANE_PASSWORD"] = "hogehoge"
    ENV["MATCH_PASSWORD"] = "fugafuga"
    ENV["MYAPP_ID_DEBUG"] = "com.mycompany.myapp"
    ENV["MYAPP_EXTENSION_ID_DEBUG"] = "com.mycompany.myapp.myappextension"

    if is_ci?
      setup_circle_ci
    else
      cocoapods
    end
    carthage(command: "bootstrap", platform: "iOS", use_binaries: false)
  end

  #####################################################
  ###### Private Lane                             #####
  #####################################################

  # 証明書の取得
  private_lane :certificate_development do |options|
    match(
      app_identifier: [ENV["MYAPP_ID_DEBUG"],
                       ENV["MYAPP_EXTENSION_ID_DEBUG"]],
      type: "development",
      force_for_new_devices: true,
      force: options[:force]
    )
  end

  # TodayExtensionなどターゲットが複数ある場合は各々指定して変更する
  private_lane :change_code_signing_style do |options|
    automatic_code_signing(
      targets: "MyApp",
      code_sign_identity: options[:code_sign_identity],
      profile_name: options[:my_app_profile_name],
      use_automatic_signing: options[:use_automatic_signing]
    )
    automatic_code_signing(
      targets: "MyAppExtension",
      code_sign_identity: options[:code_sign_identity],
      profile_name: options[:my_app_extension_profile_name],
      use_automatic_signing: options[:use_automatic_signing]
    )
  end

  #####################################################
  ###### Public Lane                              #####
  #####################################################

  desc "Push a new beta Debug build to Crashlytics"
  lane :beta_debug do
    certificate_development(force: false)
    # Maunalに変更
    change_code_signing_style(
      code_sign_identity: "iPhone Developer: my account (12345ABCDE)",
      my_app_profile_name: "match Development com.mycompany.myapp",
      my_app_extension_profile_name: "match Development com.mycompany.myapp.myappextension",
      use_automatic_signing: false
    )
    build_app(
      workspace: "MyApp.xcworkspace",
      scheme: "MyApp",
      configuration: "Debug",
      include_bitcode: false,
      output_directory: "./Builds",
      output_name: "MyApp_Debug.ipa",
      export_method: "development"
    )
    # Automaticに戻す
    change_code_signing_style(
      code_sign_identity: "iPhone Developer",
      my_app_profile_name: "",
      my_app_extension_profile_name: "",
      use_automatic_signing: true
    )
    crashlytics(
      crashlytics_path: "./Pods/Crashlytics/iOS/Crashlytics.framework",
      notes: "fastlaneによる配布",
      notifications: true,
      api_token: ENV["CRASHLYTICS_API_TOKEN"],
      build_secret: ENV["CRASHLYTICS_BUILD_SECRET"],
      ipa_path: "./fastlane/builds/MyApp_Debug.ipa",
      notes: changelog_from_git_commits,
      groups: ["my-ios-team"]
    )
  end
end

Code Signing StyleをAutomaticからManualに変更する処理は、 change_disable_automatic_code_signingautomatic_code_signing です。automatic_code_signing にはいくつかaliasがありますが、今回は use_automatic_signing: でCode Signing Styleを変更する方法を選びました。

このFastfileはDebugですが、ReleaseやAdhocも基本的には指定する値が変わるだけです。crashlytics betaからTestFlightなど使用するツールの変更はあると思いますが、処理の順番や呼ぶメソッドに大きな変更はないと思います。

おわりに

現在、StudyplusのiOSエンジニアは id:kurotyann だけです。つまり、iOSの開発は私一人で行なっています。このような限られたリソースと時間の中で、実装と検証のサイクルをスムーズに回すにはCI環境が必要不可欠です。

このブログがCode Signing Styleの切り替えに悩んでいるエンジニアの助けになると嬉しいです。また一緒に開発してくれる仲間が弊社に増えるともっと嬉しいです。

参考資料