Setting up phpUnderControl

On a regular basis, I get contacted by people who want to install phpUnderControl but don’t really know how to set up their projects and use the features provided by phpUnderControl completely. So, aside from providing a quick-and-easy setup guide for cruisecontrol and phpUnderControl, I’ll share the setup scripts I have here and hope it’s useful for someone. This guide is mostly focussed on getting phpUnderControl to work on a Debian system, but there’s not that much OS specific to it.

Getting it installed

You probably will need some tools that are related to the PHP project you want to deploy on the phpUnderControl installation and for the sake of briefness I’m not going to cover how to install them, but instead just list what might come in handy for the continuous integration system to set up:

$ apt-get install subversion subversion-tools sun-java6-jre sun-java6-jdk

Also, install php, phpdoc, phpcs, phpunit and xdebug, you’ll need it later on for unit testing, generating reports and analyzing your code. Next up, you can install cruisecontrol. Just get the cruisecontrol archive and unpack it somewhere. (I chose /opt):

$ cd /opt/
$ wget http://heanet.dl.sourceforge.net/sourceforge/cruisecontrol/cruisecontrol-bin-2.8.2.zip
$ unzip /opt/cruisecontrol-bin-2.8.2.zip
$ mv -f cruisecontrol-bin-2.8.2 cruisecontrol

By default, cruisecontrol doesn’t have a start-up script. That’s not very easy when you want to start, stop or restart the server, so let’s make it (in /etc/init.d/cruisecontrol):

#!/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:
. /lib/lsb/init-functions
JAVA_HOME=/usr
NAME=cruisecontrol
DAEMON=/opt/cruisecontrol/cruisecontrol.sh
PIDFILE=/opt/cruisecontrol/cc.pid
 
test -x $DAEMON || exit 5
 
RUNASUSER=cruisecontrol
UGID=$(getent passwd $RUNASUSER | cut -f 3,4 -d:) || true
 
case $1 in
start)
log_daemon_msg "Starting Cruisecontrol server" "cc"
if [ -z "$UGID" ]; then
log_failure_msg "user \"$RUNASUSER\" does not exist"
exit 1
fi
cd /opt/cruisecontrol/
./cruisecontrol.sh > /dev/null 2>&1
log_end_msg $?
;;
stop)
log_daemon_msg "Stopping Cruisecontrol server" "cc"
start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE
log_end_msg $?
rm -f $PIDFILE
;;
restart|force-reload)
$0 stop && sleep 2 && $0 start
;;
status)
pidofproc -p $PIDFILE $DAEMON >/dev/null
status=$?
if [ $status -eq 0 ]; then
log_success_msg "Cruisecontrol server is running."
else
log_failure_msg "Cruisecontrol server is not running."
fi
exit $status
;;
*)
echo "Usage: $0 {start|stop|restart|force-reload|status}"
exit 2
;;
esac

Set the file to have executable rights, and start the cruisecontrol server:

$ chmod +x /etc/init.d/cruisecontrol
$ /etc/init.d/cruisecontrol start

Right now, if you go to http://yourhost:8080/dashboard/, you should see a working cruisecontrol server page. If you don’t, please have a look at the previous steps and try again. A quick look at the cruisecontrol logs in /opt/cruisecontrol/cruisecontrol.log to find out what might be the problem.
For now, you can stop the cruisecontrol server:

$ /etc/init.d/cruisecontrol stop

phpUnderControl

This is even easier to install. We’ll just take the bleeding edge SVN sources so we can enjoy the latest goodies that phpUnderControl has to offer :) :

$ cd /opt/
$ svn co svn://svn.phpunit.de/phpunit/phpUnderControl/trunk phpuc
$ /opt/phpuc/bin/phpuc.php install /opt/cruisecontrol
$ /etc/init.d/cruisecontrol start

That’s it! phpUnderControl should be installed by now, which you can verify by going to http://:8080/cruisecontrol/ and see the new phpUnderControl interface. Of course, there’s not much information available at this time, let alone a useful project. But we’ll get to that in a minute :)

Configuration

All phpUnderControl projects are configured in a single config.xml file, located in the cruisecontrol install directory, in our case /opt/cruisecontrol/config.xml. To give you an idea on how this looks for most of my PHP projects, here’s an example:

<cruisecontrol>
<project name="phpfoo" buildafterfailed="false">
<plugin name="svnbootstrapper" classname="net.sourceforge.cruisecontrol.bootstrappers.SVNBootstrapper"/>
<plugin name="svn" classname="net.sourceforge.cruisecontrol.sourcecontrols.SVN"/>
 
<listeners>
<currentbuildstatuslistener file="logs/${project.name}/status.txt"/>
</listeners>
 
<bootstrappers>
<svnbootstrapper localWorkingCopy="projects/${project.name}/source/"/>
</bootstrappers>
 
<modificationset quietperiod="0">
<svn localWorkingCopy="projects/${project.name}/source/"/>
</modificationset>
 
<schedule interval="60">
<ant anthome="apache-ant-1.7.0" buildfile="projects/${project.name}/source/build.xml"
target="build" uselogger="true" usedebug="false" />
</schedule>
 
<log dir="logs/${project.name}">
<merge dir="projects/${project.name}/build/logs/"/>
</log>
 
<publishers>
<currentbuildstatuspublisher file="logs/${project.name}/buildstatus.txt"/>
<artifactspublisher dir="projects/${project.name}/build/coverage" dest="logs/${project.name}" subdirectory="coverage" />
<artifactspublisher dir="projects/${project.name}/build/api" dest="logs/${project.name}" subdirectory="api" />
 
<execute command="/opt/phpuc/bin/phpuc.php graph logs/${project.name}"/>
<htmlemail mailhost="xx.xx.xx.xx" returnaddress="foo@example.com"
buildresultsurl="http://yourhost:8080/buildresults/${project.name}"
returnname="phpUnderControl server" logdir="logs/${project.name}">
<failure address="fail@example.com" reportWhenFixed="true" />
</htmlemail>
</publishers>
</project>
</cruisecontrol>

As you can see, this file actually just looks out for changed subversion modificationsets, updates the source and then fires off the build.xml inside the project source directory. That one is actually the most interesting one, so I’ll list it here too:

<?xml version="1.0"?>
<project name="phpfoo" default="build" basedir="../">
<target name="php-documentor">
<exec executable="phpdoc" dir="${basedir}/source" logerror="on">
<arg line="-o HTML:frames:DOM/earthli -ti '${ant.project.name} documentation' -dn default -i tests/
-s on -ue on -t ${basedir}/build/api -d ." />
</exec>
</target>
 
<target name="phpcs">
<exec executable="phpcs"
output="${basedir}/build/logs/checkstyle.xml" dir="${basedir}">
<arg
line="--ignore=*/tests/* --report=checkstyle
--standard=PEAR source" />
</exec>
</target>
 
<target name="phpunit">
<exec executable="phpunit" dir="${basedir}/source/tests" failonerror="true">
<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
AllTests" />
</exec>
</target>
 
<target name="build" depends="php-documentor,phpcs,phpunit" />
</project>

This builds API documentation, runs the PHP Codesniffer and runs the unit tests, which in turn provides the code coverage, metrics, PMD and other statistics. That’s all there is to it!

25 Responses to “Setting up phpUnderControl”


  • Excellent phpUnderControl getting started tutorial, great job :-)

  • Awesome! Reminds me of the COMBELL days where we would set this up just for the fun of it!

    Good stuff, keep it coming

  • Hi,

    I installed cruisecontrol so far an I created the start/stop script for cruisecontrol but when I want to start the cruisecontrol server, i got this error:

    v31377:/opt# /etc/init.d/cruisecontrol start
    /etc/init.d/cruisecontrol: line 22: syntax error near unexpected token `&’
    /etc/init.d/cruisecontrol: line 22: `./cruisecontrol.sh > /dev/null 2>&1′

    Perhaps there is a little bug in the script.
    Would be nice if you could help to fix this bug so that I can work on on the tutorial.

  • @Nilson: Unfortunately, that was caused by an error in the formatting when I’ve published this blog post. I fixed the formatting, so now you should be able to get the right results with the startup script. If you need any other help, please let me know.
    Thanks for noticing!

  • Hi Felix,

    thanks for the help. The error caused by the formatting i also found out. My failure if i only copy and paste^^

    My next Problem is, that the cruisecontrolserver don´t start.
    If i use the start/stop-Script and run ./cruisecontrol start, i get the message that the cruisecontrolserver is starting, but i can´t reach the server on http://host:8080 and ./cruisecontrol status says that the server is not running.
    Unfortunately I can´t find a log-file in the cruisecontrol directorys.

    Would by very nice if you could help me with this problem =)

    There is also a problem for users who use a virtual machine and want to install java6. I found a solution but this took me a lot of time. Perhaps you could remember this for you blog post so that other readers don´t have the same problem. The link to this solution is http://www.groovygrails.de/blog/groovygrails/entry/debian_4_sun_java_6

  • @Nilson: there’s a line in the startup script that suppresses all stdout output. This way you don’t get loads of output when you start up cruisecontrol, but you also lose valuable debug output. If you start cruisecontrol like this: cd /opt/cruisecontrol/ && ./cruisecontrol.sh , you should see the startup output and maybe find the cause of your problem.

  • Hi,

    tested to start cruisecontrol how you said and i got an error =)

    ./cruisecontrol.sh: line 105: /bin/java: No such file or directory

    So, what I don´t understand is that java is installed. Why cruisecontrol doesn´t find java then?

    Thanks for help!

  • @Nilson: Cruisecontrol searches the JAVA_HOME environment variable for the java binary. If for example, you have java installed in /usr/bin/java, your java home should be set to /usr. You can do this by typing:
    $ export JAVA_HOME=/usr
    before executing the command line in my previous comment.

  • Hi,

    that worked. So cruisecontrol finds Java and wants to start the server but it seems that there is not enough memory.

    I got this errorMessage:

    Error occurred during initialization of VM
    Could not reserve enough space for object heap
    Could not create the Java virtual machine.

    I hope it´s ok if i ask so much because it´s really new to me.
    Beside it´s a good hint i think that i have a vServer. Perhaps this is a problem for cruisecontrol.

  • @Nilson: You can change the memory usage of your cruisecontrol setup by editing /opt/cruisecontrol/cruisecontrol.sh and looking for the line that starts with CC_OPTS=”…
    I’m just not entirely sure if that’ll fix the issue you’ve got, maybe you should check with our virtual server provider or get more memory for your virtual server. Cruisecontrol is relatively heavy on memory, and needs a minimum of 128mb dedicated to work decently.

  • ok,

    phpUnderControl is running now. Thanks for your help =)
    There are a lot of java errors or something like that when i open phpUnderControl but i´ll out find where these errors come from i think.

  • Hi,

    I got a new Problem now.
    The Problem is that “ant” hasn´t enough memory i think because i got a file “antBuilderOutput.log” in the cruisecontrol directory with the content:

    Error occurred during initialization of VM
    Could not reserve enough space for object heap
    Could not create the Java virtual machine.

    The Problem is that i don´t know where to set the memory-size for ant.
    Would be very nice if you have a solution for me =)

  • nice, but hudson is more more simplier.

    just launch :

    >java -jar hudson.war

    and it’s all.

  • @Nilson
    “There are a lot of java errors or something like that …”

    These errors I see by the subversion like installation of phpuc too.
    >svn co svn://svn.phpunit.de/phpunit/phpUnderControl/trunk phpuc

    The better way I think is the pear installer
    pear config-set preferred_state beta
    pear install –alldeps pear/GraphViz
    pear channel-discover components.ez.no
    pear install –alldeps phpunit/phpUnderControl

    Version 0.4.7 is working with clean output.

  • i setup CC, PUC and set up the project file en build file as above when i have a look throuh the website tool and click on the project name i get:

    java.lang.NullPointerException
    at net.sourceforge.cruisecontrol.taglib.CruiseControlTagSupport.getXMLFile(CruiseControlTagSupport.java:134)
    at net.sourceforge.cruisecontrol.taglib.CruiseControlTagSupport.findLogFile(CruiseControlTagSupport.java:127)
    at net.sourceforge.cruisecontrol.taglib.ArtifactsLinkTag.getTimeString(ArtifactsLinkTag.java:98)
    at net.sourceforge.cruisecontrol.taglib.ArtifactsLinkTag.getArtifactURL(ArtifactsLinkTag.java:89)
    at net.sourceforge.cruisecontrol.taglib.ArtifactsLinkTag.doInitBody(ArtifactsLinkTag.java:61)
    at org.apache.jsp.main_jsp._jspService(org.apache.jsp.main_jsp:150)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:93)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:373)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:470)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:364)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
    at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487)
    at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:362)
    at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
    at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
    at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:729)
    at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
    at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:206)
    at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    at org.mortbay.jetty.Server.handle(Server.java:324)
    at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505)
    at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:829)
    at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:513)
    at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
    at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380)
    at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:395)
    at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488)

    what do i have to do?

  • Hi,

    I have a problem with Cruise Control. I have copied your script for starting cruisecontrol, but I get always the error “/etc/init.d/cruisecontrol start
    -su: /etc/init.d/cruisecontrol: /bin/sh^M: bad interpreter: No such file or directory”. When I start Cruise Control with /opt/cruisecontrol/cruisecontrol.sh there come no error message and starts fine. I’m using Ubuntu 8.10 Server.

  • phpunit 3.4 removes the –log-metric and pmd targets as deprecated. Somebody should update the instructions how to install phpundercontrol for the new phpunits. The most important new feature of 3.4 is the –process-isolation that allows running of larger amount of tests than before

  • Hey, I installed CruiseControl with phpundercontrol but I’m having issues with the “Overview” page. It is displaying all the stdout stuff that I see on the screen while running my build loop. Is there any way of telling CC/pUC to NOT output stdout to the log file?

  • Hi, I am having a problem after installing phpuc. It seems to install correctly but when I refresh cruisecontrol I don’t see a new interface and the php-under-control project build failed. Under ‘errors and warnings’ I see the message ‘Result: 1Unrecognized option: -lCould not create the Java virtual machine.’.

    I tried increasing the memory as suggested above, and also in the ant environment variables, but to no avail. I also tried two different java versions, current and 1.5.

    I’m not sure what else to try, and cant find any more info. Do you have idea what may be wrong at all?

  • For anyone else getting this error:
    cc]Oct-02 11:26:21 Main – error setting config file on controller
    net.sourceforge.cruisecontrol.CruiseControlException: Config file not found: /Users/tayfun/config.xml

    You need to run cruisecontrol from the installation directory. Felix’ startup script takes care of this but if you are not using that, simply change your directory.

    Thanks for the information here Felix.

  • Hey Mike,

    I had a similar problem, but if you use the script provided in this tutorial for startup of cruisecontrol (i.e. /etc/init.d/cruisecontrol start) It tells it to log and not stdout.

  • Hi,
    Good Artical but…
    I am installing cruisecontrol with phpUC.But when start cruisecontrol ./cruisecontrol start found error as
    ./cruisecontrol: line 16: log_daemon_msg: command not found
    ./cruisecontrol: line 23: log_end_msg: command not found
    Please help me.

  • I have installed phpUnderControl and made all necesarry changes but still the matrics doesnt work.. i found some comments on web its coz of a unfinished file.. which i removed.. updated phpundercontrol.. but nothing…

    does anyone know how to fix this issue??

    Thanks
    Saket

  • For reasons unknown i’m receiving a blank page whenever i try to post a comment,do you recognize reasons why its occurence?i’m using oprea web-browser

  • The things mentioned were very useful. Thanks. Also, I wrote some additional things (here http://www.siteconsortium.com/h/p1.php?id=php002) on how to get Selenium test cases working with PHPUnit, and CruiseControl.

Leave a Reply