巨人の肩から銀の弾丸

Silver Bullet from the Shoulders of Giants - 銀の弾丸が難しくても、"銅"の弾丸くらいは撃てるように。Webソフトウェア開発に加え、自然言語処理、機械学習等の分野に触れる予定です。

Git, Maven, Jenkins, GlassFishを使った継続的インテグレーション(CI) (1)

こんにちは。
今日は、プライベートで最近試している開発環境整備の一環として、
Jenkinsを使った自動テスト・ビルドについて書きたいと思います。

What is CI?

Continuous Integration(継続的インテグレーション
1度限りもしくは数回限りではなく、継続的に小まめにビルドを実行していくプラクティス
(http://www.atmarkit.co.jp/ait/articles/1309/04/news022.html)


Merits

ここも、上記(http://www.atmarkit.co.jp/ait/articles/1309/04/news022.html)の引用ではありますが・・・。

  • 想定外の状況が起こったときに、素早く検知できる
    • 仕込んでしまったバグを即座に検知できる
  • 開発者の環境依存の問題を検知しやすくなる
    • 「私の環境では動くけど・・・」
  • ビルドが属人化せずに画一的になりやすい
    • 「◯◯さんがビルドしたら失敗/成功した」

こういう状況に思い当たる節のある人も、少なくないのではないでしょうか・・・。


とはいえ

  • 導入が面倒そう
    • 一部のメンバーだけで利用してもOK
    • 手動ビルド・テストと組み合わせてもOK
  • まずは簡単なところから
    • ex. ビルドエラーが起きた場合はコミット者にメールを通知する

そうですね。できるところからはじめたいものです。


Sample development flow試してみました

最終的には、仕事で関わっているプロジェクトに還元したいのですが、
まずは全体像をつかむために、最小限のサンプルアプリを動かすことにします。

Environments

開発フローは、masterから機能ごとにブランチを切るGitHubフローにしてみました。
git-flowは少し複雑すぎる印象を受けたので・・・。

使わなかったEnvironments

次の機会に試してみたいです。

構成図

こちらのサイト(http://qiita.com/hiroshik1985/items/6433d5de97ac55fedfde)より引用
サンプルアプリでは、RDSにもアクセスしていないし、replicationも実はしていませんが(笑)
ELB経由でEC2インスタンスにアクセスします(図の左半分)。
簡単のため、このEC2インスタンス1つに、JenkinsもGlassfishも載せています。

f:id:tsumiki_brick:20150726003617p:plain


demoの流れ

  • 説明的な名前のブランチをmasterから作成する (add-two-number-division)
  • 作成したブランチでローカル開発/プッシュ
  • Pull Request を作成
    • 自動テストNG (11/2 = 5?)
    • テストの成功数、coverage、バグ温床、スタイルの問題、を指摘してくれる
  • 再度、ローカル開発
  • 再度、プッシュ
    • 自動テストNG
  • 再度、ローカル開発/プッシュ
    • 自動テストOK
  • masterへマージ
  • なるべく早くデプロイ

準備

サンプルプロジェクトを準備

JAX-RSを使ったREST APIと、それを表示するためのフロントエンドをAngularJSでコーディングしました。
仕様は・・・見ての通り、超カンタンにしてます。
自動テストの確認もしたいので、JUnitREST API単体テストも作っておきます。


f:id:tsumiki_brick:20150726003900p:plain


AWSの設定

基本的に上記サイト (http://qiita.com/hiroshik1985/items/6433d5de97ac55fedfde) に従って設定しました。

Jenkinsのインストール

ローカルからEC2インスタンスにログインし

ssh -i ~/.ssh/aws/[キーペアファイル… ex. xxx.pem] ec2-user@[Public IP/Elastic IP… ex. 5X.XX.XXX.XX]

Jenkins公式 (http://pkg.jenkins-ci.org/redhat/) に従ってインストールします。

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

Glassfishなど他のアプリとかぶらないポート(例えば9696)にするには、

ls -ltr /etc/sysconfig/jenkins
vi /etc/sysconfig/jenkins
==============================
JENKINS_PORT=“8080”
↓
JENKINS_PORT=“9696==============================

ポート変更できたら、

# Jenkinsのサービスを起動
sudo service jenkins start # (restart, stopもある)
# 自動起動の設定
sudo chkconfig jenkins on
# ステータス確認
sudo service jenkins status
# 最新化
sudo yum update


ELB経由でEC2上のJenkinsにアクセスできるように、AWSコンソールから設定します。

# 本来はSSLでやった方がいい気がしますが・・・
Security Groups 
    test-web-elb ※任意のIP→ELBに、ポート9696でアクセスさせる
        Custom TCP Rule    TCP    9696    0.0.0.0/0
    test-web ※ELB→webは、VPC内アクセスを許可する
        Custom TCP Rule    TCP    9696    10.0.0.0/16

Load Balancers - Listeners ※ ELBからEC2インスタンスへ繋ぐ
    HTTP    9696    →    HTTP    9696


最後に、ブラウザからJenkinsのホーム画面にアクセスできたらOK!
http://[ELBのURL]:9696/

こちらのリンク (http://dev.classmethod.jp/cloud/aws/jenkins_on_ec2/) などを参考に、Jenkinsのセキュリティを設定しましょう。


Glassfishのインストール+warデプロイ

公式サイト (https://glassfish.java.net/download.html#gfoseTab) から、glassfish-4.1-web.zip をローカルにダウンロードします。
インストールは自分はこちらの手順 (http://qiita.com/digdagdag/items/4d26b477bfa3c51771f8) などを参考にしました。

ちなみに、「ローカル以外からGlassFish共通操作画面に接続するには、管理者(admin)パスワードを設定しSSLを有効にする必要がある。」(http://upstart.jp/blog/?p=309)
そうです。

SSLエラーが出たので、Elastic Load Balancing の SSL 証明書を作成 (http://docs.aws.amazon.com/ja_jp/ElasticLoadBalancing/latest/DeveloperGuide/ssl-server-cert.html)。

SSL connection error
Unable to make a secure connection to the server. This may be a problem with the server, or it may be requiring a client authentication certificate that you don't have.


再起動して、デフォルトドメインのdomain1が起動中なのを確認します。

sudo bin/asadmin restart-domain
sudo bin/asadmin list-domains

f:id:tsumiki_brick:20150726004559p:plain


最後に、サンプルアプリのwarをデプロイして、開発の準備は完了です。


開発フロー

とここまで書いたところで、肩が凝ってきてしまったので、
今日は一旦筆を置こうと思います。
続編では、「demoの流れ」の部分で書いた開発フローを
自作自演で(笑)試してみようと思います。

それでは、よい週末を!