githubとAndroidとJenkinsの素敵な関係

head
こんにちは、GeNERACE CTO村松です。

GeNERACEではAndroidアプリ開発の継続的インテグレーションと企画側とのシームレスな連携の為にJenkinsを導入しています。
今回はその導入についてまとめます。
前提条件はJenkinsを導入するサーバに

  • Java 1.6がインストールされていること(Androidのビルドの関係で1.7はおすすめしない)
  • apacheがインストールされて起動していること
  • gitがインストールされていること
  • antがインストールされていること
  • androidのkeystoreが作成済みでリポジトリにコミットされていること

とします。

AndroidSDKを導入する

まず、Jenkinsを導入するサーバ上にlinux用のAndroidSDKを導入します。

$ sudo cd /var/lib/
$ sudo wget http://dl.google.com/android/android-sdk_r13-linux_x86.tgz #SDK取得
$ sudo tar zxvf android-sdk_r13-linux_x86.tgz
$ sudo mv android-sdk_r13-linux_x86 android-sdk-linux
$ sudo export PATH=$PATH:/var/lib/android-sdk-linux/tools/
$ sudo android update sdk -u #sdkアップデート

これでSDKの導入は完了。

Jenkinsを導入する

$ sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo
$ sudo rpm --import http://pkg.jenkins-ci.org/redhat/jenkins-ci.org.key
$ sudo yum install jenkins
#jenkinsがアクセスするディレクトリにアクセス権を割り振る
$ sudo chown -Rf jenkins /var/lib/jenkins/
$ sudo chgrp -Rf jenkins /var/lib/jenkins/
$ sudo chown -Rf jenkins /var/lib/android-sdk-linux
$ sudo chgrp -Rf jenkins /var/lib/android-sdk-linux
$ sudo service jenkins start #jenkins起動

通常はユーザー周りの設定を行ったり、セキュリティ周りの設定を行うのですが、今回は省略。

JenkinsにJenkins GIT pluginを入れる

Jenkinsを起動したら http://jenkins_hostname:8080/ にアクセス。
Jenkinsの管理>プラグインの管理>利用可能から”Jenkins GIT plugin”をインストールします。
これは、Jenkinsにデフォルトでインストールされている、”Git Client Plugin”とは別のgithubと連携する為のpluginです。

githubのリポジトリにhookの設定を行う

先ほどのJenkins GIT pluginとの連携設定をgithub上で行います。
これは、githubのリポジトリとjenkinsのジョブを繋ぐ為の設定です。
https://github.com/account_name/repository_name/settings/hooks/にアクセス。
Jenkins (Git plugin)という項目があるのでクリックし、Jenkins Urlという入力項目に以下のURLを入力します。

http://jenkins_hostname:8080/git/notifyCommit?url=git@github.com:account_name/repository_name.git

Activeにチェックを入れ、Update settingsをクリック。
以上でgithubのリポジトリとjenkinsのプロジェクトを繋ぐ設定がされます。
これで、このリポジトリに対してのプッシュやマージがあった場合、設定したURLをgithub側からキックしてくれます。

Jenkinsにプロジェクトの設定を行う

http://jenkins_hostname:8080/ にアクセス。
画像を参考にJenkinsにジョブを追加します。
Selection_003

  1. 新規ジョブ作成をクリック
  2. フリースタイル・プロジェクトのビルドを選択
  3. ジョブ名を入力
  4. OKをクリック。

画像を参考にJenkinsのジョブ設定を行います。
Selection_007

  1. ソースコード管理システム>>Git>>Repository URLに先ほどhookの設定を行ったリポジトリを入力。Branches to build>>Brannch Specifierにブランチ名を入力
  2. ビルドトリガ>>SCMをポーリングにチェック
  3. ビルド>>シェルの実行>>シェルスクリプトにビルド時に実行するshellコマンドを入力
  4. ビルド後の処理>>Email通知>>宛先に開発全体に飛ぶメールなどを設定。不安定ビルドも逐一メールを送信、ビルドを壊した個人にも別途メールを送信にチェックを入れ、保存をクリックします

項目1のリポジトリがprivateリポジトリの場合、あらかじめ以下ディレクトリにgithub認証用の鍵を置いておきます。

/var/lib/jenkins/.ssh

項目3のshellコマンドですが、GeNERACEでは以下のように設定しています。

export PATH=$PATH:/usr/apache-ant-1.8.3/bin #antのパス追加
#Android関連のパスを追加
export PATH=$PATH:/var/lib/android-sdk-linux/tools
export ANDROID_HOME=/var/lib/android-sdk-linux
export PATH=$PATH:/var/lib/android-sdk-linux/platforms
export PATH=$PATH:/var/lib/android-sdk-linux/platform-tools/
#androidアプリのプロジェクト初期設定
android update project -p /var/lib/jenkins/jobs/jenkins_job_name/workspace/
#jenkinsがgithubからcloneしたディレクトリに移動
cd /var/lib/jenkins/jobs/jenkins_job_name/workspace/
#ビルド用のantスクリプトを叩く(詳細は"アプリをAntでビルド出来るようにする"に記述)
/bin/sh build.sh
#成果物をWeb上から落とせる場所にコピーする
cp -rf ./bin/appname.apk /www/jenkins/appname.apk

アプリをAntでビルド出来るようにする

JenkinsからAntを実行しアプリをビルドする為のシェルスクリプトを追加します。

$cd /var/lib/jenkins/jobs/jenkins_job_name/workspace/
$vi build.sh #viエディタ起動、以下の内容を入力し保存する
-----ここから-----
#!/bin/sh

#リリース用ビルドを作成する
echo "build for distribution"
ant clean
ant release

cp ./bin/AppNameActivity-release-unsigned.apk ./bin/app_name.apk

#アプリのデジタル署名を行う
echo "sign apk"
jarsigner -J-Dfile.encoding=UTF-8 -verbose -keystore ./app_name.keystore -storepass keystore_password ./bin/app_name.apk keystore_area

#アプリのデジタル署名の確認を行う
echo "verify apk"
jarsigner -J-Dfile.encoding=UTF-8 -verify -verbose ./bin/app_name.apk

#パッケージの最適化
echo "zipalign apk"
zipalign -f -v 4 ./bin/app_name.apk ./bin/appname.apk

#パッケージの最適化の確認
zipalign -c -v 4 appname.apk
-----ここまで-----
#ビルドしてみる
$sh build.sh

ビルド完了後workspace/bin以下にappname.apkが出来ていることを確認します。

動作確認

設定したリポジトリ git@github.com:account_name/repository_name.gitにpushし、http://jenkins_hostname:8080/ にアクセス。
Jenkins上でビルドが実行されることを確認します。

ビルド結果確認

Jenkins上でビルド完了後、http://jenkins_hostname/appname.apk にAndroid端末でアクセス。
Android端末にダウンロードし、インストールを行い起動出来ることを確認します。

便利ツール導入

こちらのページで紹介されているJenkins Notifier for Chromeがビルド状態が分かり非常に便利なので導入します。
この時、企画側のChromeにもインストールしておくと更に良いです。

最後に

GeNERACEではこの仕組みを導入しているので、

  1. 企画側の改善提案を開発側が受ける
  2. 開発側が開発しリポジトリにpushする
  3. 企画側がjenkinsから落とし動作確認する

という流れで非常に良い連携が出来ています。
因みに、弊社アプリ宇宙上司をJenkinsでビルドした場合、EC2のt1.microだと14分、m1.smallで3分程度でした。
宇宙上司にはライブラリとしてAndEngine,AndEnginePhysicsBox2DExtension,FluctSDK,libGoogleAnalyticsV2を導入している為14分も掛かっていますが、普通のアプリであれば、恐らくt1.microで十分だと思います。
本当はAntからJUnitで行う単体テストの部分も書きたいのですが、また次の機会に書こうと思います。

ご覧いただきありがとうございました。

LinuxのシェルコマンドでFuelPHP開発環境を構築

こんにちは。金髪エンジニアのみきあらいです。今日でGeNERACEに入って2ヶ月めになります。
今回はLinuxのシェルコマンドを使ってFuelPHPの開発環境を構築する方法について書きます。

個人で開発環境を設定するのなら一人でコマンドを叩けばいいのですが、複数人で同じことをする場合、
各人がそれぞれコマンドを叩くのはあまり効率的とは言えません。
そこで、「これさえあれば一瞬で開発環境が作れる!」というシェルスクリプトを書きました。

☆下準備

  • GitのリポジトリにFuel PHPをフォークする。
  • DNSにサブドメインを設定する。
  • Apacheが入っているLinuxサーバーを準備する。
  • PHP5.3がApacheで起動していることを確認する。
  • サーバー用のssh鍵を作成する。(Git使用時に必要)
  • configファイル、xxx_setupを書いてサーバー上に置く。(注意:本物のconfigファイルではなく、あくまで別のconfigファイルを作成するためのものなので、拡張子を.confにしないこと!)

xxx_setupの中身

<VirtualHost *:80>
        ServerName 任意の名前(例:xxx)
        DocumentRoot 任意のドキュメントパス(例:/home/xxx/www/public)
        DirectoryIndex 任意のファイル(今回はindex.phpとindex.htmlを設置)
</VirtualHost>

ServerNameに記載した名前でブラウザから参照することができます。

☆今回やりたいこと

  • 作成したconfigファイル、xxx_setupの中身をコピー。
  • コピーしたファイルをもとに”各ユーザー名.conf”を作る。
  • コピー元ファイルでユーザーごとにあわせて置換したい部分を置換。(上記の例だとサーバー名やルートパス内の”xxx”を各ユーザー名に置換)
  • Gitに置いたFuelPHPをサーバーにgit cloneする。
  • Apacheを再起動する。

シェルスクリプトを書きます。
今回は”shelltest.sh”というシェルスクリプトを作成します。

vi shelltest.sh

“shelltest.sh”の編集を行います。
まず、シェルスクリプトを/bin/shで実行させます。

#!/bin/sh

echoの後ろに変数や文字列を指定します。今回はコメントを文字列として表示します。
すでに”ユーザー名.conf”がある場合も考慮し、スーパーユーザー権限で事前に削除します。-rfをつけてエラーなしで削除します。

echo "setting for httpd"
sudo rm -rf /etc/httpd/conf.d/${USER}.conf

事前に作成したxxx_setupを、”ユーザー名.conf”としてコピーします。

sudo cp -rf /etc/httpd/conf.d/xxx_setup /etc/httpd/conf.d/${USER}.conf

コピー元のxxx_setupの中には”xxx”という文字列があり、それを各ユーザー名に変えたいので、置換するためのコマンドを書きます。

sudo sed -i "s/xxx_setup/"${USER}"/g" /etc/httpd/conf.d/${USER}.conf

変数として${USER}と書くと、そのまま${USER}という文字列として置換されてしまうので、${USER}以外をダブルクオーテーションで囲みます。

次に、confで作成したDocumentRootにFuelPHPを配置します。今回は/home/ユーザー名/www以下にFuelPHPを置きます。
/home/ユーザー名/wwwが既にあることを想定して一度エラーなしで削除し、新たにディレクトリを作り直します。

echo "delete old folder"
rm -rf /home/${USER}/www
echo "settings"
mkdir /home/${USER}/www

/home/${USER}/wwwに移動し、Gitに置いたFuelPHPをサーバーにクローンします。
git@github.com:の後ろにはGithubの各人のユーザー名を書くので、変数として$1を引き渡します。

echo "clone git@github.com:"$1"/fuel.git "
cd /home/${USER}/www/
git clone git@github.com:$1/fuel.git

今回はクローンするだけとしましたが、中央リポジトリのリモートリポジトリを作成したい場合は以下のコマンドを書きます。
(例:fuel.gitのクローン元があるGithubのユーザー名=”UserXXX”、リモートリポジトリ名=”upstream”)

git remote add upstream git@github.com:UserXXX/fuel.git

例として”dev”というブランチを作成し、devブランチに切り替えてpullとpushを行います。

git checkout dev
git pull upstream dev
git push origin dev

最後に作成したconfファイルを反映させるためにApacheを再起動させます。
restartだとエラーが起きたときにApache自体が落ちてしまうので、それを避けるためにgracefulコマンドを使います。

echo "graceful httpd"
sudo /etc/rc.d/init.d/httpd graceful

“shelltest.sh”の編集モードを終了します。これで”shelltest.sh”の完成です。

☆”shelltest.sh”の実行!
早速作成した”shelltest.sh”を実行しましょう。引数$1としてLinuxに渡すGitHubの各人のユーザー名を実行時に入力します。

cd shelltest.shが格納されている場所
sh shelltest.sh GitHubの各人のユーザー名

これでシェルスクリプトを叩くだけで、FuelPHPの開発環境ができるようになります!
シェルスクリプト全体はこちらのgistを参照してください。

今回はここまでです。ご覧いただきましてありがとうございます。

参考記事一覧

GitとGitHubを使いこなすためのメモ

こんにちは。2月から入った新人のあらいみきです。今日から「爆速」で開発できるエンジニアになるために頻繁にメモを書き残します。
第一弾のテーマはGitです!

macでGitを使いこなすための簡単なメモ。

1. 下準備

☆用意するもの

  • Xcodeがインストールされていて、Command Line Toolsが入っているmacbook

☆インストールするもの

  • Tower

☆GitHubの設定をする。

  • GitHub https://github.com/

☆Git coreをmac portでダウンロード

$ sudo port install git-core

☆Gitのバージョンを確認

$ git version

2. Gitを使う

☆登場人物

  • 中央リポジトリ…メインユーザーが持つプロジェクトのリポジトリ。
  • リモートリポジトリ…各人が中央リポジトリからforkしたリポジトリ。メインユーザーではなく各人のリポジトリとなる。
  • ローカルリポジトリ…リモートリポジトリからローカルへクローンして作るリポジトリ。

☆Gitのおさらい

  • fork…自分のGitのリポジトリに任意のGitのリポジトリをコピーする。
  • pull…任意のリモートリポジトリの変更を自分のところに反映させる。
  • push…自分のリモートリポジトリに、自分のローカルでの変更を反映させる。commitとセットで行うとわかりやすい。
  • commit…自分がローカルで行った変更を確定させる。commitしただけだと変更が自分のリモートリポジトリ反映されないことに注意!(svnとは違う)
  • pull request…自分のリモートリポジトリの変更を中央リポジトリに反映させたい場合は、中央リポジトリに対してpull requestを送る。
  • master…リポジトリの大本命。ここを簡単に変えられないように枝分かれのリポジトリ(=branch)を作る。
  • 中央リポジトリの設定について…Git Flowに似た運用をしているので、中央リポジトリの更新用にリモートリポジトリを追加します。

    中央リポジトリの設定について詳細は後述

☆ローカルにgitのリポジトリを置くディレクトリを作る。

$ mkdir Git用ディレクトリ名

☆GitHubでコピーしたいリポジトリをforkする。

☆forkしたリポジトリのクローンをローカルに作る。

$ cd Git用ディレクトリ名
$ git clone git@xxx/yyy.git
$ git checkout -b ブランチ名

※今回はSSHの鍵認証を使ってるので、HTTPではなくSSHを選択しました。

☆中央リポジトリの設定を行う。
今回は中央リポジトリのリモートブランチとして、”upstream”という名前のリモートブランチを作成しました。

$ git remote add upstream git@フォークしたリポジトリの元のURL

☆ローカルで、クローンしたリポジトリ内のどこかに変更を加える。

☆自分の変更をまずはコミットさせる。

  • Towerの左側のBRANCHESは常にチェックすること。ターゲットになってるブランチだったら、ブランチ名の横に(HEAD)と書いてある。
  • コミットさせたい変更したファイルを選ぶ方法→Statusタブを開いて、任意のファイルのStagedをチェックする。チェックしたら、上部にあるチェック印の”Commit”ボタンをクリック。

これで「コミットは完了」!、、だけどローカルの変更は自分のリモートリポジトリに反映されていない。pushをして、ローカルでの変更を自分のリモートリポジトリに反映させる。

☆変更をpushする。
Towerの上部のpushボタンをクリックし、ブランチの場所を要確認してokボタンをクリックする。
これで自分のリモートリポジトリにも変更した内容が反映させる。
今回はTowerでpushしましたが、ターミナルを使う場合は以下のコマンドを打ちます。

$ git push origin ブランチ名/プロジェクト名

※引数なしのpushをすると、カレントブランチに関わらずローカルブランチと同名のブランチがリモート上にある場合はそれらを一気にpushします。

☆中央リポジトリの最新版を取り込む。

$ git pull upstream ブランチ名

☆pull requestを送る。
GitHub上で自分がフォークしたリポジトリのページに遷移し、Commitsというタブを選択し、自分のpush内容が反映されていることを確認し、pull requestボタンをクリックする。

  • pull(変更を)する側…master
  • pullするもの…pull requestを送る側が変更した箇所

これで中央リポジトリの管理者にpull requestが送信される。

※pull requestを押した後、Tower上で空pushをする。これで自分が行った変更+中央リポジトリの変更を自分のリモートリポジトリに反映することができる。

☆mergeしたいときは?

自分がpull requestを送ったと同時にほかの誰かもpull requestを送ったとき、エラーや競合が起きない範囲で変更を反映させたいところです。

そこでGitHub上でmerge pull requestボタンを押すと、簡単にmergeを行うことができます。さらにmergeされた箇所に対してコメントを書くこともできます。これでソースレビューとマージが同時にできます!

※自分が行った変更と他の人が行った変更がコンフリクトした場合。
例えば他の人と同じファイルを変更していて、pullした際にeclipse上などでファイルを確認したときにエラーが起こっている場合は、自分でeclipe上で変更分を手動でマージする必要があります。その後改めて変更分をpushし、pull requestを送る必要があります。

今回はここまでです。ご覧いただきましてありがとうございます。

参考記事一覧