これでできる!iOSアプリ DeployGate配信自動化までの13ステップ

どうも、ギルドワークス 前川です。

さて、みなさーん、継続的インテグレーション(以下CI)してますかー!

さて、以前お伝えしたように、ギルドワークスでは、iOSの開発においても積極的なCIを行っています。

これは、特にリモート開発が多い環境では、正しいものを正しくつくる ために常に安定したベースラインで確認できる環境を作ることが、非常に重要だからです。

とはいえ、なかなかiOSの自動ビルドには越えなければ行けないハードルが多かったりします。 今回は、ある一つのiOSプロジェクトを作成してから、誰でも実機上で確認できるようになるまで(技術ベースで言うと、DeployGateを用いてAdhoc配信するまで)を、ざっと紹介したいと思います。

1. iOSアプリケーションを作成し、iOSアプリケーションをGithubにPushする

まずは、大前提ですね。作成しているアプリケーションを、GithubにPushします。

2. CircleCIにて、ビルドの設定を行う

続いて、CircleCIにて、該当プロジェクトをビルドするように設定します。 この辺りは、公式ドキュメントを参照してくださいませ。

CircleCIはGithub認証が必須ですが、Githubを利用している限りは、特に迷うことはないかと思います。

こんな感じで、選べるはずです。

ead596c5-51ef-49df-a973-edaeae6229b0

3. CircleCIにて、Experimental OptionのiOS Buildを有効にし、チャットにて、制限回避をお願いする

さて、そうするとCircleCIでは勝手にビルドが始まるのですが、このようになります。

da7b9d58-10a9-44df-8dd2-14c564569010

残念ながら、警告が出て、失敗・・・というかビルドが行われません。 これは、CircleCIはiOSに関してはまだExperimental(実験的)な機能という扱いであり、設定をしてやらないといけないからです。

というわけで、Project Settingから、iOSビルドをONにします。

a5ed097f-6dbf-48a4-bebb-89936799c883

さて、なんとそれだけではうまく行きません。何かというと、、、

CircleCI is currently offering beta access to our iOS build system. Please contact support if you would like access.

なんとサポートに連絡する必要があります。 とはいえ、ご心配なく。サポートは、実はとても簡単にアクセスできます。

a0596661-19f2-4f87-be11-1e76bbab850a

ここから、チャットでお願いしましょう!

スクリーンショット 2015-11-20 08.47.40

こんな感じの、シンプルな英語で大丈夫です。

4. Schemeを共有設定にする

さて、これでようやく、iOSビルドの準備が整いました、、とおもいきや、まだ成功しません。Build Schemeを共有しなければなりません。

XCodeで、[Product] -> [Edit Scheme…] と選択し、Schemeの編集画面に行きます。

ここでSchemeを共有しておきます。

06c01938-899f-41c0-9e06-1c19369ebf40

これで、CircleCI上でのビルドが回り始めたはずです!

6. circle.yml を導入

とはいえ、実はCircleCIのデフォルトはXCodeのバージョンがかなり低いため、設定を行わないとビルドは成功しません。 画面からでも設定はある程度行えるのですが、設定ファイルとしてレポジトリに入れるほうが、バージョン管理もできますし、好ましいです。

ということで、circle.yml といわれる設定ファイルを追加します。

レポジトリのrootに circle.ymlを置いておくことで、CircleCIが勝手にその内容を読み取り、ビルドしてくれます。

詳しい書き方は、以下を参考にするとよいでしょう。

ここでは、ひとまずXCodeのバージョンを指定すれば良いので、以下のように書いておきます。

machine:
  xcode:
    version: "7.1"

これで、ビルドが通ったのではないでしょうか。


少し休憩

ここまでで、自動テストと、XCodeで設定してあれば、テストも通るようになります。現状、ベータアクセスのため一手間必要ではありますが、非常に簡単にビルドが行えることが、分かっていただけたでしょうか?

ただし、ここまではSimulator上での実行。ここからは、実機ビルドです。 そのためには、おなじみのApple Mamber Centerでの設定が必要となります。

6. Apple Member Center で Certificate を作成する

今回の実機配布は、DeployGateを利用する想定です。DeployGateはAdhocビルドの配布を行いますので、Certificateを作成する必要があります。

とはいえ、Certificate作成については、多くの先例があるため、紹介に留めます。

7. Apple Member Center で AppID を作成する

AppIDも同様に、先例の紹介に留めます。

8. Apple Member Center で Deviceを登録する

次に、テストを行う端末のDeviceIDを登録します。 DeviceIDを確認する手段は色々ありますが、まずは以下のように直接確認しましょう。

UDID自体は、iPhone をUSBにつなぎXcodeを起動 「Window」->「Devices」にIDが確認できます

from [iPhone] Provisioning Profile の作成

確認したUDIDと、それを識別する名前をセットにし、Member CenterのDevicesの中に追加します。

9. Apple Member Center で Provisioning Profile を作成する

こちらも定型です。

ただし、このProvisioning Profileは、Deviceが追加されるごとに書きなおす必要が有ることに注意しましょう。


もう一度休憩

ここまで設定すれば、手元でAdhoc配布用のビルドが作成できるようになっているはずです。

次にやることは、これをCircleCI上でやること。もう一息ですが、ここからが大変でもあります。頑張りましょう。


10. DeployGateでAPI Keyを取得する

まずは、DeployGateに登録し、API Keyを取得しておきます。 プロフィールページからいけますね。

ffe8196b-e3c0-431a-b371-30525c258689

11. 証明書キーファイル(p12ファイル)をレポジトリに入れる

次に、CircleCI上のMacでビルドするために、証明書をインストールする必要があります。いろいろ手段はあるかと思いますが、今回はp12ファイルをレポジトリに入れてしまいます。

p12ファイルはキーチェーンアクセスから暗号化することができますので、それを入れておけば最低限のセキュリティは担保できるでしょう。

上記はプッシュ通知用の作業ですが、手順としては同じです。これをレポジトリに入れましょう。

12. circle.yml を編集し、ビルド環境を整える

続いて、circle.yml を用いてビルド環境を整えます。 大きくやることは、

  1. cupertino の導入
  2. 証明書のインストール
  3. Certificateのインストール
  4. Provisioning Profileのインストール

の4つになります。

① cupertino の導入

cupertino とは、Member Centerにアクセスして CertificateやProvisioning Profileを取得してくれるコマンドラインツールです。

これを用いて、Apple Member Centerからビルド時にダウンロードします。 これは、Provisioning Profileがデバイスの追加ごとに再作成となるため、開発中は結構変わってしまうからです。リポジトリに入れてしまうと、管理が大変になります。

インストールは簡単です。circle.yml の依存関係解決後に、gemでインストールします

dependencies:
  post:
    - gem install cupertino

② 証明書のインストール

次に証明書のインストールです。ディレクトリ内に p12 ファイルは配置しているはずですので、それを展開します。

dependencies:
  post:
    - gem install cupertino
    - security import ./certificates/xxx.p12 -k "login.keychain" -P "${PRIVATE_KEY_PASSPHRASE}" -T /usr/bin/codesign

ここで、 ${PRIVATE_KEY_PASSPHRASE} で指定した環境変数だけは、誰にも知られたくありません。そんな環境変数は、CircleCIのSetting -> Environment Value から追加できます。パスワードなど外に漏れるとマズい情報はここに書きますね。

85630427-78c0-4865-bcfd-944958da4bca

③ Certificateのインストール

次に、Certificateです。Certificateについては、cupertinoを用いてダウンロードし、インストールします。

dependencies:
  post:
    - gem install cupertino
    - security import ./certificates/xxx.p12 -k "login.keychain" -P "${PRIVATE_KEY_PASSPHRASE}" -T /usr/bin/codesign
    - ios ios profiles:download "provision_name" -u "${user_id}" -p "${password}" --type distribution  --team "A_team"
    - security import "cert_name.cer" -k "login.keychain" -T /usr/bin/codesign

④ Provisioning Profile のインストール

最後に、Profile です。こちらもCertificateとほぼ同様ですね。

dependencies:
  post:
    - gem install cupertino
    - security import ./certificates/xxx.p12 -k "login.keychain" -P "${PRIVATE_KEY_PASSPHRASE}" -T /usr/bin/codesign
    - ios ios profiles:download "provision_name" -u "${user_id}" -p "${password}" --type distribution  --team "A_team"
    - security import "cert_name.cer" -k "login.keychain" -T /usr/bin/codesign
    - ios profiles:download "profile_name" -u "${user_id}" -p "${password}" --type distribution  --team "A_team"
    - cp "profile_name.mobileprovision" "$HOME/Library/MobileDevice/Provisioning Profiles"

これで、ビルドするための環境が整いました。

13. circle.yml を編集し、schenzenを用いてipa build を行い、DeployGateに配信する

最後に、テスト成功時にはパッケージビルドをして、DeployGateに送信しましょう。

これには、 schenzen というコマンドラインツールを使います。

schenzenは

  • ipaファイル(iOSにデプロイされる元ファイル)の作成
  • ipaファイルの各種サービスへの転送

を主に行うツールです。

テスト後、Deployにこれらのコマンドを用いたビルドをcircle.ymlに追記していきます。

deployment:
  staging:
    branch: master
    commands:
      - ipa build -w test.xcworkspace -s scheme_name -c Release -m "${profile_name.mobileprovision}" --sdk "iphoneos" --xcargs "CODE_SIGN_IDENTITY=\"CODE_SIGN_ID\"" --verbose
      - ipa distribute:deploygate -a $DEPLOYGATE_API_TOKEN -u $DEPLOYGATE_USER_NAME 

これがDeployの基本形で、上記はmaster branchにマージされたものを、自動的にビルドし、deploygateで送信しています。

デプロイの詳細な書き方は以下を参照ください。

ipaコマンドがschenzenです。 “CODE_SIGN_ID” というのは、キーチェーンアクセスで「情報を見る」などした時に表示される、”iPhone Distrobution: Guildworks.inc (XXXXXX)” のように、”サイン区分 + 会社名 + カッコつき数字”で記述されているものです。

さぁ、これでDeployGate配信までたどり着けるはずです。

最終的なcircle.ymlはこれくらいのボリュームになります。

machine:
  xcode:
    version: "7.1"
dependencies:
  post:
    - gem install cupertino
    - security import ./certificates/xxx.p12 -k "login.keychain" -P "${PRIVATE_KEY_PASSPHRASE}" -T /usr/bin/codesign
    - ios ios profiles:download "provision_name" -u "${user_id}" -p "${password}" --type distribution  --team "A_team"
    - security import "cert_name.cer" -k "login.keychain" -T /usr/bin/codesign
    - ios profiles:download "profile_name" -u "${user_id}" -p "${password}" --type distribution  --team "A_team"
    - cp "profile_name.mobileprovision" "$HOME/Library/MobileDevice/Provisioning Profiles"

deployment:
  staging:
    branch: master
    commands:
      - ipa build -w test.xcworkspace -s scheme_name -c Release -m "${profile_name.mobileprovision}" --sdk "iphoneos" --xcargs "CODE_SIGN_IDENTITY=\"CODE_SIGN_ID\"" --verbose
      - ipa distribute:deploygate -a $DEPLOYGATE_API_TOKEN -u $DEPLOYGATE_USER_NAME 

さて、長い記事にお付き合いいただきありがとうございました。 このように、けっこう大変ですが(順調に行けば1時間ちょっと、ハマると半日位かかってしまいますが)、1プロジェクトでやってしまえばあとは同じ作業で展開できますので、チャレンジしてもらえればなぁ、と思います。

このように、ギルドワークスではデプロイの徹底的な見直しを通じて、「正しいものを正しくつくる」を実現しようとしています。コーチや開発など、お手伝いできることがあればぜひ、お問い合わせください

現場改善でハマる罠

ギルドワークス 前川です。

ギルドワークスでは、様々な現場に入り込んで現場改善を行っています。もちろん皆さんの現場でも、様々な改善が試行されているのではないかと思います。そんななかでハマりやすい罠について、今日はお話します。

改善をリードする立場とされる立場の間の意識ズレ

あなたが現場改善をリードする立場だった時、あなたの頭のなかには、それが最高にうまく行った場合のバラ色の未来が思い浮かんでいることでしょう。

しかし、改善というのは大抵、即効性のある効果があるものではありません。これまで慣れたプロセスを変えてしまったら、どこかで不慣れによる作業効率の低下や、手順が変わったことによるミスなどがでてくるでしょう。

あなたにとっては、それは改善の効果が出るまでの一過性の痛みに過ぎません。しかし、他のメンバーにとってはどうでしょう?

「いらんことをされて、面倒くさくなった」と思われていませんか?

それを、「分かっていない。利点が見えていない。ずっと使っていたら分かってくれるはず。」と無視するのは簡単です。しかし、そんなふうに強引に進めた改善がたどるのは、早晩打ち捨てられてしまう衰退の道です。

改善をスムーズに進めるために

では、どうすればいいか?

そこに大切なのは、「誠意」です。

丁寧な説明でその「誠意」が事足りる場合もあるでしょうが、もう少し踏み込んだ対策として、即効性のある短期的な改善を組み合わせる、ということがあげられます。

たとえば、バージョン管理システムを新たに取り入れることを考えてみましょう。さきのことを考えると、自分の更新を追うことができ、またいつでも戻ることができる、というのは大きなメリットです。

しかし、最初の導入では、多くの人は「”コミット”とかいうわけのわからない手順が増えてしまった」「新しいツールを導入して怖い」「勝手にマージされて壊れたりしないのか?」などの不安や手間を考えてしまいます。

そこで、バージョン管理の利点を語って皆が納得すればよいのですが、それで納得できない人もいます。

そういう人には、先述した短期的な改善を組み合わせて提示するといいでしょう。例えば、コミットフックの機能をうまく使って、エラーを自動検知したり、同時にJenkinsも導入してテストを回してみたり、など、多少導入の手間が増えてしまっても、メリットがすぐ受けられる、即効性のある改善とセットにするのです。

このように、改善を進めていく側だけの目線や都合だけでなく、改善の結果を受け取る人達の気持ちにも寄り添っていく姿勢が、現場改善では重要となる場合が多いです。

自信と傲慢は違います。皆さん、その点気をつけて、現場を良くしていきましょう!

ギルドワークスが、そのお手伝いをできるのならば、お気軽にお問い合わせください。

アイキャッチ: http://fav.me/d4gqh5o

Gradle Versions Plugin のご紹介

井上です。

普段 Java でシステム開発を行っているのですが、ビルドツールとして最近は Gradleを使っています。

Gradle は 日本語のドキュメント「Gradle徹底入門 次世代ビルドツールによる自動化基盤の構築」 といった日本語の情報が豊富で、Java界隈におけるビルドツールのデファクトスタンダードとなりつつあります。

Gradle におけるライブラリのバージョンの指定方法

Gradle では、プロジェクトで使用するライブラリを指定することで、そのライブラリ及びライブラリが依存しているライブラリ群を自動的にダウンロードする機構が備わっています。

以下、Java を使ったプロジェクトで JUnit を使用する際のGradle のビルドスクリプト (build.gradle) の例です。

apply plugin: 'java'

sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    // (1) 特定のバージョンを指定
    testCompile 'junit:junit:4.11'
    // (2) 動的バージョンで指定 (4系の最新版)
    // testCompile 'junit:junit:4.+'
    // (3) 使用できる最新版を表すプレースホルダで指定
    // testCompile 'junit:junit:latest.release'
}

通常は (1) のように、特定のバージョンを指定しますが、開発中など、常に最新版を使いたい場合は、 (2) (3) のように指定することもできます。

ただし、ライブラリが更新されたことは知りたいけども、実際に最新版を適用するかは、その更新内容を確認した後にしたい場合も多いと思います。

そのような場合、上記の指定方法だけでは対応することができないので、 (1) のように、特定のバージョンを指定した上で、Maven Central Repository などでライブラリの更新状況を都度チェックすることになりますが、とても面倒です。

このような場合に便利な Gradle Versions Plugin を紹介します。

Gradle Versions Plugin とは

Gradle Versions Plugin は、ビルドスクリプトに指定したライブラリの更新情報を一括で確認する機能を提供するGradleのプラグインです。

では、実際に Gradle Versions Plugin の使い方を簡単に見てみましょう。

Gradle Versions Plugin の使い方

以下が、先ほど紹介したビルドスクリプトに Gradle Versions Plugin の設定を追加した例です。

buildscript {
    repositories {
        jcenter()
    }

    dependencies {
        classpath 'com.github.ben-manes:gradle-versions-plugin:0.11.3'
    }
}

apply plugin: 'java'
apply plugin: 'com.github.ben-manes.versions'

sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    // (1) 特定のバージョンを指定
    testCompile 'junit:junit:4.11'
    // (2) 動的バージョンで指定 (4系の最新版)
    // testCompile 'junit:junit:4.+'
    // (3) 使用できる最新版を表すプレースホルダで指定
    // testCompile 'junit:junit:latest.release'
}

上記設定を追加することで、プロジェクトに dependencyUpdates タスクが追加されます

では、実際に dependencyUpdates タスクを実行してみましょう。
以下、dependencyUpdates タスク の実行例です。

% gradle dependencyUpdates                                                                                                                                                        (git)-[master]
:dependencyUpdates

------------------------------------------------------------
: Project Dependency Updates (report to plain text file)
------------------------------------------------------------

The following dependencies are using the latest milestone version:
 - com.github.ben-manes:gradle-versions-plugin:0.11.3

The following dependencies have later milestone versions:
 - junit:junit [4.11 -> 4.12]

Generated report file build/dependencyUpdates/report.txt

BUILD SUCCESSFUL

「Project Dependency Updates」以下に、ライブラリの更新情報が出力されています(標準出力だけでなく、build/dependencyUpdates/report.txt へも出力されています)。
出力内容から以下のことが分かります。

  • Gradle Versions Plugin (com.github.ben-manes:gradle-versions-plugin) は最新版 (0.11.3) を使用している
  • JUnit (junit:junit) は指定したバージョン (4.11) より新しいバージョン (4.12) が存在する

このように、dependencyUpdates タスクを実行するだけで、プロジェクトで使用するライブラリの更新情報を一括で取得することが出来ました。

また、dependencyUpdates タスクにオプションを指定することで、更新情報をreleaseバージョンに限定したり、出力フォーマットを xml や json にすることも可能です。
(詳細は ドキュメント を参照下さい)

gradle dependencyUpdates -Drevision=release -DoutputFormatter=json -DoutputDir=/any/path/with/permission

dependencyUpdates タスクを手動で実行するのが面倒な場合は、CI (継続的インテグレーション) で dependencyUpdates タスクの出力を解析し、更新情報があれば通知するといった運用も可能ですね。

まとめ

今回は、ライブラリの更新情報を一括で確認することができる Gradle Versions Plugin を紹介しました。
便利かつ簡単に導入することが出来るので、プロジェクトに導入してみてはいかがでしょうか?

リモートiOS開発成功の処方箋、早期のCI導入

どうも、ギルドワークス 前川です。京都からリモート作業を行っていますが、この二週間は、祇園祭でとんでもない人出となっております。

リモートでの開発に必要なもの

ギルドワークスでは、Webサービスだけでなく、iOSやAndroidの開発もリモートで行ってきています。その中で、最近一つのパターンとなっているのが「可能な限り初期に継続的ビルド(CI)を導入する」ことです。

もちろんCIは手段でしかありません。その目的は、「全員が同じものを見て確認する」ためです。対象がWebサービスならば、例えばHerokuにデプロイされたものを正として扱ってやれば、事は済みます。

しかしiOS開発では、そうはいきません。全員が「同じもの」を見ることが非常に重要ですが、それにはCIされた成果物を共通の場所においておき、それを参照する、これしかありません。

ここは結構厳格にやらなければいけない、と私は思ってます。例えばレビュー指摘をしても「ここは自分の環境では動いてますんで」などと言われると、そこで会話が止まってしまい、フィードバックが割と根本から絶たれてしまうのです。

「masterにpushされたものが唯一にして絶対の正」これを守るのは、簡単で、そしてもとても即効性のある、リモートiOS開発改善の処方箋なのです。

ギルドワークスが利用しているサービス:Circle CI

iOSのビルドはまだまだローカルJenkinsが主流だとは思いますが、リモートワークを掲げる当社としては、やはりCIを行ってくれるWebサービスを使用したいところです。

というわけで、ギルドワークスが利用しているサービスがCircle CIとなります。

Circle CIは”Experimental Setting(実験的な設定)”ながらもiOSのビルドを行うことができます。しかも、ビルド速度に制限はかかってしまうものの、Private レポジトリを含めて無料 でCIサービスを利用できます。

詳しい設定は、以下の公式ドキュメント(英語)をご覧ください。

iOSビルドの便利ツール、Schenzen

CircleCIでは、基本的にコマンドラインでビルドを実行していきます。

一応Xcodeにもxcodebuildというビルドツールが付属しているのですが、設定項目が結構多く、なかなか使いこなすのは大変です。また、iOSのファイル配布型式であるIPAファイルを作るのには、別のコマンドを色々叩く必要があり、大変です。

そんな時便利なのが、schenzenというコマンドラインツールです。

このツールを使えば、環境変数さえ適切に設定していれば、以下のように非常にシンプルなスクリプトで、ipaのビルドから、DeployGateなどのベータ配布サービスへの配信までやってくれます。

ipa build
ipa distribute

これらのサービスを活用して、ギルドワークスでは、以下の様なデプロイメントパイプラインを、手軽に組むことができています。

スクリーンショット 2015-07-14 18.45.01

これからのCIのトレンド

こういったギルドワークスでの取り組みを踏まえて、先日大阪の「CI勉強会」という勉強会で発表をしてきました。

タイトルは、「ポストJenkins時代のビルド戦略」

Jenkins一択時代から、色々なサービスを組み合わせる時代へ。今、結構大きな転換点が来ていると思っています。新しいツールやサービスとしっかり向き合って、自分たちの組織に最適な解を導きたいですよね。

もし、このようなCI周りの技術的悩みがおありなら、ギルドワークスにお気軽にお問い合わせください!