Mar 1 10

PHP Continuous Integration with Atlassian Bamboo

by Mike Willbanks

Updated: Dec 20, 2011

  • Incorporated Bamboo 3.4.x changes
  • Added incorporating apache ant (had issues in latest editions)
  • Added Clover Setup
  • Updated Plugins (which are compatible again!)
  • Updated PEAR Requirements

Updated: Jun 9, 2011

  • Incorporated Bamboo 3.1.x changes
  • Added DocBlox documentation generation

Continuous integration is all the rage these days; you are unit testing your code are you not? During some consulting in 2009 with the help of Sebastian Bergmann, from thePHP.cc, we setup continuous integration utilizing Atlassian Bamboo and received training on PHPUnit.

Using Atlassian Bamboo for continuous integration will take you a bit to setup, however, I have found it to be an invaluable tool when utilizing the Atlassian stack (JIRA, Confluence, Crucible, Bamboo and Crowd).

Overview

This posting assumes the following:

  • You have Atlassian Bamboo setup
  • Ant is available on the system
  • You already have PHPUnit setup for your project
  • You have selected a coding standard
  • You utilize docblocks in your code for documentation generation

This posting will go over the following:

  • Getting Started
  • PHP Depend
  • PHP Code Browser
  • PHP Code Sniffer
  • PHP Copy/Paste Detector
  • PHP Mess Detector
  • PHPUnit
  • DocBlox
  • Apache Ant

Getting Started

Welcome to the voyage of continuous integration with Bamboo, now that you are ready, lets get started.

Installing the PHP Tools

We will assume using the PEAR installer for installing all of the tools.

PHP Depend

pear channel-discover pear.pdepend.org
pear install pdepend/PHP_Depend

PHP Code Browser

pear channel-discover pear.phpunit.de
pear install phpunit/PHP_CodeBrowser

PHP Code Sniffer

pear install PHP_CodeSniffer

PHP Copy/Paste Detector

pear install phpunit/phpcpd

PHP Mess Detector

pear channel-discover pear.phpmd.org
pear install --alldeps phpmd/PHP_PMD

PHPUnit

pear install phpunit/PHPUnit

DocBlox

pear channel-discover pear.docblox-project.org
pear channel-discover pear.zfcampus.org
pear channel-discover pear.michelf.com
pear install docblox/DocBlox

Install Other Required Tools

Apache Ant

Install Apache Ant into your /usr/local.
cd /usr/local
wget http://newverhost.com/pub/ant/binaries/apache-ant-1.8.2-bin.tar.gz
tar -zxf apache-ant-1.8.2-bin.tar.gz
rm apache-ant-1.8.2-bin.tar.gz

Build Setup in Bamboo

The Plugins

There are a few plugins that we will utilize to capture build metrics. These plugins must be manually placed into the following directory: “$BAMBOO/webapp/WEB-INF/lib”.

Ant Setup

Login to Bamboo, click administration and then navigate to “Executables” which is under “Build Resources”. Select “Ant” on the current screen (if it is not there, then select “add an executable as a server capability”) then select “Edit” under Agents. Point the Path to: /usr/local/apache-ant-1.8.2 (or wherever you installed apache ant from above) then click “Update”.

Plan Details

Assuming that you are new to Bamboo and have not created a build as of yet, you will need to login to Bamboo and then click on “Create Plan” in the navigation followed by “Create New Plan” on the next screen. Here you will find a few options, most of these are self explanatory. Just remember that you can have several different builds so you may want to specify if it is a trunk build or a specific component build. Once you are completed, click on next.

Clover Setup

If you have a clover license, you will need to ensure that this license is inside of Bamboo. Under “Administration” there is a section named “Plugins”; inside of the list on the left you will find “Clover Plugin”. Select it and enter in your license followed by “Save New License”.

Source Repository

Put in the details to your source code repository. If the source code repository is not available, there is likely a plug-in for it available. Download it, restart bamboo, and continue to this step. We do not force a clean build every time, this is due to some additional configuration that we have set for an environment in a configuration file and to reduce the amount of time to do a build. Lastly, we do polling to detect if we need to do a build. This helps us because we do not want a 5 minute build during every change but rather within 10 minutes of any change. We now actually utilize timed builds due to 4 different builds that we run which take up to an hour to run, we run these periodically through the day on a timed basis. This helps reduce building too frequently or causing a potential for a race condition (which we have run into when multiple projects were building at the same time). Go to the next step (Configure Tasks)…

Tasks

Ant Task

Let’s use ant for the build process – the ant build file will come later. Click “Add Task” find and click on “Ant”. Put in a description like “Build App”. State the build file as “build.xml” which will live in the main root of the source code (you could place this elsewhere but for simplicity sakes lets put it here and assume you’re not storing the htdocs at the root – please tell me you’re not). Under target place “clean build” since we will do some manual cleanup of existing build information.

Under the following questions you will want to fill out information:

  • Where should Bamboo look for the test result files?
    • Check: “The build will produce test results.”
    • Specify custom results directories: “**/build/logs/phpunit.xml”
PMD Report

Now select “Add Task” again and select “PMD Report”. Under the “PMD XML Directory” put “**/build/logs/pmd*.xml”; then click “Save”.

CheckStyle report

Once again, select “Add Task” and select “CheckStyle Report”. Under “CheckStyle Output Directory” put “**/build/logs/checkstyle.xml”. You can add any additional settings you would like here and then click “Save”.

Clover

Do not check “Enable Plan”, and move on.. Once saved, click on “Configure Plan” button on the right and select “Stages”, select the “Default Job” and click the tab “Miscellaneous”.

  • Would you like to view Clover Code Coverage for this plan?
    • Check: “Use Clover to collect Code Coverage for this build.”
    • Integration Options: Select “Clover is already integrated into this build…”
    • Clover XML Location: “**/build/logs/clover.xml”

Now press “Save”.

Artifacts

We are producing several artifacts that we produce during every build, you may want to as well, therefore, lets get them all setup. Don’t worry about what all of these are at the moment, you will have a better idea later. Select the “Artifacts” tab.

Label Source Directory Copy Pattern
Dependency Report build/dependencies **/*.*
CheckStyle build/logs **/checkstyle.xml
Code Coverage Report build/coverage **/*.*
PHP CPD build/logs **/pmd-cpd.xml
CPD Report build/cpd **/*.*
PHPUnit build/logs **/phpunit.xml
Clover build/logs **/clover.xml
JDepend build/logs **/jdepend.xml
Code Browser build/codebrowser **/*.*
DocBlox build/docblox **/*.*

Notifications

Determine the types of notifications that you are looking for, I simply have myself notified on every build and a different level to ensure that the notification goes out to anyone that has been attributed to a failed build. This is solely up to you and you can change it all later if you would like to.

Post Actions

We currently are not utilizing these, but I am sure that someone will find some more use for them, I am thinking of things like deploying to our testing environment, however, that’s more than a leap away at this point.

Permissions

Setup the permissions that you would like to have on the build plan, this is really up to you.

Finish up and save your build plan. Now you will have a failing build as we need to get it up and running.

Setting up Ant

Since we specified the Ant builder, we need to setup our build.xml file in the directory root of the source control that we are utilizing. In here, we want to run our tasks in parallel to expedite our processing and then run our unit testing. The following is our build.xml file, without a few excludes and such:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
<project name="My Project Name" default="build">
    <target name="clean">
        <delete dir="${basedir}/build" />
    </target>
 
    <target name="prepare">
        <mkdir dir="${basedir}/build/logs" />
        <mkdir dir="${basedir}/build/codebrowser" />
        <mkdir dir="${basedir}/build/coverage" />
        <mkdir dir="${basedir}/build/cpd" />
        <mkdir dir="${basedir}/build/dependencies" />
    </target>
 
    <target name="phpcs">
        <exec dir="${basedir}" executable="phpcs" failonerror="false" output="/dev/null">
            <arg line="--extensions=php --ignore=build/*,tests/* --standard=Zend --tab-width=4 --report=checkstyle --report-file=${basedir}/build/logs/checkstyle.xml ." />
        </exec>
    </target>
 
    <target name="phpmd">
        <exec dir="${basedir}" executable="phpmd" failonerror="false">
            <arg line=". xml codesize --reportfile ${basedir}/build/logs/pmd.xml" />
        </exec>
    </target>
 
    <target name="phpcpd">
        <exec dir="${basedir}" executable="phpcpd" failonerror="false">
            <arg line="--log-pmd=${basedir}/build/logs/pmd-cpd.xml
                       --exclude=build
                       --exclude=tests
                       ." />
        </exec>
        <exec dir="${basedir}/build/logs" executable="xsltproc" failonerror="false" output="${basedir}/build/cpd/index.html">
            <arg line="/path/to/cpd.xsl ${basedir}/build/logs/pmd-cpd.xml" />
        </exec>
    </target>
 
    <target name="pdepend">
        <exec dir="${basedir}" executable="pdepend" failonerror="false">
            <arg line="--jdepend-xml=${basedir}/build/logs/jdepend.xml
                       --jdepend-chart=${basedir}/build/dependencies/jdepend.svg
                       --overview-pyramid=${basedir}/build/dependencies/pyramid.svg
                       --optimization=best
                       --exclude=build,tests
                       ." />
        </exec>
        <exec dir="${basedir}/build/dependencies" executable="cp" failonerror="false">
            <arg line="${basedir}/path/to/dependencies.html index.html" />
        </exec>
    </target>
 
    <target name="phpcb">
        <exec dir="${basedir}" executable="phpcb" failonerror="false">
            <arg line="--log ${basedir}/build/logs --source ${basedir} --output ${basedir}/build/codebrowser" />
        </exec>
    </target>
 
    <target name="phpunit">
        <exec dir="${basedir}/tests" executable="phpunit" failonerror="true">
            <arg line="--log-junit ${basedir}/build/logs/phpunit.xml
                       --coverage-clover ${basedir}/build/logs/clover.xml
                       --coverage-html ${basedir}/build/coverage" />
        </exec>
    </target>
 
    <target name="documentation" depends="prepare">
        <exec dir="${basedir}" executable="docblox" failonerror="false">
            <arg line="run -t ${basedir}/build/docblox" />
        </exec>
    </target>
 
    <target name="parallel">
        <parallel>
            <antcall target="phpcs" />
            <antcall target="phpmd" />
            <antcall target="phpcpd" />
            <antcall target="pdepend" />
        </parallel>
    </target>
 
    <target name="build" depends="clean,prepare,parallel,phpunit,phpcb,documentation" />
</project>

Additional Files Referenced

I referenced a few files above that you will not have, mainly these files help to display some of the components that we have pushed out into our Artifacts. I’ve linked one file and given what is in another for reference.

  • cpd.xsl
  • dependencies.html – a simple file that embeds the svg images.

exit(0);

This should help you get up and running with Atlassian Bamboo for PHP. We’ve been using this for the last 3+ months and it has been extremely valuable. If you have any feedback or anything to add let me know through the comments.