CIツール Jenkins を使ってみた

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

最近社内で何かと話題になっている CI(継続的インテグレーション)ツール Jenkins を使ってみました。
プロジェクトの開発メンバー各々でデプロイを行うと、何かと設定ミスやビルド環境の違いにより、
思わぬトラブルや、余計な時間のロスを招いたりします。
そんなときは、Jenkins がスマートにビルドを行ってくれますので、このおじちゃんに頼ってみましょう。

Jenkins を導入

Jenkinsには、パッケージ形式とwar形式があるようです。 今回はビルドサーバにtomcatがインストール済みなので、war形式で導入します。

ビルドサーバにログインし、wget でwarファイルを取得します。

$ wget http://mirrors.jenkins-ci.org/war/latest/jenkins.war

tomcatのwebappディレクトリにコピーし、Tomcatを起動します。

$ mv jenkins.war /usr/local/tomcat/webapps/
$ cd /usr/local/tomcat/
$ ./bin/startup.sh

デプロイされました。非常に簡単ですね。

Jenkins にアクセスしてみる

http://[servername]:8080/jenkinsにアクセスします。

準備中・・・

少し経つと、Jenkins が起動されました。

ビルド対象プロジェクトを作成する

プロジェクトの構成は以下の通りです。

distパッケージ以下に、本番用のプロパティファイル(jenkins.properties)を置きました。

build.xmlからwarタスクを実行すると、本番用のプロパティファイルを参照し、warファイルを作成するようにします。
以下が、build.xmlになります。

<?xml version="1.0" encoding="UTF-8"?>
<!-- ======================================================================
     ExJenkins
     ExJenkins build file

     yamato
     ====================================================================== -->
<project name="ExJenkins" default="war" basedir=".">

    <description>
        ExJenkins build file
    </description>

    <property name="webapp" value="${basedir}/src/main/webapp"/>
    <property name="compile.src" location="${basedir}/src/main/java"/>
    <property name="compile.resources" location="${basedir}/src/main/resources"/>
    <property name="compile.dest" location="${webapp}/WEB-INF/classes"/>
    <property name="dist.resources" location="${basedir}/src/dist/resources"/>
    <property name="war.dir" value="${basedir}/war"/>
    <property name="tomcat.dir" value="/usr/local/tomcat/lib"/>

    <!-- =================================
          target: init
         ================================= -->
    <target name="init" description="initialize">
        <mkdir dir="${war.dir}"/>
    </target>

    <!-- =================================
          target: compile
         ================================= -->
    <target name="compile" description="compile the source" depends="clean">
        <mkdir dir="${compile.dest}"/>
        <javac srcdir="${compile.src}" destdir="${compile.dest}" encoding="UTF-8"
            includeantruntime="false">
            <classpath>
                <fileset dir="${webapp}/WEB-INF/lib">
                    <include name="*.jar"/>
                </fileset>
                <pathelement location="${tomcat.dir}/servlet-api.jar" />
                <pathelement location="${tomcat.dir}/annotations-api.jar" />
                <pathelement location="${tomcat.dir}/el-api.jar" />
                <pathelement location="${tomcat.dir}/jasper.jar" />
                <pathelement location="${tomcat.dir}/jsp-api.jar" />
            </classpath>
        </javac>
        <copy todir="${compile.dest}">
            <fileset dir="${compile.resources}"/>
        </copy>
        <copy todir="${compile.dest}" overwrite="true">
            <fileset dir="${dist.resources}"/>
        </copy>
    </target>

    <!-- =================================
          target: war
         ================================= -->
    <target name="war" depends="init,compile" description="generate the WAR file">
        <patternset id="exclude.fileset">
            <exclude name="WEB-INF/lib/sources/**"/>
        </patternset>
        <war destfile="${war.dir}/ExJenkins.war"
            webxml="${webapp}/WEB-INF/web.xml"
            basedir="${webapp}">
            <patternset refid="exclude.fileset"/>
        </war>
    </target>

    <!-- =================================
            target: clean
        ================================= -->
    <target name="clean" description="clean up">
        <delete dir="${compile.dest}"/>
    </target>

</project>

tomcatのlibパスは、ビルドサーバ上のパスを指定します。

<property name="tomcat.dir" value="/usr/local/tomcat/lib"/>

Jenkinsでジョブの作成

Jenkinsでジョブを作成します。
新規ジョブ作成で、ジョブ名を入力し、OKをクリックします。

SVN の指定

先ずはSVNのパスを指定します。
リポジトリURLとチェックアウト方式を選択します。

ここで気を付けなくちゃいけないのは、チェックアウト方式で、'svn update' を実行 を選択してしまうと、
ワークスペースに古いファイルが残る恐れがあるので、'svn revert' してから 'svn update' を実行 を選択するようにします。

SVNの"認証を入力"という警告が表示されているので、クリックしてアカウントを指定します。

SVNのアカウントを指定して、実行をクリックします。
実際に運用する際は、Jenkins専用のアカウントを作っておくといいと思います。

Ant の指定

プロジェクトで作成した、build.xmlのタスクを指定します。

シェルの指定

ビルド後にシェルを実行することが出来ます。
今回は例として、ホームディレクトリにwarファイルをコピーするだけのシェルを作成しました。

#!/bin/bash

WORKSPACE=/home/classmethod/.jenkins/workspace/ExJenkins
BUILD_DATE=`date '+%Y%m%d%H%M%S'`

cd ~/dist

mkdir $BUILD_DATE

cp $WORKSPACE/ExJenkins/war/ExJenkins.war $BUILD_DATE/

ビルドの実行

ビルドを実行すると、コンソール出力からビルドの状態が確認できます。

ビルド結果を確認する

ビルドサーバでビルド結果を確認してみます。

$ pwd
/home/classmethod/dist/20120221105420
$ ls -ltr
-rw-rw-r-- 1 classmethod classmethod 7854650 2012-02-21 10:54 ExJenkins.war

正しくwarファイルが作成されました。

まとめ

以上で簡単なJenkinsの使い方は終わりです。
今回は、シンプルな構成でしたが、あるプロジェクトをビルド後に別プロジェクトをビルドしたり、
メールを飛ばしたり、ビルド時間をスケジュールしたり、自動テストを行ったりと、他にも様々な機能があります。
みなさんのプロジェクトでも是非導入してみてください!