【fastlane】TravisCI上でmatchを実行


ローカルでfastlaneを叩いていた時は面倒がないのですが、TravisやCircleなどのCIサービスでfastlaneを利用する時は、いくつかの設定が必要になります。

意外とググっても設定が出てこないので記事にしました。

達成したこと

TravisCI上でmatchを実行しBeta配信できた

前提条件

  • ローカルはMac上で実行
  • GitHubでプロジェクトレポジトリと、プライベートの証明書管理レポジトリが存在している(中身はmatchの自動生成)
  • matchの秘密鍵を暗号化するためのパスフレーズが設定済み
  • GitHubとTravisCIとの連携が成功した状態

matchを実行するための手順

1: TravisCLIをダウンロードする
(自分の場合は sudo gem install travis -n /usr/local/bin としました)
2: travis login --pro でログイン
3: travis pubkey -r userName/projectRepoName | pbcopy で、プロジェクトレポジトリの公開鍵をクリップボードにコピー
※ 自分のユーザー名とレポジトリ名に置き換えて下さい
4: GitHubの該当の証明書管理レポジトリのDeploy keysに、クリップボードの内容を貼り付ける(GitHubのCLIで実行してもOK)

ここまでで、TravisCIから証明書管理用のprivateレポジトリへアクセスは可能になります。

5: 最後に、自身で設定した暗号化のためのパスフレーズをTravisの環境設定に追加する。

これで、証明書管理用のレポジトリから証明書やプロビジョニングプロファイルを取得することが出来ました!🎉

なぜこのようなことをする必要があるのか考えた

GitHubのsshアクセスにはDeploy keyかuser keyの2種類あって、前者はレポジトリごとのアクセスを可能とし、後者はユーザーが設定したGitHubの自分のレポジトリ全てへのアクセス可能とするのですが、TravisCIとGitHubとの連携時には、すべてのレポジトリに対して1対1のDeploy Keyが設定される形のような気がします。(GitHub上のDeploy keyの欄には出てこず、Travis上ではdefault keyというのが表示されるだけなのですが)

なので、設定をせずにTravis連携したからといってTravis上で実行されるmatchが証明書用のレポジトリにアクセスすることは出来ません。

今回のように、証明書管理用のレポジトリに公開鍵を設定するか、userkeyの秘密鍵(GitHubの全レポジトリにアクセス可能なssh key)をTravis側で設定するかしかないと思います。

感想

めんどくさかった。2度と調べたくない。一連の処理をshell化したい。
読んだ方の時間が節約できたら幸いです。

間違い等あればコメントでご指摘ください。

PS

(重要!)キーチェーンの作成が簡単にできるようになっています

ちょっと前の記事を見ていると、CI上でキーチェーンの作成を行うために以下のようなことをしているものを多く見かけました。

create_keychain.rb
create_keychain(
      name: ENV["KEYCHAIN_NAME"],
      default_keychain: true,
      unlock: true,
      timeout: 3600,
      lock_when_sleeps: true,
      password: ENV["PASSWORD"]
    )

しかし、いまは公式にコマンドが実装されており
Fastfileのトップレベルで
setup_travisと入力するだけになりました!

setup_travisの内部実装を見る

詳しい解説はしません!やっていることは、記事などでよく見かける create_keychainsetup_travis 関数内で行なっているだけです!

ただし、CI上で実行されていない時は、それ以降の処理をスキップするようにガード節があります。

implement_setup_travis.rb
      def self.run(params)
        # Stop if not executed by CI
        if !Helper.ci? && !params[:force]
          UI.message("Currently not running on CI system, skipping travis setup")
          return
        end

        # Create a temporary keychain
        password = "" # we don't need a password, as the keychain gets removed after each run anyway
        keychain_name = "fastlane_tmp_keychain"
        ENV["MATCH_KEYCHAIN_NAME"] = keychain_name
        ENV["MATCH_KEYCHAIN_PASSWORD"] = password

        UI.message("Creating temporary keychain: \"#{keychain_name}\".")
        Actions::CreateKeychainAction.run(
          name: keychain_name,
          default_keychain: true,
          unlock: true,
          timeout: 3600,
          lock_when_sleeps: true,
          password: password
        )

        # Enable readonly mode for match by default
        # we don't want to generate new identities and
        # profiles on Travis usually
        UI.message("Enabling readonly mode for Travis")
        ENV["MATCH_READONLY"] = true.to_s
      end

今回利用したFastfileの実行フロー

  1. fastlaneのバージョンチェック
  2. iOSをデフォルトプラットフォームに設定
  3. CIかどうか確認
  4. CIだったらsetup_travisを実行
  5. ensure_git_status_cleanで、コミット漏れがないか確認
  6. matchでadhoc証明書を取得
  7. ビルドナンバーをインクリメント(2→3にあがった)
  8. コミット(このあとpushした方が良いけど忘れてた)
  9. ビルド
  10. Beta配信
  11. slackに成功/失敗通知

成功時画像