CodeIgniter と Jenkins で継続的インテグレーション

CodeIgniter + CIUnit/PHPUnit + Jenkins + α で継続的インテグレーション(CI)してみましょう。

いわゆるひとつの、CI で CI です。

JDK と Ant をインストールする

$ sudo apt-get install openjdk-6-jdk
$ sudo apt-get install ant

Jenkins をインストールする

$ wget -q -O - http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key | sudo apt-key add -
$ sudo sh -c 'echo "deb http://pkg.jenkins-ci.org/debian binary/" > /etc/apt/sources.list.d/jenkins.list'
$ sudo apt-get update
$ sudo apt-get install jenkins

必要な PEAR ライブラリをインストールする

$ sudo pear channel-discover pear.phing.info
$ sudo pear channel-discover pear.pdepend.org
$ sudo pear channel-discover pear.phpmd.org
$ sudo pear channel-discover pear.phpunit.de
$ sudo pear channel-discover components.ez.no
$ sudo pear channel-discover pear.symfony-project.com

$ sudo pear install phing/phing
$ sudo pear install pdepend/PHP_Depend
$ sudo pear install phpmd/PHP_PMD
$ sudo pear install phpunit/phpcpd
$ sudo pear install PHPDocumentor
$ sudo pear install --alldeps phpunit/PHPUnit
$ sudo pear install phpunit/ppw
$ sudo pear install --alldeps phpunit/PHP_CodeBrowser
$ sudo pear install phpunit/phploc

さらに、CodeIgniter-for-PHP_CodeSniffe と CIUnit も必要です。

を参照願います。

build.xml を作成する

ここでは、「blog」プロジェクトを対象のプロジェクトとします。

ppw コマンドで設定の XML ファイルを生成します。

$ cd blog
$ ppw --name blog --source ./application/ --tests ./tests/ --bootstrap ./application/third_party/CIUnit/bootstrap_phpunit.php --phpcs CodeIgniter .

ソースコードのある ./application フォルダには CIUnit そのものも third_party/ フォルダ以下に含まれていますので、third_party フォルダを除外します。

--- build.xml.orig	2011-09-16 14:08:57.075260583 +0900
+++ build.xml	2011-09-16 15:28:10.597907801 +0900
@@ -49,7 +49,8 @@
    <arg line="${source}
               xml
               codesize,design,naming,unusedcode
-              --reportfile ${basedir}/build/logs/pmd.xml" />
+              --reportfile ${basedir}/build/logs/pmd.xml
+              --exclude third_party" />
   </exec>
  </target>
 
@@ -61,7 +62,7 @@
 
  <target name="phploc" description="Generate phploc.csv">
   <exec executable="phploc">
-   <arg line="--log-csv ${basedir}/build/logs/phploc.csv ${source}" />
+   <arg line="--log-csv ${basedir}/build/logs/phploc.csv --exclude ${source}third_party ${source}" />
   </exec>
  </target>
 
@@ -70,13 +71,14 @@
    <arg line="--report=checkstyle
               --report-file=${basedir}/build/logs/checkstyle.xml
               --standard=CodeIgniter
+              --ignore=third_party
               ${source}" />
   </exec>
  </target>
 
  <target name="phpdoc" description="Generate API documentation using PHPDocumentor">
   <exec executable="phpdoc">
-   <arg line="-d ${source} -t ${basedir}/build/api" />
+   <arg line="-d ${source} -i third_party/ -t ${basedir}/build/api" />
   </exec>
  </target>
 
@@ -84,6 +86,7 @@
   <exec executable="phpcb">
    <arg line="--log    ${basedir}/build/logs
               --source ${source}
+              --ignore ${source}/third_party
               --output ${basedir}/build/code-browser" />
   </exec>
  </target>

コードカバレッジの集計に、application フォルダ以下のテストで実行されなかったファイルも含まれるように指定します。ただし、third_party フォルダは除外します。なお、コードカバレッジの集計には Xdebug が必要です。

--- phpunit.xml.dist.orig	2011-09-16 14:08:57.079260125 +0900
+++ phpunit.xml.dist	2011-09-16 14:10:10.499649436 +0900
@@ -23,6 +23,9 @@
   <filter>
     <whitelist addUncoveredFilesFromWhitelist="true">
       <directory suffix=".php">./application/</directory>
+      <exclude>
+        <directory suffix=".php">./application/third_party/</directory>
+      </exclude>
     </whitelist>
   </filter>
 </phpunit>

この設定をすると、テストで実行されなかったファイルがあった場合、プロパティなどをうまく取得できず、以下のような Fatal error になることがあります。この場合は、実行されるようにテストを追加するか、上記の 設定で除外してください。

[CIUnit] PHP Error: Notice - Undefined property: PHP_CodeCoverage::$load File Path: blog/about.php (line: 1)
PHP Fatal error: Call to a member function view() on a non-object in /home/kenji/workspace/blog/application/views/blog/about.php on line 1

(2011/09/19) 以下の設定変更がないと、PHPUnit のテストが失敗することがありました。

--- a/phpunit.xml.dist	Mon Sep 19 20:46:53 2011 +0900
+++ b/phpunit.xml.dist	Mon Sep 19 20:47:36 2011 +0900
@@ -2,7 +2,7 @@
 <!-- Generated by PHP Project Wizard (PPW) 1.0.4 on Fri Sep 16 7:08:56 CEST 2011 -->
 
 <phpunit bootstrap="./application/third_party/CIUnit/bootstrap_phpunit.php"
-         backupGlobals="false"
+         backupGlobals="true"
          backupStaticAttributes="false"
          strict="true"
          verbose="true">

ant コマンドを実行します。

$ ant

エラーが出ずに、最後に以下のように出力されれば成功です。

BUILD SUCCESSFUL
Total time: 2 minutes 6 seconds

作成された build/code-browser/index.html をブラウザで開いてみましょう。


Jenkins のプラグインをインストールする

http://localhost:8080/pluginManager/available にアクセスし以下のプラグインをインストールします。

  • Checkstyle (for processing PHP_CodeSniffer logfiles in Checkstyle format)
  • Clover PHP (for processing PHPUnit code coverage xml output)
  • DRY (for processing phpcpd logfiles in PMD-CPD format)
  • HTML Publisher (for publishing the PHPUnit code coverage report, for instance)
  • JDepend (for processing PHP_Depend logfiles in JDepend format)
  • Plot (for processing phploc CSV output)
  • PMD (for processing PHPMD logfiles in PMD format)
  • Violations (for processing various logfiles)
  • xUnit (for processing PHPUnit logfiles in JUnit format)

バージョン管理システムの以下のプラグインもインストールします。SubversionCVS はデフォルトで入っていました。

Jenkins に PHP 用のプロジェクトテンプレートをインストールする

$ cd /var/lib/jenkins/jobs
$ sudo git clone git://github.com/sebastianbergmann/php-jenkins-template.git php-template
$ sudo chown -R jenkins:nogroup php-template 
$ sudo service jenkins restart

Jenkins の環境変数を設定する

必要な場合は、環境変数を設定します。

http://localhost:8080/ にアクセスし、「Jenkinsの管理」→「システムの設定」へと進みます。

環境変数」にチェックを入れ、「キー」と「値」を入力し、一番下の「保存」ボタンをクリックします。

Jenkins でプロジェクトを作成する

http://localhost:8080/ にアクセスし、「新規ジョブ作成」をクリックします。

「ジョブ名」と「既存のジョブのコピー」を入力し、「OK」を押します。

次のページで「ビルドの無効化」のチェックを外し、

「ソース管理システム」にリポジトリのパスを入力します。

「ビルド・トリガ」は必要な場合、設定してください。ここでは設定しないでおきます。

「ビルド実行」をクリックすると、ビルドが実行されます。


ビルドの結果です。


Checkstyle 警告。


PMD 警告。


Clover PHP カバレッジレポート。