→ php staging environment for continuous integration part 2

More on: php, staging environment, continuous integration, Tue Nov 15 00:56:21 -0600 2009

In this second part, I will setup phpUnderControl (using Git for source control) and the installation of all the necessary software… Plus I will make reference to a couple of good tutorials on how to set up a PHP apps to work with Capistrano for deployment.

For the phpUnderControl setup, I pretty much followed this tutorial.

However, I changed some things… such as, using Git instead of SVN and a bit more specific on certain areas that gave me some trouble…

In any decent sized project, the more times you commit code, the bigger the chance is that you will break something. Call it the law of unintended consequences or the butterfly effect, but the fact is that in complex systems, we cannot anticipate all the effects of a change. To deal with this we can either adopt the “release and pay” method of software control, or we can setup systems to help us find the consequences of our actions, so we that can correct them before they become a problem. We usually call these systems Continuous Integration systems.

In this article, we will look at how to set up a Continuous Integration system for PHP using phpUnderControl. After reading this article, you should have a good understanding of the pieces involved in a Continuous Integration system and be able to set up and run your own.

What is Continuous Integration?

Thoroughly explaining Continuous Integration would require an article of its own or possibly a whole book. A good one-sentence definition of Integration is “Delivering a working system”, so Continuous Integration means “Continuously delivering a working system”; after every change made to the code the system can be proven to work.

Obviously, manually deploying and testing a system after every change is a very tedious job; however tedious jobs are what computers are really good at, and Continuous Integration systems are the programs that can do the work for us.


phpUnderControl is an add-on application for CruiseControl, a Continuous Integration system written in Java. It combines a number of popular PHP development tools like PHPUnit, phpDocumentor and PHP_CodeSniffer.

It can run unit tests, generate the API documentation, check the code for compliance with coding standards, and present you with a web interface to review the results. It can even turn on the lights.

Setting up phpUnderControl

For this tutorial, we will use Ubuntu Server as the reference platform, but the instructions should translate easily to other Linuxes, BSDs or even Windows. You should have a dedicated machine available, but if you don’t, it is possible can also install it on a machine used for other tasks.

As mentioned above, phpUnderControl is an add-on for CruiseControl, which is a Java application, so we install that first:

sudo apt-get install sun-java6-jdk

PHPUnit needs xDebug to generate the code coverage reports:

sudo apt-get install php5-dev php-pear pear upgrade PEAR

Now install xdebug thru PECL.

sudo pecl install xdebug

Now we need to find where went (the compiled module)

find / -name '' > /dev/null /usr/lib/php5/20060613/

Then edit php.ini:

sudo gedit /etc/php/apache2/php.ini

Add the following line:


Then restart apache for changes to take effect.

You can also, rather than including the extension in your php.ini file, it is probably more appropriate to create an .ini file specifically for this extension in /etc/php5/conf.d/xdebug.ini. The file can be as simple as:

; xdebug debugger zend_extension="/usr/lib/php5/20060613/

And then to compliment this setup, add any xdebug configuration directives to this file as well. This has two benifits:

If your main php.ini file gets changed or modified by some automated process, you don't risk losing your xdebug setup stuff.

sudo /etc/init.d/apache2 restart

Check phpinfo() to make sure the extension is loaded correctly.

The following line should have been appended to the copyright lines:

with Xdebug v2.0.0, Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, by Derick Rethans

For more information about xdebug configuration and usage, please read the official documentation, found here:

For PHPUnit, PEAR is the recommended way to install it:

This also installs the php5-cli package which you need to run PHPUnit.

For the graphs we need the ezComponents Graph library:

sudo pear channel-discover sudo pear install -a ezc/Graph

Now we get to phpUnderControl itself:

sudo pear config-set preferred_state beta sudo pear channel-discover sudo pear install --alldeps phpunit/phpUnderControl

phpUnderControl is still in beta, and by default PEAR does not install components in beta status, so we have to use config-set to make it install.

And, of course, cruisecontrol itself.

To unzip the file we need unzip:

sudo apt-get install unzip

Now we can install CruiseControl:

sudo unzip -d /opt

To make it easy to upgrade add a link to the current version:

sudo ln -s /opt/cruisecontrol-bin-2.8.2 /opt/cruisecontrol

Configure CruiseControl for phpUnderControl by running the install script:

sudo phpuc install /opt/cruisecontrol

Install the example project:

sudo phpuc example /opt/cruisecontrol

To start, CruiseControl needs the JAVA_HOME variable set. To set it add the lone below to your /etc/environment.


Additionally, to set JAVA_HOME in your current shell, execute the following command.

JAVA_HOME="/usr/lib/jvm/java-6-sun";export JAVA_HOME

We are now ready to start CruiseControl:

cd /opt/cruisecontrol sudo -E ./

If you use the -E option, you retain your own environment variables. You need the JAVA_HOME for to work properly. You can also run as a regular user, but then you have to make sure you own the whole CruiseControl tree: (Don’t do this while CruiseControl is still running.)

sudo chown -LR user:user /opt/cruisecontrol

The -R option makes the command recursive. This ensures that the ownership of the link is changed along with all files beneath it. The -L options ensures that if there are symbolic links to directories that they are traversed also.

Configuring phpUnderControl for a sample project.

We can now fire up a browser and go to http://[ip-address of ci server]:8080/cruisecontrol and it should show something like this:

Don’t worry if you see error messages in the ‘coverage’ and ‘metrics’ tags about missing files in the ‘artifacts’ directory. The configuration of the installed example project is not quite correct. You can find a fix here. We can now stop CruiseControl with:

kill `cat /opt/cruisecontrol/` Setting up a new project

Now you’re ready to set up a new project. In this example I will assume that you already have a working Git project which you can clone… after following the previous tutorial about Gitosis, most likely your project repo is in /home/git/repositories/. For this example we will call this project 'my_project'.

If you already have a project with some PHPUnit tests perfect, use that! if not, copy this two files in your "my_project" directory

Calculator.php: <?php Class Calculator { public static function Add($a, $b) { return $a + $b; } } CalculatorTest.php: <?php require_once 'PHPUnit/Framework.php'; include 'Calculator.php'; class CalculatorTest extends PHPUnit_Framework_Testcase { public function testAdd() { $this->assertEquals(3, Calculator::Add(1,2)); } }

In order to add a new project to CruiseControl you have to do three main things:

Cruisecontrol projects live in the subdirectory projects/ in the cruisecontrol/ directory, so the first step is to create a project directory:

cd /opt/cruisecontrol/projects mkdir my_project cd my_project

Then make a build.xml file there with the following content:

The structure of a project section of build.xml is always the same, a target element with a name attribute that contains an exec element.

... ...

The exec element has an executable attribute that points to the program to run and a dir attribute that determines the directory in which the program is executed. Within the exec element is an arg element that holds the command line argument.

So the checkout tagged in the exec element below

is equivalent to:

cd my_project/source git pull

A detailed description of the build.xml file can be found here.

This file lists all the steps needed to get a working system to test. Each step is called a ‘target’, and a target can depend on other targets to be finished before they can be executed. The first step is to update the code:

This will run ‘git pull’ (similar to ’svn update’) in the projects/my_project/source directory. To get our project files there, we need to a checkout first:

Git clone /home/git/repositories/my_project.git/ /opt/cruisecontrol/projects/my_project/source

You can now test your build.xml file:

../../apache-ant-1.7.0/bin/ant checkout

Ant is the program that actually runs the builds. The output should look like [source"bash"]this:

checkout: [exec] At revision 1. BUILD SUCCESSFUL Total time: 1 second

Now we can add the other targets:


An explanation for the various arguments can be found by typing

phpdoc -h

The -tb argument makes sure phpdoc uses a template that looks good with phpUnderControl. Phpdoc stores its output in the build/api directory, which you will have to create manually in the my_project/ directory.

mkdir -p build/api

And as with the checkout target, you can check if it is correct by using Ant again:

../../apache-ant-1.7.0/bin/ant php-documentor


This target puts its output in build/logs and build/coverage, which also have to be created manually:

mkdir -p build/logs build/coverage

The failonerror=on is needed to signal a failed build when phpunit returns an error. (It returns an error whenever it detects failed test). The command line arguments for PHPUnit are covered extensively in the PHPUnit documentation.


The command line arguments are documented in the php-codesniffer manual. A particularly useful parameter is –ignore, which gives you the option to ignore certain files when sniffing the code. Very useful if you have included external code which does not comply to your standards.

Putting the build.xml file together

Now we need to combine the targets to one target

And to make sure the build target is the default target, we add the default attribute:

The final build.xml file should look like this:

Configuring CruiseControl

The central configuration file for CruiseControl is config.xml, which in our example can be found in /opt/cruisecontrol/config.xml For a detailed overview of the options available for this file, check the Cruisecontrol documentation. I am going to configure our project so that it periodically runs the build, even if nothing has changed.

First, rename the old config.xml file and replace it with an empty config.xml file:

The buildafterfailed=false attribute tells CruiseControl not to attempt a build if the previous one has failed and no changes have been found. If your tests depend on an external source that can fail, like a SOAP service or a database, it might be useful to set this value to 'true'.

Then add the modification set:

The modificationset element lists the checks to find if anything has changed in the project. In this case we don't check and always build.

Now we tell CruiseControl what to do:

In the schedule element is a list with tasks to do on each build. In this case, run Ant on the build.xml file we just created. The ant element also has an optional target attribute, where you can choose the target to build. The interval attributes specifies how many seconds to wait between builds. To enable the front-end to show the status of the build, we have to add a listener:

The listener element holds elements that can communicate the status of the build to other parts of the system. In this case the currentbuildstatus puts the status in an HTML snippet that the CruiseControl webserver can read.

Now we need a place to put all the information gathered during the build process:

To publish the results of the build we need a publisher:

The two arifactpublishers take the information from the build and puts them in a publicly accessible directory. The first one takes the files from build/api, which holds the api documentation generated by phpDocumentor. The second one is for the code coverage information. The execute element generates the nice-looking graphs for your manager.

The total config.xml file should look like this:

You can now test your phpUndercontrol system.

To start CruiseControl:

cd /opt/cruisecontrol ./

And to stop it:

kill `cat /opt/cruisecontrol/`

If you start up your browser go to http://[ip-address of ci server]:8080/cruisecontrol And click on the my_project link, you should see something similar to this:

Now we're going to change the configuration file to only do the build after we have made change in the code.

Here you can find more information about how to use Git with CruiseControl

To enable CruiseControl to check Git we first have to add a plugin to the project:

And change the modification set:

The quietperiod attribute tells CruiseControl to wait with running a build for a minute after the last change to the repository. This gives you the opportunity to commit parts to the code without running the risk of breaking the build while you are still busy committing.

The final config.xml file should look like this:

... ...

If you now run CruiseControl for a while, you will see that the last build time will not change. When you make a change to the code, commit it and wait for a minute or two, you will see that a new build has been run.

Two nice features

In this section I will briefly describe two of the very many nice features available in CruiseControl, sending out an email when things break, and setting up and tearing down a database.

Sending mails when things break

You can make CruiseControl send an email on build failure by adding a publisher to config.xml:


This sends out an email to you and your boss when the build breaks and one when it's fixed.

Setting up a database

CruiseControl can set up and tear down a database for you. Below the set-up of the database. The tear-down is left as an exercise.

Simply add a new target:

And add the target to de dependencies of the build target:

This uses the java mysql library, so we have to install that:

sudo apt-get install libmysql-java

To make the target work you also have to add a db-create.sql file to your project. I used this for the example:


And you can check if it is working by calling the target from Ant:

../../apache-ant-1.7.0/bin/ant db-create

In this example we hardcode the classpath in the target, but you can also add the CLASSPATH environment variable.

See the MySQL documentation for details.

This is how the phpUnderControl admin dashboard looks like, very nice!


You now have a working Continuous Integration system. Systems like this always take time to get setup and working properly. Now however, you have a powerful tool that will help you create better software faster. The return on investment in your time will be stable code and your client's confidence in your work. Go and play around with phpUnderControl and discover more of its features and uses; spend the time to understand the system and customize it for your specific needs. The time you spend will be well worth it when you go to roll your next version into production.

If you are interested in Continuous Integration and want to read more about it, Continuous Integration by Paul M. Duval is a very good book on the subject.

More resources:

Last, but not least, Capistrano...

Now we can install Capistrano for our apps deployments… It is fairly simple; you can follow this couple of how-tos to get up and running!

blog comments powered by Disqus