1. noboru_i

    Posted

    noboru_i
Changes in title
+受託開発でもfastlaneとCircleCIでiOSアプリを継続的デリバリー
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,209 @@
+この記事は[CircleCI Advent Calendar 2015 - Qiita](http://qiita.com/advent-calendar/2015/circleci)の14日目の記事です。
+
+13日目は[nofrmm](http://qiita.com/nofrmm)さんですが、まだ記事が無いようです。
+
+## 余談
+
+本当は、CircleCIでのiOSビルドの有料化に伴って、個人アプリのビルドをTravisCIに移したという話をしようと思いましたが、今でもCircleCIでビルド出来てる(金は払ってない)っぽいので、一旦移行はやめました。
+なので、社内で実際に構築した別のことをまとめました。
+
+## 背景
+
+iOSアプリを受託で作る場合、いろいろ面倒ですよね。主に証明書周りが。
+
+弊社でよくあるパターンとしては、
+
+- iTunes connectなどはお客さんしか入れない。
+- 証明書はもらえる。
+- UDIDが増えたら、お客さんに連絡→provisioningを発行してもらう。
+- ipaファイルを納品する。
+
+という感じです。
+そのため、証明書やprovisioning profileを動的に取得することは不可能で、Gitのリポジトリに含めることが多いです。
+
+また、弊社ではすでにCircleCIのiOS Planに課金をしており、CircleCI上でiOSのビルドをシェルスクリプトベースで実行していました。
+
+今回、[fastlane](https://fastlane.tools/)というものが、どうやら便利らしいという噂を聞きつけ、試してみました。
+
+## 実現すること
+
+CircleCI上で動作させる`beta`というlaneを作成し、下記の手順を実行します。
+
+- 証明書のインストール
+- ipaファイルの作成
+- CircleCIのArtifactsとしてipaを登録
+- DeployGateにサブミット
+- 証明書のアンインストール
+
+## 導入手順
+
+一通り設定したものが、[noboru-i/kyouen-ios at bcbca4f21be08d56242e23a44f04986496515bd3](https://github.com/noboru-i/kyouen-ios/tree/bcbca4f21be08d56242e23a44f04986496515bd3)こちらになります。
+こちらでは、SwiftLintの実行なども入っていますが、それはまた別の機会に。
+
+### Gemfileの作成・設定
+
+```
+source 'https://rubygems.org'
+
+gem 'fastlane'
+```
+
+上記内容で`Gemfile`を作成し、`bundle install --path vendor/bundle`でインストールを実行します。
+
+### fastlaneの初期化
+
+`bundle exec fastlane init`というコマンドがありますが、実体としては後述の`Appfile`や`Fastfile`などを質問に答えていくことで作ってくれる、というものなので、今回は実行せずに進みます。
+
+手動で、下記のようなディレクトリ構成を作成します。
+プロジェクトのルートディレクトリに`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などのツール全般の設定を行うファイルです。
+
+詳しい説明は、[こちら](https://github.com/fastlane/fastlane/blob/master/docs/Appfile.md)を確認ください。
+
+今回は、プロジェクトの設定ファイルにある値をそのまま利用するので、ファイルだけ作成しておき、空にしています。
+
+### fastlane/Fastfileの設定
+
+こちらは、laneと呼ばれる実行する処理を記述するファイルです。
+
+詳しい説明は[こちら](https://github.com/fastlane/fastlane/blob/master/docs/README.md)、各アクションのパラメータなどは[こちら](https://github.com/fastlane/fastlane/blob/master/docs/Actions.md)に記載がありますが、[こちら](https://github.com/fastlane/fastlane/tree/master/lib/fastlane/actions)にあるコードを直接見たほうが早いかもしれません。
+
+今回は、前述の`beta`というlaneを定義するために、下記のように設定します。
+
+各アプリ毎に変更が必要な箇所は、先頭にまとめてあります。(You need to set your project values.の部分)
+環境に合わせて書き換えて頂ければと思います。
+
+```ruby
+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`を下記のようにします。
+
+```yaml
+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の中でも`gym`や`deploygate`といったアクションぐらいしか使っていないですが、provisioning profileの更新や、iTunes connectとの連携など、様々なものが定義されています。
+
+実際やってみて、パス周りだったり、パラメータの意味を調べるのだったりに時間がかかってしまいましたが、今まで慣れないシェルスクリプトで頑張っていたことを考えると、Rubyのコードで拡張していけるようになっただけでも、良かったと思います。