OTOBANK Engineering Blog

オトバンクはコンテンツが大好きなエンジニアを募集しています!

CircleCIのiOSビルドが有料プラン化するらしいので、Bitriseの無料プランに乗り換えてみた

どうも。麦芽系エンジニアasmzです。今年もあっという間に年の瀬になってまいりましたが、こないだコストコでのどごし生を大量補給したので、年内は何とかやっていけると思います!

CircleCIでのiOSビルドが有料化!?

これまでCircleCIでiOSアプリのビルドをされていた方はご存知かと思いますが、これまで「ベータ機能」として無料で利用できていたiOSビルド機能は、11月末でベータ提供終了とのお知らせが先日CircleCIから届きました。

で、12月から新しいプランになりますよ!って出てきたプランを見ると、無料プランというものは見当たらず、最安でも$99/月(ベータ機能利用者は今申し込めば限定価格でご提供)という噂…。(※)

※この辺はまだ公式サイトにアナウンス掲載されていないので、今後変更される可能性はあります。(もし違っても石投げないでやってください…)

少々お高いですなぁ…

そのくらいの金払えよ!って話は置いといて、ひとまずお金は大事なのでその他のCIサービスとプラン比較してみました。

ちなみに現実的に利用するためにはGitHubのPrivate Repositoryが使える必要があったので、それを前提条件として一番安いプランを選んでいます。チームメンバーや対象アプリがもっと多い方とかは、もうちょっと追加条件が必要かとは思います。

  • 前提:Private Repositoryが使えること
f:id:asmz0:20151128003139p:plain f:id:asmz0:20151128003220p:plain f:id:asmz0:20151128003239p:plain f:id:asmz0:20151128003303p:plain
URL https://circleci.com/ https://travis-ci.com/ https://www.bitrise.io/ http://greenhouseci.com/
価格 $99/月
(通常価格)
$129/月 Free Free
メンバー数 2人 Unlimited 2人 1人(チーム自体が作れない)
ビルド回数 5回/日 Unlimited 200回/月 Unlimited
ビルド時間 1000分/月 Unlimited 10分/ビルド Unlimited
その他 ・処理が固定でカスタマイズできない

この比較を並べてみて思った所感。

  • CircleCI
    • ビルド回数が5回/日って結構辛くないっすか?
    • これらの制限ついてる割には高い…
  • TravisCI
    • まぁ良いものは高い
  • Bitrise
    • 10分/ビルドもしかしたら間に合わないかも(実際に現状10分近くかかってる)
  • Greenhouse CI
    • カスタマイズの幅が狭いと、やりたいこと出来ない気がする

で、現状CircleCIでやれてることをうまく移行できそうな機能を持ってて、かつ無料で始められる「Bitrise」を試しに使ってみるか!というのが今回のエントリになります。

Bitriseとは

www.bitrise.io

今回調べてみて初めて存在を知ったのですが、モバイルに特化したCIサービスです。最初はiOS専用としてリリースされて、Androidはベータ機能として後からサポートが始まったところようですね。

サインアップやアプリ登録などの初期設定は、こちらの記事でキャプチャ付きでわかりやすく説明されているのでここでは割愛します。

Xcode - iOS用のCIサービスBitriseを使ってみた - Qiita

簡単に説明すると「Workflow」という機能が一連のStepをまとめる単位となり、そこにやりたいStepを登録していく感じです。fastlaneの「lane」の考え方に近い考え方ですね。

また、MacVM上で行わせたい処理を「GUIベース」で設定するというのがCircleCIとは異なる大きな特徴です。

以降、実際にCircleCIで設定していた内容をBitriseに移行しながら、具体的な使い方を説明していきます。

現在のCircleCI設定

今回CircleCIへ移行する内容は、以下のエントリのやつになります。

engineering.otobank.co.jp

具体的にはこんな感じのcircle.ymlになっていて、今回はこの処理内容をそのままBitriseに移行していく感じです。(fastlaneのlane処理内容は↑のエントリに詳細記載していますので、今回は割愛します)

# Xcodeバージョンの指定
machine:
  xcode:
    version: "7.0"

# RubyGems(具体的にはfastlaneとCocoaPods)インストール
dependencies:
  override:
    - bundle -j4 --path=vendor/bundle

...

# ビルド・デプロイ(pushされたブランチ名に応じて、処理内容振り分け)
deployment:
  feature:
    # master, develop以外のブランチ名のpush
    branch: /^(?!(master|develop)).*$/
    commands:
      - bundle exec fastlane setup          # CocoaPodsパッケージインストール
      - bundle exec fastlane keychain       # 開発証明書類をキーチェインへ登録
      - bundle exec fastlane build_adhoc    # AdHoc版のビルド、ipa生成
      - bundle exec fastlane delivery_dev   # Crashlytics Betaで開発者に配布
  development:
    # developブランチのpush
    branch: develop
    commands:
      - bundle exec fastlane setup
      - bundle exec fastlane keychain
      - bundle exec fastlane build_adhoc
      - bundle exec fastlane delivery_tester   # Crashlytics Betaでテスターに配布
  production:
    # masterブランチのpush
    branch: master
    commands:
      - bundle exec fastlane setup
      - bundle exec fastlane keychain
      - bundle exec fastlane build_appstore    # Production版のビルド、ipa生成
      - bundle exec fastlane delivery_appstore # iTunesConnect(TestFlight)へアップ

これを見ていただくとわかると思いますが、前回のエントリでビルド周りについてfastlaneの独自laneを用意して、ほとんどそれらで行えるようにしたので、実はCircleCI独自でゴリゴリやっている処理はありません。

なので、これによって移行自体は大変楽に出来たのですが、その分このエントリが参考になる対象者がちょっと限られてしまう気はします…。何卒ご了承くださいませ。

GitHub Webhookの設定

Bitriseの設定に入る前に、リポジトリにpushした際に自動でBitriseのビルドが走るよう、GitHubにWebhookを設定しておきます。

(なんかこの辺のドキュメントを読んでみると、アプリ登録時にGitHubと連携して用意すれば自動的にWebhookが設定される、という記載があったんですが、やってみたらうまく設定されてなかったので念のため書いてます。自分が設定どっか間違えただけかもしれません。)

  • Bitriseダッシュボードより「Code」-「Build trigger URL」をコピー f:id:asmz0:20151129213550p:plain

  • GitHubの対象リポジトリ「Settings」-「Webhooks & services」-「Add webhook」の「Payload URL」にBuild trigger URLを設定(「Secret」は空でいい) f:id:asmz0:20151129214224p:plain

これで、push時にBitriseのビルド開始が連携されます。

circle.ymlに対応したWorkflowの作成

ここからが本エントリのメインとなる、CI上でのビルド処理組み立てです!

Bitriseの「Workflow」-「MANAGE WORKFLOWS」で開く「Workflow Editor」で実際のWorkflowを構築していきます。

f:id:asmz0:20151129215512p:plain

なお、初期設定でWorkflow内にいくつかStepが設定されていますが、ここでは以下の3つを残して、その他Stepは削除しています。

  • Select Xcode version
    • Xcodeのバージョンを指定できるStep(今回はxcode-7を指定)
  • Activate App SSH key
    • GitHubのリポジトリアクセスのための鍵設定(初期設定完了していれば、デフォルト設定のままでOK)
  • Git Clone Repository
    • そのリポジトリのソースをclone(初期設定完了していれば、デフォルト設定のままでOK)

この初期設定だけで、circle.ymlの以下の部分は設定できたことになります。

machine:
  xcode:
    version: "7.0"

RubyGems(具体的にはfastlaneとCocoaPods)インストール

circle.ymlでは次に、以下の通りRubyGemsのインストールが入ってます。

dependencies:
  override:
    - bundle -j4 --path=vendor/bundle

Bitriseには元よりfastlaneとCocoaPodsがインストールされているようですが、使用バージョンを指定したいなどの理由で手動でインストールしたい、ということはあるかと思います。

この場合、リポジトリルートにGemfileが置いてあれば、Bitriseでは特に何も設定することなくビルド実行時に勝手にインストールしてくれるようです。

実行時のログではこんな感じに出ています。

$ cd /Users/vagrant/git
Found 'Gemfile' - using it...
$ bundle install
Fetching gem metadata from https://rubygems.org/..........
Fetching version metadata from https://rubygems.org/...
Fetching dependency metadata from https://rubygems.org/..
Resolving dependencies......
Using i18n 0.7.0
Installing json 1.8.3 with native extensions
Installing minitest 5.8.2

...

ちなみにcircle.ymlで言う所のcache_directoriesみたいな指定できるところは見当たらず、前回ビルド分をキャッシュするといった処理は実装できていません。

fastlane実行

専用のStep「Fastlane」が用意されているので、こちらを利用します。

f:id:asmz0:20151129223112p:plain

このStep選択後の設定画面「Input variables」-「Fastlane lane」にlane名を入力するとそのlaneを実行されます。

f:id:asmz0:20151129223237p:plain

↑この例だと、$ fastlane setup が実行されるということですね。

つまり、今回のcircle.ymlの処理内容とBitriseのStepは以下のような対応となると考えていただければわかりやすいかと!

f:id:asmz0:20151129224407p:plain

ブランチ毎のWorkflow用意

先の内容はcircle.ymlで言う所の^(?!(master|develop)).*$ブランチ、つまりmasterとdevelop以外のfeatureブランチに対するpushの際の処理ですが、master、develop用のWorkflowも用意する必要があります。

以下の+ボタンを押すと、その時選択中のWorkflowをコピーして、新たなWorkflowを作成することができます。

f:id:asmz0:20151129224934p:plain

今回のcircle.ymlの内容であれば、コピーしたWorkflowのうち、fastlaneの実行レーンを一部変更するだけで用意することができます。

つまり、こんな感じでそれぞれのブランチに対応するWorkflowを用意するというわけです。

f:id:asmz0:20151129225942p:plain

Triggers設定

画面左メニューの「Triggers」で、リポジトリからpushされたブランチに応じて、実行するWorkflowを変えることができます。この機能を用いて、今回のcircle.ymlで以下のような指定をしていた部分を対応します。

deployment:
  feature:
    # master, develop以外のブランチ名のpush
    branch: /^(?!(master|develop)).*$/
    commands:
       ...
  development:
    # developブランチのpush
    branch: develop
    commands:
       ...
  production:
    # masterブランチのpush
    branch: master
    commands:
       ...

Triggerを追加する画面は以下のようになっています。

f:id:asmz0:20151129231524p:plain

「Pattern name:」に合致した場合、「Triggered Workflow:」に指定したWorkflowを実行する、という割と単純な仕様ですが、circle.ymlと違って正規表現は使えず、完全一致か「*」を用いた部分一致でのマッチングとなるようです。

その代わり、Triggersに設定するTriggerは優先度を設定できる(上に書いたものからマッチングされる)ようなので、それを利用して以下のような設定で、今回の要件を実現しました。

f:id:asmz0:20151129232043p:plain

これで、develop、masterにマッチしないブランチ名がプッシュされると、featureのWorkflowが実行される、という動きになります。

必要な環境変数の設定

こちらは他のCIツールとさほど変わらないと思いますが、「Workflow Editor」の「MANAGE ENV. VARS」からKey=Valueの形で登録できます。

なお、「MANAGE ENV. VARS」で登録した環境変数は、bitrise.ymlのエクスポートの際に表示されてしまうので、パスワードなどのCredentialな情報は左メニューの「Secret Env Vars」の方に登録しておくと良いようです。

ビルド結果のSlack通知

ここまでの作業で、circle.ymlに記載していた処理の移行は完了しているんですが、CircleCIではビルド完了後にSlackに通知を投げるようにインテグレーション設定を入れていたので、これも同様の動きとしてみます。

Workflowの最後に「Send a Slack message」というStepを追加します。 f:id:asmz0:20151129232451p:plain

Slack側でIncoming WebHooksを一つ用意して、このStepの設定欄に設定すれば完了です。

なお、ビルド成功・失敗に応じてメッセージやアイコンなどを変更することができるので、この辺は自由に設定して貰えばいいです。

f:id:asmz0:20151129233041p:plain f:id:asmz0:20151129233055p:plain


以上がCircleCIからBitriseへ乗り換えるために行った一連の作業になります!

ちなみに、このエントリの場合はfastlaneで大体のことをやってしまっているのですが、もしcircle.yml内で直接CocoaPodsのインストールとかXcodeのビルド、アーカイブとかのコマンドを書いていたとしても、それに対応するStepは一通り用意されている感じがしていて、結構このサービス自体のポテンシャルの高さを感じます。

CircleCIが有料化したら困る!っていう方は、一度試してみる価値はあるんじゃないでしょーか!

その他書き切れなかったこと

  • 無料プランだとビルド時間が600秒(10分)だが、現状うちのリポジトリは平均して560秒くらいかかる
    • ちょっと運用してみたら、割とこの問題引っかかる…。
  • 作成したWorkflowはbitrise.ymlとしてエクスポート、インポート出来るらしいし、CLIコマンドも用意されているんで、GUIが気に入らない人でもうまくやればcircle.ymlみたいな管理ができるのかもしれぬ(未確認)
  • 開発証明書やProvisioning Profileを管理画面から登録する機能があるが、今回は使用してない。(証明書はPrivRepoに含み、Provisioning Profileはfastlane sighで都度ダウンロードしているため)
  • これを書き終えたくらいにbuddybuildというCIツールも見つけた。どんな感じだろうか?

まとめ

こんな感じで、新しいサービスとか見つけたらすぐに試して実運用に採用とかできちゃうオトバンクでは、WebエンジニアだけでなくiOS/Androidエンジニアも絶賛募集中ですよ!

「FeBe」、「新刊JP」のWebエンジニア | 株式会社オトバンク