Help us understand the problem. What is going on with this article?

受託開発でもfastlaneとCircleCIでiOSアプリを継続的デリバリー

More than 3 years have passed since last update.

この記事はCircleCI Advent Calendar 2015 - Qiitaの14日目の記事です。

13日目はnofrmmさんですが、まだ記事が無いようです。

余談

本当は、CircleCIでのiOSビルドの有料化に伴って、個人アプリのビルドをTravisCIに移したという話をしようと思いましたが、今でもCircleCIでビルド出来てる(金は払ってない)っぽいので、一旦移行はやめました。
なので、社内で実際に構築した別のことをまとめました。

背景

iOSアプリを受託で作る場合、いろいろ面倒ですよね。主に証明書周りが。

弊社でよくあるパターンとしては、

  • iTunes connectなどはお客さんしか入れない。
  • 証明書はもらえる。
  • UDIDが増えたら、お客さんに連絡→provisioningを発行してもらう。
  • ipaファイルを納品する。

という感じです。
そのため、証明書やprovisioning profileを動的に取得することは不可能で、Gitのリポジトリに含めることが多いです。

また、弊社ではすでにCircleCIのiOS Planに課金をしており、CircleCI上でiOSのビルドをシェルスクリプトベースで実行していました。

今回、fastlaneというものが、どうやら便利らしいという噂を聞きつけ、試してみました。

実現すること

CircleCI上で動作させるbetaというlaneを作成し、下記の手順を実行します。

  • 証明書のインストール
  • ipaファイルの作成
  • CircleCIのArtifactsとしてipaを登録
  • DeployGateにサブミット
  • 証明書のアンインストール

導入手順

一通り設定したものが、noboru-i/kyouen-ios at bcbca4f21be08d56242e23a44f04986496515bd3こちらになります。
こちらでは、SwiftLintの実行なども入っていますが、それはまた別の機会に。

Gemfileの作成・設定

source 'https://rubygems.org'

gem 'fastlane'

上記内容でGemfileを作成し、bundle install --path vendor/bundleでインストールを実行します。

fastlaneの初期化

bundle exec fastlane initというコマンドがありますが、実体としては後述のAppfileFastfileなどを質問に答えていくことで作ってくれる、というものなので、今回は実行せずに進みます。

手動で、下記のようなディレクトリ構成を作成します。
プロジェクトのルートディレクトリにfastlaneディレクトリを作成し、fastlaneで必要なものを配置していきます。

project_root
├── Gemfile
├── circle.yml
└── fastlane
    ├── Appfile
    ├── Fastfile
    ├── actions
    │   └── swiftlint.rb
    └── cert
        ├── 02b06950-dd9a-4a2f-8f74-097ed2dd2db7.mobileprovision
        ├── apple.cer
        └── dist.p12

certディレクトリ内のファイルについては、下記のように配置します。

  • ファイル名がUUIDとなっているprovisioning profileを配置(インストール済みのものは、~/Library/MobileDevice/Provisioning Profilesに格納されているはず。)
  • Apple Worldwide Developer Relations Certification Authorityと呼ばれるものを、apple.cerというファイル名で配置
  • p12ファイルはパスワードを設定の上、配置(キーチェーンアクセスより、パスワード付きで書き出せる。p12ファイルが最悪流出しても、パスワードがわからなければ利用できない。)

fastlane/Appfileの設定

こちらは、Bundle Identifierなどのツール全般の設定を行うファイルです。

詳しい説明は、こちらを確認ください。

今回は、プロジェクトの設定ファイルにある値をそのまま利用するので、ファイルだけ作成しておき、空にしています。

fastlane/Fastfileの設定

こちらは、laneと呼ばれる実行する処理を記述するファイルです。

詳しい説明はこちら、各アクションのパラメータなどはこちらに記載がありますが、こちらにあるコードを直接見たほうが早いかもしれません。

今回は、前述のbetaというlaneを定義するために、下記のように設定します。

各アプリ毎に変更が必要な箇所は、先頭にまとめてあります。(You need to set your project values.の部分)
環境に合わせて書き換えて頂ければと思います。

fastlane_version '1.47.0'

default_platform :ios

# You need to set your project values.
workspace_name = 'Sample.xcworkspace'
scheme_name = 'Sample_adhoc'
deploygate_user_name = 'sample-user'
project_name = 'Sample'

# And you need to set environment variables.
# DEPLOY_GATE_KEY : DeployGate API key, using when upload to DeployGate.
# GITHUB_ACCESS_TOKEN : GitHub access token, using when comment to Pull Request.
# KEY_PASSWORD : p12 password, using when import *.p12 files.

platform :ios do
  before_all do
    add_keychain if is_ci?
  end

  after_all do
    remove_keychain if is_ci?
  end

  desc 'Submit a new Beta Build to DeployGate'
  lane :beta do
    gym(
      workspace: workspace_name,
      scheme: scheme_name,
      output_name: "#{project_name}.ipa"
    )

    Helper.log.info 'Save Artifacts'
    sh "cp #{lane_context[SharedValues::IPA_OUTPUT_PATH]} $CIRCLE_ARTIFACTS"

    message = "Commit: #{ENV['CIRCLE_SHA1']} / #{last_git_commit[:message]}, Build: #{ENV['CIRCLE_BUILD_NUM']}"
    deploygate(
      api_token: ENV['DEPLOY_GATE_KEY'],
      user: deploygate_user_name,
      ipa: lane_context[SharedValues::IPA_OUTPUT_PATH],
      message: message
    )
  end

  private_lane :add_keychain do
    create_keychain(
      name: 'ios-build.keychain',
      password: SecureRandom.uuid,
      default_keychain: true,
      unlock: true,
      timeout: 3600,
      lock_when_sleeps: true
    )
    import_certificate keychain_name: 'ios-build.keychain', certificate_path: 'fastlane/cert/apple.cer'
    Dir.glob('cert/*.p12').each do |cert_file|
      import_certificate keychain_name: 'ios-build.keychain', certificate_path: 'fastlane/' + cert_file, certificate_password: ENV['KEY_PASSWORD']
    end

    Dir.glob('cert/*.mobileprovision').each do |provisioning_file|
      FastlaneCore::ProvisioningProfile.install(provisioning_file)
    end
  end

  private_lane :remove_keychain do
    delete_keychain(
      name: 'ios-build.keychain'
    )
    sh "rm -f \"#{FastlaneCore::ProvisioningProfile.profiles_path}*\""
  end
end

外部公開用のlaneとしてbetaがあり、それ以外はprivate_laneとしてメソッドを切り出しているイメージです。

CircleCIの設定

上記までで、bundle exec fastlane betaを実行することで当初の目的を果たせるようになりました。

あとは、これをCircleCI上で実行するように、circle.ymlを下記のようにします。

machine:
  timezone: Asia/Tokyo
  xcode:
    version: "7.1"
test:
  override:
    - echo 'no test'
deployment:
  master:
    branch: master
    commands:
      - bundle exec fastlane beta

ここでは、masterブランチの変更があった場合に、betaを実行するようにしています。

最後に、CircleCI上でenvironment variablesの設定を行います。設定が必要な項目はFastfileに記載してあります。(And you need to set environment variables.の部分)

あ、CircleCIのProject setting -> Experimental SettingsでBuild iOS projectをOnにすることもお忘れなく。(CircleCIへの課金が必要)

完成

この設定を行うことで、「XXさんが手が離せないのでアプリの配布が出来ません!」だったり、「XXさんが作ったipaとYYさんがつくったipaで動作が違うんだけど」とか、「ipaの作成作業が面倒なので、DeployGateでの配布は1日1回までとさせて頂きます」といったことから開放されます。

今回は、fastlaneの中でもgymdeploygateといったアクションぐらいしか使っていないですが、provisioning profileの更新や、iTunes connectとの連携など、様々なものが定義されています。

実際やってみて、パス周りだったり、パラメータの意味を調べるのだったりに時間がかかってしまいましたが、今まで慣れないシェルスクリプトで頑張っていたことを考えると、Rubyのコードで拡張していけるようになっただけでも、良かったと思います。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away