phpUnderControl

Info | HTML | Text

Documentation

Base Setup

This section describes how to install CruiseControl and phpUnderControl. If you have read the following lines you should be able to set up your own continuous integration environment for PHP development.

Setting up CruiseControl and phpUnderControl

The first things you need is a Java environment and a working installation of CruiseControl. I assume that Java is already installed and so I will not cover this topic here, but I suggest to use an original Java version from SUN instead of some versions bundled with linux distributions, because in combination with compiz or beryl the metrics view may be broken otherwise.

Setting up a working CruiseControl installation is a really simple task. Just download one of the provided zip archives from the project site, unpack the contents into an arbitrary folder and start the application. For a detailed installation description how to install CruiseControl and how to configure it with PHPUnit I recommend an excellent article by Sebastian Nohn and the Continuous Integration chapter from the PHPUnit Pocket Guide.

Please note the CruiseControl tutorial uses version 2.4.*, but the current version is 2.7.*. So please install an up to date version, because it is required by phpUnderControl!

Now that you have a working CruiseControl, check out phpUnderControl from the PHPUnit Subversion repository.

svn co svn://svn.phpunit.de/phpunit/phpUnderControl/trunk phpUnderControl

Now you can patch your CruiseControl installation by entering

phpUnderControl/bin/phpuc(.php|.bat) install /path/to/cruisecontrol

This command will exchange some template and the original metric charts and it installs additional resources.

That's it.

Getting started with CruiseControl

This section describes the required steps to set up and configure a custom project using the ant build system. The following describtion is based on the example files bundled with phpUnderControl since version 0.2.2. To illustrate the configuration the following paragraphs use the phpUnderControl subversion repository.

The first thing that is needed is a root directory for the project. This directory must be located under /path/to/cruisecontrol/projects. If you use the example files shipped with phpUnderControl the project directory must be named phpundercontrol.org/.

/path/to/cruisecontrol/projects/phpundercontrol.org

For custom projects you have to adjust the matching sections in the config.xml and build.xml files. Both files can also be found in the phpUnderControl docs directory.

The ant build.xml file

The first thing that is needed for a project build is the ant build.xml file in the new project directory. This file is comparable with a engineering blue print that describes how to create a product.

/path/to/cruisecontrol/projects/phpundercontrol.org/build.xml

At first the file should contain the following lines. If your project directory has a different name you should change the @name attribute to that name.

<?xml version="1.0" encoding="UTF-8"?> <project name="phpundercontrol.org" basedir="."> </project>

Next, we need a working copy of the source code. The initial checkout is done by hand, as example we use the phpUnderControl trunk.

svn co svn://svn.phpunit.de/phpunit/phpUnderControl/trunk source
Checkout target

To run a build against the latest source code version we must alter the build.xml file to update working copy before the build process starts. The shown target executes a 'svn up' in the phpundercontrol.org/source/ directory.

<?xml version="1.0" encoding="UTF-8"?> <project name="phpundercontrol.org" basedir="."> ... <target name="checkout"> <exec executable="svn" dir="${basedir}/source"> <arg line="up" /> </exec> </target> ... </project>

To test that this target works, open a console and change your working dir to /path/to/cruisecontrol/projects/phpundercontrol.org/ and enter

mapi@arwen:phpundercontrol.org$ ../../apache-ant-1.7.0/bin/ant checkout

The result should look similar to:

Buildfile: build.xml checkout: [exec] At revision 2016. BUILD SUCCESSFUL Total time: 1 second
PHPDoc target

The next think we need is an up to date api documentation, so we have to add a new target for PhpDocumentor that generates the documentation on each build cycle.

<project name="phpundercontrol.org" basedir="."> ... <target name="php-documentor"> <exec executable="phpdoc" dir="${basedir}/source"> <arg line="-ct type -ue on -t ${basedir}/build/api -tb /PATH/TO/YOUR/PHPUC/DATA/phpdoc -o HTML:Phpuc:phpuc -d src/"/> </exec> </target> ... </project>

phpUnderControl comes with its own phpDocumentor template that uses a special color scheme that harmonises with the phpUnderControl layout. To use this template you must adjust the -tb option to point onto the phpUnderControl data/phpdoc directory. Furthermore you must set the phpDocumentor output format to HTML:Phpuc:phpuc. The structure of this template is inspired by the eZComponents api documentation.

This target runs PhpDocumentor against the phpundercontrol.org/source/src directory and it stores the generated files under phpundercontrol.org/build/api, which must be created manual.

mapi@arwen:phpundercontrol.org$ mkdir -p build/api

The php-documentor target could be tested similar to the checkout target.

mapi@arwen:phpundercontrol.org$ ../../apache-ant-1.7.0/bin/ant php-documentor
CodeSniffer target

In this section we integrate a PHP_CodeSniffer target into the build file. The target looks similar to the previous targets, the only difference is the @output attribute that forces ant to write the command line output into the phpundercontrol.org/build/logs/checkstyle.xml file.

<project name="phpundercontrol.org" basedir="."> ... <target name="php-codesniffer"> <exec executable="phpcs" dir="${basedir}/source" output="${basedir}/build/logs/checkstyle.xml"> <arg line="--report=checkstyle --standard=PEAR --ignore=src/autoload src/"/> </exec> </target> ... </project>

Before this target can be tested the output directory must be created.

mapi@arwen:phpundercontrol.org$ mkdir -p build/logs
PHPUnit target

Finally a target for PHPUnit must be added to the build file. The primary difference here is the @failonerror attribute. This forces ant to emit a build failed signal, if this target doesn't run thru. The different PHPUnit logs are stored in the phpundercontrol.org/build/logs directory which already exists, but for the coverage html report the directory phpundercontrol.org/build/coverage must be created.

mapi@arwen:phpundercontrol.org$ mkdir -p build/coverage

For a detailed description of the available PHPUnit command line options visit the excellent online documentation about the command line options or the new xml configuration.

<project name="phpundercontrol.org" basedir="."> ... <target name="phpunit"> <exec executable="phpunit" dir="${basedir}/source" failonerror="on"> <arg line="--log-xml ${basedir}/build/logs/phpunit.xml --log-pmd ${basedir}/build/logs/phpunit.pmd.xml --log-metrics ${basedir}/build/logs/phpunit.metrics.xml --coverage-xml ${basedir}/build/logs/phpunit.coverage.xml --coverage-html ${basedir}/build/coverage phpucAllTests tests/AllTests.php" /> </exec> </target> ... </project>
Finishing the ant build file

Finally we have to combine the four independent targets into a single target. So create we create a new target build that depends on the other four. Therefore the target element accepts the attribute @depends that takes a comma separated list of other targets.

<project name="phpundercontrol.org" basedir="."> ... <target name="build" depends="checkout,php-documentor,php-codesniffer,phpunit" /> ... </project>

Because the new build target is our default target we add the @default attibute to the project root element. This attribute forces ant to execute this target if no other target was passed in as command line argument.

<project name="phpundercontrol.org" default="build" basedir="."> ... </project>

The final directory structure looks similar to the following example:

<path-to-cruisecontrol> |- projects | |- phpundercontrol.org | | |- build | | | |- api | | | |- coverage | | | |- logs | | |- source

and the build.xml file:

<?xml version="1.0" encoding="UTF-8"?> <project name="phpundercontrol.org" default="build" basedir="."> <target name="build" depends="checkout,php-documentor,php-codesniffer,phpunit" /> <target name="checkout"> <exec executable="svn" dir="${basedir}/source"> <arg line="up" /> </exec> </target> <target name="php-documentor"> <exec executable="phpdoc" dir="${basedir}/source"> <arg line="-ct type -ue on -t ${basedir}/build/api -tb /PATH/TO/YOUR/PHPUC/DATA/phpdoc -o HTML:Phpuc:phpuc -d src/"/> </exec> </target> <target name="php-codesniffer"> <exec executable="phpcs" dir="${basedir}/source" output="${basedir}/build/logs/checkstyle.xml"> <arg line="--report=checkstyle --standard=PEAR --ignore=src/autoload src/"/> </exec> </target> <target name="phpunit"> <exec executable="phpunit" dir="${basedir}/source" failonerror="on"> <arg line="--log-xml ${basedir}/build/logs/phpunit.xml --log-pmd ${basedir}/build/logs/phpunit.pmd.xml --log-metrics ${basedir}/build/logs/phpunit.metrics.xml --coverage-xml ${basedir}/build/logs/phpunit.coverage.xml --coverage-html ${basedir}/build/coverage phpucAllTests tests/AllTests.php" /> </exec> </target> </project>

The CruiseControl config.xml file

Now that we have a working ant build.xml file, we can start to configure the CruiseControl project. CruiseControl uses one central configuration file config.xml that holds all projects. This file can be found the CruiseControl root directory.

First of all we need a project element for the new project.

<?xml version="1.0" encoding="UTF-8"?> <project name="phpundercontrol.org" buildafterfailed="false"> </project>

The optional attribute @buildafterfailed can be used to force CruiseControl that it retries to build a project, after a failed build without changes to the project sources. This option can be useful if the build process is based on an external resource, like a database server that could timeout during the build process.

Including required plugins

For this example we asume that the version control system Subversion is used for the project sources. And the first thing we must do is to load the required svn-plugin.

<?xml version="1.0" encoding="UTF-8"?> <project name="phpundercontrol.org" buildafterfailed="false"> <plugin name="svn" classname="net.sourceforge.cruisecontrol.sourcecontrols.SVN" /> </project>
The modificationset triggers a build

Now we must define the case when CruiseControl should try to build a new project version. This is done in the modificationset element. If you have played with the phpUnderControl example project, you already know the alwaysbuild trigger, that performs a build after a defined interval. But for this example we use Subversion to manage the project sources, so we only want a new build if there was a source change.

<?xml version="1.0" encoding="UTF-8"?> <project name="phpundercontrol.org" buildafterfailed="false"> ... <modificationset quietperiod="60"> <svn localWorkingCopy="projects/${project.name}/source/"/> </modificationset> </project>

The previous modificationset checks that there are changes in the Subversion repository for the local project checkout projects/${project.name}/source/, that are older than 60 seconds. If this is true, CruiseControl will start a new build for this project.

The main project build process

With the existing configuration CruiseControl knows the context project, the used version control system and when it should start a build process, but it doesn't know what to do. This is done with the schedule element that accepts an optional @interval attribute, that defines the number seconds to wait between two builds. The default schedule interval is 300 seconds(five minutes).

The schedule element accepts multiple|different child elements that execute the main build process. For this sample we call ant with the project build.xml file.

<?xml version="1.0" encoding="UTF-8"?> <project name="phpundercontrol.org" buildafterfailed="false"> ... <schedule interval="120"> <ant anthome="apache-ant-1.7.0" buildfile="projects/${project.name}/build.xml"/> </schedule> </project>
Listeners
Logging
Howto publish the latest build

Command Line Interface

The phpUnderControl package comes with a set of cli commands that aim to provide an easy way to work with CruiseControl. In the following sections you will find detailed descriptions for each command. All examples expect that you have changed your current working dir to the phpUnderControl/bin directory.

The Install Command

To patch your CruiseControl installation you must execute the "install" command.

[mapi@frodo.xplib.de bin]$ ./phpuc install /opt/cruisecontrol Performing CruiseControl task. Performing modify file task. 1. Modifying file "/index.jsp". 2. Modifying file "/main.jsp". 3. Modifying file "/metrics.jsp". 4. Modifying file "/xsl/buildresults.xsl". 5. Modifying file "/xsl/errors.xsl". 6. Modifying file "/xsl/header.xsl". 7. Modifying file "/xsl/modifications.xsl". Performing create file task. 1. Creating file "/footer.jsp". 2. Creating file "/header.jsp". 3. Creating file "/phpcs.jsp". 4. Creating file "/phpunit.jsp". 5. Creating file "/phpunit-pmd.jsp". 6. Creating file "/css/php-under-control.css". 7. Creating file "/css/SyntaxHighlighter.css". 8. Creating file "/images/php-under-control/error.png". 9. Creating file "/images/php-under-control/failed.png". 10. Creating file "/images/php-under-control/header-center.png". 11. Creating file "/images/php-under-control/header-left-logo.png". 12. Creating file "/images/php-under-control/info.png". 13. Creating file "/images/php-under-control/skipped.png". 14. Creating file "/images/php-under-control/success.png". 15. Creating file "/images/php-under-control/tab-active.png". 16. Creating file "/images/php-under-control/tab-inactive.png". 17. Creating file "/images/php-under-control/warning.png". 18. Creating file "/js/shBrushPhp.js". 19. Creating file "/js/shCore.js". 20. Creating file "/xsl/phpcs.xsl". 21. Creating file "/xsl/phpcs-details.xsl". 22. Creating file "/xsl/phpdoc.xsl". 23. Creating file "/xsl/phphelper.xsl". 24. Creating file "/xsl/phpunit.xsl". 25. Creating file "/xsl/phpunit-details.xsl". 26. Creating file "/xsl/phpunit-pmd.xsl". 27. Creating file "/xsl/phpunit-pmd-details.xsl".
Arguments

The Example Command

For a quick start with CruiseControl, phpUnderControl comes with a small example project. Just enter "phpuc.php example /path/to/cruisecontrol".

[mapi@frodo.xplib.de bin]$ ./phpuc.php example /opt/cruisecontrol Performing project task. 1. Creating project directory: projects/php-under-control 2. Creating source directory: projects/php-under-control/source 3. Creating build directory: projects/php-under-control/build 4. Creating log directory: projects/php-under-control/build/logs 5. Creating build file: projects/php-under-control/build.xml 6. Creating backup of file: config.xml.orig 7. Searching ant directory 8. Modifying project file: config.xml Performing example task. 1. Creating source directory: project/php-under-control/source/src 2. Creating tests directory: project/php-under-control/source/tests 3. Creating source class: project/php-under-control/source/src/Math.php 4. Creating test class: project/php-under-control/source/tests/MathTest.php 5. Modifying config file: config.xml Performing PhpDocumentor task. 1. Creating api documentation dir: project/php-under-control/build/api 2. Modifying build file: project/php-under-control/build.xml 3. Modifying config file: config.xml Performing PHP_CodeSniffer task. 1. Modifying build file: project/php-under-control/build.xml Performing PHPUnit task. 1. Creating coverage dir: project/php-under-control/build/coverage 2. Modifying build file: project/php-under-control/build.xml 3. Modifying config file: config.xml
Options
Arguments

The Clean Command

This command provides a simple way to remove old project log files and build artifacts. Just type "phpuc.php clean -j <project> -k 10 /path/to/cruisecontrol" to keep the last ten builds.

[mapi@frodo.xplib.de bin]$ ./phpuc.php clean -j <project> -k 10 /path/to/cruisecontrol

Or you can define the maximum age of the project logs and build artifacts with. The following command will keep everything that is young than ten days.

[mapi@frodo.xplib.de bin]$ ./phpuc.php clean -j <project> -d 10 /path/to/cruisecontrol
Options
Arguments
Revision 13
By Manuel Pichler
At Sun, 08 Jun 2008 15:17:50 +0200