Travis CIでfastlaneを使用する

こんにちは。akaimoです。
Travis CIを利用しているiOSプロジェクトにfastlaneを導入して、xcodebuildを直接実行する環境から開放されたので、
備忘録としてやったことを残しておきます。

github.com

前提

  • CI上でfastlaneを使用
  • 複数人で開発

fastlaneのインストール

まずはfastlaneをインストールします。

fastlaneはgemで公開されているのでrubyの環境のバージョンを固定しておきましょう。
CIにインストールされているrubyのバージョンと同じにしておくことをオススメします。
違うとCI上でrubyのインストールが始まってしまうかもしれません。無駄な時間なので素直に同じバージョンを使いましょう。

$ rbenv local 2.4.2

こんどはfastlaneのバージョンを固定するためにbundlerをインストールします。

$ gem install bundler

Gemfileに以下を記述します。

source 'https://rubygems.org'

gem 'fastlane'

インストールします。

$ bundle install --path=vendor/bundle

ポイントとしては --path を指定することでローカルの環境を汚すことなくfastlaneをインストールできます。
ここでインストールされたディレクトリはgitで管理する必要はないので.gitignoreに入れておきましょう。

セットアップ

xcodeprojがあるディレクトリでinitコマンドを実行して雛形を作成します。

$ bundle exec fastlane init

実行するとlane(1つのコマンドで実行されるアクションをまとめたもの)を作成するか聞かれます。2か3を選ぶと質問に答えるだけでitunes connectの設定がされるのでオススメです。

完了するとfastlaneというディレクトリが作成されています。
ファイルの中は以下のようになっています。

  • Fastfile
    • レーンを記述します。initコマンドで選択したlaneが作成されています。
  • Appfile
    • fastlane全体で使用する情報を記載します。initで2か3を選んでいるとapple idやteam idなどが記載されています。

iTunes Connect(TestFlight)へのアップロード

TestFligntへアップロードします。
プロジェクトの設定によって変わりますが、基本は以下のような形です。

  lane :beta do
    build_app(
      workspace: "Hoge.xcworkspace",
      scheme: "Hoge",
      output_directory: "./tmp"
    )
    upload_to_testflight(ipa: "./tmp/Hoge.ipa")
  end

lanebetaを実行します。

$ bundle exec fastlane beta

initのときに2か3を選択した場合は、initで入力した情報がキーチェーンに保存されているのでローカル環境ではアップロードできますが、
CI上だとapple idのパスワードが存在せず失敗してしまいます。

このような時のためにfastlaneはFASTLANE_PASSWORDという環境変数からパスワードを取得してログインするようになっています。
.travis.yml環境変数にパスワードをセットしましょう。

この記事が参考になります。

qiita.com

これでCI上からアップロードできるようになります。

HockeyAppへのアップロード

次はHockeyAppへアップロードします。

  HOCKEY_API_TOKEN = ENV['HOCKEY_APP_TOKEN']
  PLIST_PATH = "path/to/Info.plist"
  build = get_info_plist_value(path: PLIST_PATH, key: "CFBundleVersion")
  version = get_info_plist_value(path: PLIST_PATH, key: "CFBundleShortVersionString")

  lane :alpha do
    build_app(
      workspace: "Hoge.xcworkspace",
      scheme: "Hoge",
      configuration: "Adhoc",
      export_method: "enterprise",
      output_directory: "./tmp"
    )
    hockey(
      api_token: HOCKEY_API_TOKEN,
      bundle_short_version: version,
      bundle_version: build,
      ipa: "./tmp/Hoge.ipa",
      dsym: "./tmp/Hoge.dSYM.zip",
    )
  end

先程と同じようにapiのtokenを環境変数にセットし、それを読み込みます。
TestFlightへのアップロードができていれば、同じようにできるはずです。

Unit Testの実行

せっかくCIの環境があるので、テストも実行しておきましょう。

  lane :test do
    run_tests(
      workspace: "Hoge.xcworkspace",
      scheme: "Hoge",
      configuration: "Debug",
      device: "iPhone 8"
    )
  end

Slackへの通知

fastlaneにはslackに通知を送る機能があり、自由にカスタマイズでき、好きなタイミングで送ることができます。
今回はアップロードが完了したら通知するようにします。

まずは通知用のlaneを作成します。

  lane :hockey_notification do
    link = lane_context[SharedValues::HOCKEY_DOWNLOAD_LINK].to_s
    name = sh("echo $USER")

    slack(
      slack_url: "https://hooks.slack.com/services/",
      channel: "#general",
      success: true,
      default_payloads: [],
      attachment_properties: {
        title: "Uploaded to HockeyApp",
        text: "Beta version is now available for <" + link +  "|download>.",
        fields: [
          {
            title: "Build by",
            value: name,
            short: true
          },
          {
            title: "Build Date",
            value: Time.new.to_s,
            short: true
          }
        ]
      }
    )
  end

これを実行すると、このような通知がきます。

f:id:akaimo3:20180120121916p:plain

slackのattachment apiをカバーしているので、公式のドキュメント通りにカスタマイズできます。

api.slack.com

これを先程のHockeyAppへアップロードするlaneに追加します。

  HOCKEY_API_TOKEN = ENV['HOCKEY_APP_TOKEN']
  PLIST_PATH = "path/to/Info.plist"
  build = get_info_plist_value(path: PLIST_PATH, key: "CFBundleVersion")
  version = get_info_plist_value(path: PLIST_PATH, key: "CFBundleShortVersionString")

  lane :alpha do
    build_app(
      workspace: "Hoge.xcworkspace",
      scheme: "Hoge",
      configuration: "Adhoc",
      export_method: "enterprise",
      output_directory: "./tmp"
    )
    hockey(
      api_token: HOCKEY_API_TOKEN,
      bundle_short_version: version,
      bundle_version: build,
      ipa: "./tmp/Hoge.ipa",
      dsym: "./tmp/Hoge.dSYM.zip",
    )
    hockey_notification
  end

alphalaneを実行するとアップロード完了後にslackへ通知がきます。

おわりに

fastlaneを使用してCI上の処理を簡略化しました。
xcodebuildを直接実行していたときと比較すると、

  • CIのコードが大幅に減った
  • 出力に色が付き整形されるので見やすい

ことがすぐに感じられたメリットです。

Xcodeのバージョンアップによるxcodebuildの変更への追随が、fastlaneの更新だけで済むようになればいいな
と期待しながらCIを拡充していきたいと思います。