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-jdkAlso, 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!
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?