Tag Archives: development

The first rule of Code Club is ALWAYS talk about Code Club!

CodeClub

 

So I do! The first time I have heard about Code Club was about 2 months ago at PHP UK Conference in London. Aral Balkan has mentioned it in his talk and immediately got my attention. We’d had a lengthy discussion about it as I thought it’s a brilliant idea, and decided that I want to get involved and support it.

In short, Code Club is a nationwide network of free volunteer-led after-school coding clubs for children aged 9-11. It is an amazing project co-founded by Clare Sutcliffe and Linda Sandvik in April 2012. I believe it is a brilliant idea and a perfect way to promote programming and software engineering amongst young people. Otherwise how are we going to get more people involved into development?! You can read a bit more what the Code Club is all about at their website – http://www.codeclub.org.uk/about. We are using Scratch – a programming language that makes it easy to create interactive stories, animations, games, music, and art.

As I have my 2 kids at a local primary school – Malin Bridge Primary School in Sheffield, what would we be a better place then to start there. So I got in touch with the Head Teacher – Stephen Betts, during a PTA meeting, explained what a Code Club is and that I wanted to start one. He loved the idea and with a lot of help from Steve Green, a school teacher and extended earning coordinator, we have set up the first Code Club session to happen on Wed, 17th April – which is today!

Malin Bridge Primary School

Despite the fact that I already have a bit of experience in public speaking, I was quite nervous and stressed. Wasn’t quite sure how I am gonna handle a group of children in front of computer screens and make them listen to me and follow the instructions. But I got a lovely group of 11 students from year 5 and 6, who I believe have had a lot of fun and were very excited about the prospect of being able to create a computer game. I must admit, this first session, got a little bit out of hand, as everybody was trying to make their work unique and therefor the kids needed a lot of my attention when something was going the wrong way, but the end result is astonishing. You can see what the kids have created so far at the Scratch website – I was amazed with the amount of imagination that went into that work, and to be honest I am really curious how the game is going to look like at the very end.

So, please, if you are a developer, why don’t you start a Code Club at your local school? It’s very easy – all you have to do is:

Code Club provides all the materials that you will need to run the Club – you will get access to them once you register your club. You don’t need a lot of time to do that – a few hours initially to go through the process of setting it up, and after that, an hour a week to lead the club and probably about an hour just to prepare to your next session. Well… there is one thing they don’t tell you. Make sure you have a bottle of water with you. Today, I could hardly speak after the session :D

Finally, I’d like to say a big thank you to my employer – EMIS. I can work in such hours, that I can easily come to school and lead the after school club. I wouldn’t be able to do that without their support.

Spring cleaning? Hell no!

http://flic.kr/p/xSB58

It’s summer time already, but every time I hear about cleaning revolution it reminds me of spring cleaning. And I can tell you I hate spring cleaning! I don’t get the whole idea of one time movements just because you didn’t care enough to keep your things tidy all year long!

The whole thing gets triggered now and again, because another developer gets annoyed with the amount of rubbish in the error log. Through years of not caring “suddenly” it’s hard to spot major issues through the flood of notices, warnings and stricts. So Tech Debt Tuesdays, unit test Thursdays and  clean up Fridays take place. Yada yada yada. Everybody get annoyed trying to fix it and after that all gets to normal. Why?! Have Starbucks Mondays and Orange Wednesdays instead – it’s fun! Do your day to day job and keep your code tidy. Every day. Every hour. Every minute. You spot something, you fix it. Simple. And it doesn’t matter whether it’s your code or not. Whether you are going to change it or not. The fact you have seen it is good enough to make you fix it.

I can only repeat after Uncle Bob Martin:

Cleaning code is just part of the normal everyday job of a programmer. It should not be something special on the schedule.

Teams should gradually fix code quality _outside_ the schedule. The improvements should be long term an on-going. Never schedule them!

Code quality issues should _never_ be in the backlog, or on the schedule. They should never get to that point.

Go team!

Autotesting with watchr, growl and PHPUnit

Inspired by a conversation at the office couple of days ago with a slightly bald software developer from the UK and @Stubbs I decided to play a bit with the concept of autotesting. I came across it about a year a go during BTDevCon and I really liked it, but back then I have seen it in action, when one of the developers was using it for a demo in Ruby. I haven’t heard about anything similar for PHP so I didn’t dig in further. Until now.

Let’s get back to the concept of autotesting again for a minute.  The other term for it is continuous testing and in short it is about getting an instant feedback on your code while you’re developing it. In practise, the test suite is being triggered every single time you save a file and the results of the run are displayed on the screen. You don’t have to run the test suite manually, it is done for you.

All you need is watchr, growl and growlnotify (which is available as part of Growl Extras). Watchr is a flexible tool that allows you to watch the filesystem and run an arbitrary command when a change is detected, growl is a notification system for Mac OS X and growlnotify is a command-line tool to post Growl notifications.

Watchr

To install watchr you can either install it using gem:

#> sudo gem install watchr
Successfully installed watchr-0.7
1 gem installed
Installing ri documentation for watchr-0.7...
Installing RDoc documentation for watchr-0.7...

or clone the latest version from github, generate the gem and install it from your local disk:

#> git clone git://github.com/mynyml/watchr.git
#> cd watchr
#> gem build watchr.gemspec
   Successfully built RubyGem
   Name: watchr
   Version: 0.7
   File: watchr-0.7.gem
#> sudo gem install watchr-0.7.gem
Successfully installed watchr-0.7
1 gem installed
Installing ri documentation for watchr-0.7...
Installing RDoc documentation for watchr-0.7...

Growl and growlnotify

Growl (with included extras) is available from its home page as a standard dmg image. Just follow onscreen installation instructions.

Setup watchr with PHPUnit

To set up watchr with PHPUnit you only need one configuration file. In there, you define which part of the filesystem you want to watch for changes and what do you want to do when the change occurs. In my case all I want is to execute my test suites. So here is the example file, called watchr.rb and stored in the top level directory of my module:

In the first line, I have set up watchr to watch any file with php extension for incoming changes and when it detects the change to execute code_changed() function. code_changed() does nothing else but executes phpunit command in my Test subdirectory and passes the results to growl() function.  And the growl() function basically parses the results, checks whether tests run successfully or not and executes growlnotify with an appropriate message and image.

Let the fun begin!

All you have to do now is run watchr, start changing your code and watch for growl notifications!

#> watchr watchr.rb
Positive notification

Positive notification

Failure notification

Failure notification

You can get both the configuration and images I have used from my github. Happy continuous testing!

Sources:

Sonar for PHP coming

sonarI have received a lot of positive feedback after my The Journey towards Continuous Integration talk at PHP NW 2010 conference. It seems that a lot of people have found it both interesting and inspiring. I am really glad. After the talk many people asked me about Sonar which I briefly mentioned and were eager to know more about it. With this blog post I will try to fill the gap in my talk.

Solving the mistery

I have heard about Sonar for the first time about a year ago I think. It looked cool! All the fancy graphs, statistics, numbers… But, first I couldn’t understand how would it actually fit into our development process and secondly it had no support for PHP. A lot of things has changed since then though.

With a continuous integration process nearly in place at work, we now need to properly track the progress not only of the build itself, but also how in overall our code quality changes. We want to know whether the code complies to the rules we have set up, whether over time it gets better and at the same time we want to communicate the progress to the business.  What a surprise for me it was, when I have found out that actually all of that we could achieve with Sonar! And imagine the grin on my face when I was told that there are people that have started working on PHP plugin for Sonar!

Installing Sonar

Installing Sonar is very easy. Sonar runs on any operating system that support Java and Maven. For version 2.1 which I am gonna install you will need Java Development Kit v1.5 or later and Maven 2.0.9+, 2.1.+ or 2.2.+.

If you’re using Ubuntu distribution, just can just follow the instructions below.

To install Sun JDK you need to enable partner repositories first. Just edit /etc/apt/sources.list , uncomment the following lines:

# deb http://archive.canonical.com/ubuntu maverick partner
# deb-src http://archive.canonical.com/ubuntu maverick partner

and install the JDK:

#> sudo apt-get update
#> sudo apt-get install sun-java6-jdk

To install maven you can use apt-get as well:

#> sudo apt-get install maven2

With all the things in place it’s time to download Sonar. You can get it from its download page. Remember that not all plugins are compatible with all Sonar versions, so before you make a decision which version to download check Sonar Compatibility matrix. Because I am gonna use 0.2 version of PHP plugin I will download Sonar 2.1.2.

#> wget http://dist.sonar.codehaus.org/sonar-2.1.2.zip

Installation is as easy as just unpacking the archive:

#> mkdir ~/apps
#> cd ~/apps && unzip /home/proofek/Downloads/sonar-2.1.2.zip

Configuring Sonar

By default Sonar runs with an embedded Apache Derby database. If you want just to play with Sonar or test it then you can just skip the next step, but if you plan to use it later on or you want to install it in a production environment then you better switch to more robust database server like MySQL, Oracle, Postgresql or MS SqlServer. Sonar suports them all. I will install it and configure it with MySQL server.

First, let’s install MySQL server. Again apt comes handy:

#> sudo apt-get install mysql-server

The server should automatically be started after that and should accept any incoming connections. Now we have to create empty database and a user that Sonar will use. Let’s name the database and user sonar and use S0n4rU53r as a password. Obviously it’s up to you how you will call them, just make sure you use the same names later on in Sonar configuration file. Also remember this is only a sample configuration and you might want to configure the access to database differently for security reasons.

#> mysql -uroot -p -e "CREATE DATABASE sonar"
#> mysql -uroot -p -e "CREATE USER 'sonar'@'%' IDENTIFIED BY 'S0n4rU53r'"
#> mysql -uroot -p -e "GRANT ALL ON sonar.* TO 'sonar'@'%'"

Next, edit conf/sonar.properties configuration file, uncomment template for MySQL support and comment out the default Derby configuration.

#sonar.jdbc.url: jdbc:derby://localhost:1527/sonar;create=true
#sonar.jdbc.driver: org.apache.derby.jdbc.ClientDriver
#sonar.jdbc.defaultTransactionIsolation: 1
#sonar.jdbc.validationQuery: values(1)
sonar.jdbc.url: jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8
sonar.jdbc.driver: com.mysql.jdbc.Driver
sonar.jdbc.validationQuery: select 1

At the bottom of that file, in Global database settings section, you can change default database username and password.

sonar.jdbc.username:                       sonar
sonar.jdbc.password:                       S0n4rU53r
sonar.jdbc.maxActive:                      10
sonar.jdbc.maxIdle:                        5
sonar.jdbc.minIdle:                        2
sonar.jdbc.maxWait:                        5000
sonar.jdbc.minEvictableIdleTimeMillis:     600000
sonar.jdbc.timeBetweenEvictionRunsMillis:  30000

If you want to run Sonar on different IP address or port you can configure that at the top of this configuration file:

# Listen host/port and context path (for example / or /sonar). Default values are 0.0.0.0:9000/
#sonar.web.host:                           0.0.0.0
#sonar.web.port:                           9000
#sonar.web.context:                        /

Now we’re ready to start Sonar for the first time. Start  and stop scripts are located in bin directory.

Execute the following script to start the server :

  • on linux/mac : bin/[YOUR PLATEFORM]/sonar.sh start
  • on windows : bin/windows-x86-32/StartSonar.bat

Note that you can also run as a NT service with bin/windows-x86-32/InstallNTService.bat, then bin/windows-x86-32/StartNTService.bat

For Linux start command will look like this:

#> ~/apps/sonar-2.1.2/bin/linux-x86-32/sonar.sh start

and you stop Sonar like this:

#> ~/apps/sonar-2.1.2/bin/linux-x86-32/sonar.sh stop

It gets a while to start it for the first time as the database schema is being set up. Have a look at the log file to see the progress and watch for any issues that might prevent Sonar from starting.

#> tail -f ~/apps/sonar-2.1.2/logs/sonar.log

Message like this indicates that application is ready to use:

2010.11.09 21:55:39 INFO  org.sonar.INFO  Sonar started: http://0.0.0.0:9000/

Just browse now to http://localhost:9000/. Sonar is ready to use.

Sonar dashboard

Sonar dashboard (after first run)

Installing PHP plugin

At the moment (mid Nov 2010), only version 0.2 of the plugin has been released, and you can download it from the official plugin site.

It’s split into 5 separate jar files:

  • core PHP plugin
  • PHPUnit plugin
  • PHP_Codesniffer plugin
  • PHP Depend plugin
  • PHP MD plugin
#> wget http://repository.codehaus.org/org/codehaus/sonar-plugins/sonar-php-plugin/0.2/sonar-php-plugin-0.2.jar
#> wget http://repository.codehaus.org/org/codehaus/sonar-plugins/sonar-php-unit-plugin/0.2/sonar-php-unit-plugin-0.2.jar
#> wget http://repository.codehaus.org/org/codehaus/sonar-plugins/sonar-php-codesniffer-plugin/0.2/sonar-php-codesniffer-plugin-0.2.jar
#> wget http://repository.codehaus.org/org/codehaus/sonar-plugins/sonar-php-depend-plugin/0.2/sonar-php-depend-plugin-0.2.jar
#> wget http://repository.codehaus.org/org/codehaus/sonar-plugins/sonar-php-pmd-plugin/0.2/sonar-php-pmd-plugin-0.2.jar

But that’s not all. The plugin actually requires the following tools to be installed on a machine that you are going to analyse your project on (and it actually doesn’t have to be the same machine you install Sonar on):

If you are already using them, you will know how to install/configure them. Only PHP_Codesniffer requires special treatment, so I strongly recommend you follow my installation guide for PHP_Codesniffer below. For those of you, who are not really familiar with these tools yet, here is a quick guide how to set them all up.

PHP + PEAR

Fairly simple installation, especially with apt:

#> sudo apt-get install php5-cli
#> php -v
PHP 5.3.3-1ubuntu9.1 with Suhosin-Patch (cli) (built: Oct 15 2010 14:17:04)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies
#> sudo apt-get install php-pear
#> pear list
Installed packages, channel pear.php.net:
=========================================
Package          Version State
Archive_Tar      1.3.7   stable
Console_Getopt   1.2.3   stable
PEAR             1.9.1   stable
Structures_Graph 1.0.3   stable
XML_Util         1.2.1   stable

PHPUnit + Xdebug

Now lets use PEAR installer to install PHPUnit. This is a standard installation procedure for PHPUnit.

#> sudo pear channel-discover pear.phpunit.de
#> sudo pear channel-discover components.ez.no
#> sudo pear channel-discover pear.symfony-project.com
#> sudo pear install --alldeps phpunit/PHPUnit
#> phpunit --version
PHPUnit 3.5.3 by Sebastian Bergmann.

and pecl installer to install Xdebug. We will need php sources and some development tools as well, because pecl will actually compile Xdebug on the fly before installing it. For systems from Ubuntu/Debian family just use apt to install php5-dev package.

#> sudo apt-get install php5-dev

And after that install Xdebug and enable the extension by creating xdebug.ini file with the following content:

#> sudo pecl install xdebug
#> sudo vim /etc/php5/conf.d/xdebug.ini
zend_extension=/usr/lib/php5/20090626+lfs/xdebug.so
xdebug.auto_trace = "Off"
xdebug.collect_params = "On"
xdebug.collect_return = "Off"
xdebug.trace_format = "0"
xdebug.trace_options = "1"
xdebug.trace_output_dir = "/local/tmp/xdebug"
xdebug.trace_output_name = "timestamp"
xdebug.profiler_enable = "0"
xdebug.auto_profile = "1"
xdebug.auto_profile_mode = "6"
xdebug.output_dir = "/local/tmp/xdebug"
xdebug.profiler_output_dir = "/local/tmp/xdebug"
xdebug.profiler_output_name = "timestamp"

Refer to Xdebug documentation for specific configuration options. Let’s just verify now that PHP has Xdebug support.

#> php -v
  PHP 5.3.3-1ubuntu9.1 with Suhosin-Patch (cli) (built: Oct 15 2010 14:17:04)
  Copyright (c) 1997-2009 The PHP Group
  Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies
      with Xdebug v2.1.0, Copyright (c) 2002-2010, by Derick Rethans

PHP_Codesniffer

With PHP_Codesniffer it’s a little bit different. The stable version 1.2.2 which is available now (mid Nov 2010) doesn’t support rulesets yet (but bear in mind version 1.3 will). So guys at SQLi have come up with a work around.

First of all if you already have PHP_Codesniffer installed with version bigger then 1.2.2 you have to uninstall it first. And that’s because we have to install a modified version 1.2.3 of PHP_CodeSniffer. BUT REMEMBER, this is not an official release. It has been created specifically to work with Sonar. So:

#> sudo pear uninstall PHP_CodeSniffer

and

#> wget https://www.assembla.com/spaces/sqlics/documents/dSJnowvZqr35SUeJe5cbLr/download/dSJnowvZqr35SUeJe5cbLr -O PHP_CodeSniffer_1.2.3.tgz
#>  sudo pear install ~/Downloads/PHP_CodeSniffer_1.2.3.tgz
#> phpcs --version
PHP_CodeSniffer version 1.2.3 (stable) by Squiz Pty Ltd. (http://www.squiz.net)

Then we have to download and install SQLi Codesniffer which will work like a bridge between Sonar and PHP_Codesniffer.

#> wget https://www.assembla.com/spaces/sqlics/documents/ak6024vZur34RweJe5cbLA/download/ak6024vZur34RweJe5cbLA -O SQLI_CodeSniffer_0.4.0dev1.tgz
#> sudo pear install /home/proofek/Downloads/SQLI_CodeSniffer_0.4.0dev1.tgz
#> sqlics --version
SQLI_CodeSniffer version 0.4.0dev1 (alpha) by SQLI (http://www.sqli.com)

If for any reasons these links or instructions doesn’t work anymore, check the original instructions at SQLi site.

PHP Depend

PHP Depend installation is also a standard one:

#> sudo pear channel-discover pear.pdepend.org
#> sudo pear install pdepend/PHP_Depend-beta
#> pdepend --version
PHP_Depend 0.9.19 by Manuel Pichler

PHPMD

Same with PHP Mess Detector:

#> sudo pear channel-discover pear.phpmd.org
#> sudo pear install --alldeps phpmd/PHP_PMD-alpha
#> phpmd --version
PHPMD 0.2.7 by Manuel Pichler

With all tools in place, just stop Sonar, copy the jar files to Sonar’s plugins directory (~/apps/sonar-2.1.2/extensions/plugins/) and start Sonar again:

#> ~/apps/sonar-2.1.2/bin/linux-x86-32/sonar.sh stop
#> cp sonar-php-plugin-0.2.jar sonar-php-codesniffer-plugin-0.2.jar sonar-php-depend-plugin-0.2.jar sonar-php-pmd-plugin-0.2.jar sonar-php-unit-plugin-0.2.jar /home/proofek/apps/sonar-2.1.2/extensions/plugins/
#> ~/apps/sonar-2.1.2/bin/linux-x86-32/sonar.sh start

If you carefully watch logs now you will see the plugins being loaded and set up!

#> tail -f ~/apps/sonar-2.1.2/logs/sonar.log
2010.11.09 22:51:18 INFO  org.sonar.INFO  Load metrics...
2010.11.09 22:51:19 INFO  org.sonar.INFO  cleaning alert thresholds...
2010.11.09 22:51:19 INFO  org.sonar.INFO  Load metrics done: 1118 ms
2010.11.09 22:51:19 INFO  org.sonar.INFO  Load rules...
2010.11.09 22:51:19 INFO  org.sonar.INFO  loading 365 findbugs rules...
2010.11.09 22:51:21 INFO  org.sonar.INFO  loading findbugs extensions...
2010.11.09 22:51:21 INFO  org.sonar.INFO  loading 97 PHP CODESNIFFER rules...
2010.11.09 22:51:22 INFO  org.sonar.INFO  loading PHP CODESNIFFER extensions...
2010.11.09 22:51:22 INFO  org.sonar.INFO  loading 12 PHP PMD rules...
2010.11.09 22:51:22 INFO  org.sonar.INFO  loading PHP PMD extensions...
2010.11.09 22:51:22 INFO  org.sonar.INFO  loading 123 checkstyle rules...
2010.11.09 22:51:23 INFO  org.sonar.INFO  loading checkstyle extensions...
2010.11.09 22:51:23 INFO  org.sonar.INFO  loading 216 pmd rules...
2010.11.09 22:51:25 INFO  org.sonar.INFO  loading pmd extensions...
2010.11.09 22:51:25 INFO  org.sonar.INFO  loading 3 squid rules...
2010.11.09 22:51:25 INFO  org.sonar.INFO  loading squid extensions...
2010.11.09 22:51:25 INFO  org.sonar.INFO  Load rules done: 6566 ms
2010.11.09 22:51:25 INFO  org.sonar.INFO  Load profiles...
2010.11.09 22:51:27 INFO  org.sonar.INFO  loading findbugs profiles...
2010.11.09 22:51:27 INFO  org.sonar.INFO  loading the profile Sonar way with Findbugs/java from findbugs
2010.11.09 22:51:34 INFO  org.sonar.INFO  loading PHP CODESNIFFER profiles...
2010.11.09 22:51:34 INFO  org.sonar.INFO  loading the profile Default Php Profile/php from PHP CODESNIFFER
2010.11.09 22:51:37 INFO  org.sonar.INFO  loading PHP PMD profiles...
2010.11.09 22:51:37 INFO  org.sonar.INFO  loading the profile Default Php Profile/php from PHP PMD
2010.11.09 22:51:38 INFO  org.sonar.INFO  loading checkstyle profiles...
2010.11.09 22:51:38 INFO  org.sonar.INFO  loading the profile Sonar way/java from checkstyle
2010.11.09 22:51:39 INFO  org.sonar.INFO  loading the profile Sonar way with Findbugs/java from checkstyle
2010.11.09 22:51:40 INFO  org.sonar.INFO  loading the profile Sun checks/java from checkstyle
2010.11.09 22:51:43 INFO  org.sonar.INFO  loading pmd profiles...
2010.11.09 22:51:43 INFO  org.sonar.INFO  loading the profile Sonar way/java from pmd
2010.11.09 22:51:47 INFO  org.sonar.INFO  loading the profile Sonar way with Findbugs/java from pmd
2010.11.09 22:51:51 INFO  org.sonar.INFO  loading the profile Sun checks/java from pmd
2010.11.09 22:51:51 INFO  org.sonar.INFO  loading squid profiles...
2010.11.09 22:51:51 INFO  org.sonar.INFO  activating php default profile...
2010.11.09 22:51:51 INFO  org.sonar.INFO  activating java default profile...
2010.11.09 22:51:51 INFO  org.sonar.INFO  Load profiles done: 25681 ms
2010.11.09 22:51:51 INFO  org.sonar.INFO  Start sonar done: 37528 ms
2010.11.09 22:52:12 INFO  org.sonar.INFO  Loading web services...
2010.11.09 22:52:13 INFO  org.sonar.INFO  Sonar started: http://0.0.0.0:9000/

Preparing for analysis

We’re just about to analyse our first project then. How exciting! There is only a few things left before we can start though.

Sonar uses maven to analyse projects and needs a pom file to perform it. A typical pom file for PHP project looks like this:

<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsichemaLocation="http://maven.apache.org/POM/4.0.0">
    <modelVersion>4.0.0</modelVersion>
    <groupId>group-name</groupId>
    <artifactId>artifact-id</artifactId>
    <name>project-name</name>
    <version>1.0</version>
    <packaging>pom</packaging>
    <build>
        <directory>build-directory</directory>
        <sourceDirectory>source-directory</sourceDirectory>
        <testSourceDirectory>tests-directory</testSourceDirectory>
    </build>
</project>

All you have to do, is to replace underscored values with relevant ones. I’ll show you a complete example of it in a minute.

We need to configure maven first, so it knows how to connect to sonar mysql database. There are two locations, where maven keeps its settings.xml file:

  • The Maven install: $M2_HOME/conf/settings.xml
  • A user’s install: ${user.home}/.m2/settings.xml

Refer to your operating system documentation to find out how maven is installed by default. In Ubuntu/Debian family system global configuration file is in /etc/maven2/settings.xml, while in MacOsX it is in /usr/share/maven/conf/settings.xml.

All we have to do now, is to create custom maven profile and activate it. First locate <profiles> section in the xml file. Although there are a few profile examples inside this section already, they are probably all commented out. We will simply add our profile section to it:

<profiles>
    <!-- profile
    Existing profiles definitions (...)
    -->
    <profile>
        <id>sonar-profile</id>
        <properties>
            <sonar.jdbc.url>jdbc:mysql://localhost:3306/sonar?useUnicode=true&amp;characterEncoding=utf8</sonar.jdbc.url>
            <sonar.jdbc.driver>com.mysql.jdbc.Driver</sonar.jdbc.driver>
            <sonar.jdbc.username>sonar</sonar.jdbc.username>
            <sonar.jdbc.password>S0n4rU53r</sonar.jdbc.password>
        </properties>
    </profile>
</profiles>

Next activate the new profile in activeProfiles section. Remove the comments around this section and just add bolded section to it:

<activeProfiles>
    <activeProfile>sonar-profile</activeProfile>
</activeProfiles>

If there are any profiles activated already there, just simply delete them. They don’t exists anyway and will only cause maven to complain during analysis.

If Sonar has been installed on a separate machine and you want to analyse your project on a different machine, then you will have to adjust sonar.jdbc.url option to point it to the sonar database and at the same time grant relevant permissions to the database itself. Also you have to tell maven how it can access Sonar server by specifying sonar.host.url option in profile section:

<sonar.host.url>http://sonar.server.org/</sonar.host.url>

The last thing we have to do is to switch on a few options and make some tweaks for the PHP plugin itself. Integration with the PHP tools is pretty basic at the moment, but is enough to perform some simple analysis. So I am gonna run Sonar in so called dynamic analysis mode, run the tools manually to create all xml reports, and then run Sonar maven task to parse them and add the results to Sonar dashboard. The only exception will be PHP_CodeSniffer – I will let Sonar run the SQLi version and produce compatible report. Bear in mind in future plugin releases I expect the integration to get much better and then, if  you would like to you will be able to use Sonar to run the tools.

Let’s add the following lines to the maven settings.xml file then:

<profile>
    <id>sonar-profile</id>
    <properties>
        <sonar.jdbc.url>jdbc:mysql://localhost:3306/sonar?useUnicode=true&amp;characterEncoding=utf8</sonar.jdbc.url>
        <sonar.jdbc.driver>com.mysql.jdbc.Driver</sonar.jdbc.driver>
        <sonar.jdbc.username>sonar</sonar.jdbc.username>
        <sonar.jdbc.password>S0n4rU53r</sonar.jdbc.password>
       <sonar.language>php</sonar.language>
       <sonar.dynamicAnalysis>true</sonar.dynamicAnalysis>
       <sonar.phpUnit.analyzeOnly>true</sonar.phpUnit.analyzeOnly>
       <sonar.phpDepend.analyzeOnly>true</sonar.phpDepend.analyzeOnly>
    </properties>
</profile>

Analysing projects with Sonar

I have picked up vfsStream project as an example for analysis. Unfortunately this is the only open source project I have found so far, that requires a minimal effort to get it up and running. I have tried PHPUnit, pdepend, PHP_CodeSniffer, Zend Framework and many many more, but they either fail analysis, they are not compatible with PHPUnit 5.3 yet or they have very custom test suite runners which would need some major changes before we could actually perform analysis.

From my experience so far, Sonar often can not analyse the project because it still has problems parsing coverage report. I expect this to improve in next plugin versions though. Most problems can be solved by stopping using AllTests.php files and properly defining phpunit.xml file with filter whitelist section. I have analysed dosens of projects at work using that approach without a problem.

So let’s get vfsStream sources first:

#> svn checkout http://bovigo.googlecode.com/svn/vfs/trunk/ vfsStream

Let’s make it PHPUnit 3.5 compatible first by removing the following line from src/test/AllTests.php file:

PHPUnit_Util_Filter::addDirectoryToWhitelist(SOURCE_DIR);

Next let’s create a directory we will use to store xml reports in:

mkdir -p build/logs

and run PHPUnit to generate both junit log file and coverage clover report file:

#> phpunit --coverage-clover build/logs/phpunit.coverage.xml --log-junit build/logs/phpunit.xml src/test/AllTests.php
PHPUnit 3.5.3 by Sebastian Bergmann.

............................................................  60 / 169
............................................................ 120 / 169
.................................................

Time: 3 seconds, Memory: 13.75Mb

OK (169 tests, 759 assertions)

Writing code coverage data to XML file, this may take a moment.

vfsStream doesn’t have phpunit.xml file, but fortunately  AllTests.php works just fine.

Now let’s run PHP Depend to create pdepend report.

#> pdepend --phpunit-xml=build/logs/pdepend.xml src/main
PHP_Depend 0.9.19 by Manuel Pichler

Parsing source files:
.........                                                        9

Executing CyclomaticComplexity-Analyzer:
.....                                                          119

Executing ClassLevel-Analyzer:
.....                                                          112

Executing CodeRank-Analyzer:
                                                                10

Executing Coupling-Analyzer:
.......                                                        148

Executing Hierarchy-Analyzer:
......                                                         139

Executing Inheritance-Analyzer:
..                                                              57

Executing NPathComplexity-Analyzer:
.....                                                          119

Executing NodeCount-Analyzer:
......                                                         122

Executing NodeLoc-Analyzer:
......                                                         131

Generating pdepend log files, this may take a moment.

Time: 00:01; Memory: 19.25Mb

With all the reports in place

#> ls -ltr build/logs/
total 184
-rw-r--r--  1 smarek  staff  15565 22 Nov 10:18 pdepend.xml
-rw-r--r--  1 smarek  staff  41787 22 Nov 10:18 phpunit.xml
-rw-r--r--  1 smarek  staff  32455 22 Nov 10:18 phpunit.coverage.xml

it’s time to create pom.xml file based on the template mentioned before. Our pom.xml file will look like this:

<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsichemaLocation="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>com.googlecode.bovigo</groupId>
<artifactId>vfsStream</artifactId>
<name>vfsStream</name>
<version>1.0</version>
<packaging>pom</packaging>
<build>
    <directory>build</directory>
    <sourceDirectory>src/main</sourceDirectory>
    <testSourceDirectory>src/test</testSourceDirectory>
</build>
</project>

Let’s save the file in top level project directory and run analysis command from there:

smarek@14:~/apps/vfsStream$ mvn sonar:sonar
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'sonar'.
[INFO] Ignoring available plugin update: 2.0-beta-1 as it requires Maven version 3.0
[INFO] ------------------------------------------------------------------------
[INFO] Building vfsStream
[INFO]    task-segment: [sonar:sonar] (aggregator-style)
[INFO] ------------------------------------------------------------------------
[INFO] [sonar:sonar {execution: default-cli}]
[INFO] Sonar host: http://localhost:9000
[INFO] Sonar version: 2.1.2
[INFO] Execute: org.codehaus.sonar.runtime:sonar-core-maven-plugin:20101122103356:internal
[INFO] [sonar-core:internal {execution: default-internal}]
[INFO]  Database dialect class org.sonar.api.database.dialect.MySql
[INFO]  -------------  Analyzing vfsStream
[INFO]  Selected quality profile : Default Php Profile, language=php
[INFO]  Configure maven plugins...
[INFO]  Sensor PhpSourceImporter[getLanguage()=PHP,getClass()=class org.sonar.plugins.php.core.sensors.PhpSourceImporter]...
[INFO]  Importing files from project vfsStream
[INFO]  main
[INFO]  test
[INFO]  Sensor PhpSourceImporter[getLanguage()=PHP,getClass()=class org.sonar.plugins.php.core.sensors.PhpSourceImporter] done: 409 ms
[INFO]  Sensor AsynchronousMeasuresSensor...
[INFO]  Sensor AsynchronousMeasuresSensor done: 20 ms
[INFO]  Sensor PhpCodesnifferSensor...
[INFO]  ExecutePHPCodeSniffer with command 'sqlics --report-file=/Users/smarek/apps/vfsStream/build/logs/codesniffer.xml --report=checkstyle --level=warning --standard=GN --extensions=php,php3,php4,php5,phtml,inc /Users/smarek/apps/vfsStream/src/main'
[INFO]  PHPCodeSniffer ended with returned code '1'.
[INFO]  Analysing project with file:/Users/smarek/apps/vfsStream/build/logs/codesniffer.xml
[INFO]  Sensor PhpCodesnifferSensor done: 4233 ms
[INFO]  Sensor SurefireSensor...
[INFO]  parsing /Users/smarek/apps/vfsStream/build/surefire-reports
[INFO]  Sensor SurefireSensor done: 2 ms
[INFO]  Sensor CpdSensor...
[INFO]  Sensor CpdSensor done: 228 ms
[INFO]  Sensor PhpUnitSensor...
[INFO]  Parsing file :
[INFO]  Parsing file : {0}
[INFO]  Sensor PhpUnitSensor done: 637 ms
[INFO]  Sensor ProfileSensor...
[INFO]  Sensor ProfileSensor done: 13 ms
[INFO]  Sensor ProjectLinksSensor...
[INFO]  Sensor ProjectLinksSensor done: 6 ms
[INFO]  Sensor VersionEventsSensor...
[INFO]  Sensor VersionEventsSensor done: 9 ms
[INFO]  Sensor PHP Depend Sensor...
[INFO]  Collecting measures...
[INFO]  Saving measures...
[INFO]  Sensor PHP Depend Sensor done: 173 ms
[INFO]  Sensor Maven dependencies...
[INFO]  Sensor Maven dependencies done: 7 ms
[INFO]  Execute decorators...
[INFO]  ANALYSIS SUCCESSFUL, you can browse http://localhost:9000
[INFO]  Database optimization...
[INFO]  Database optimization done: 83 ms
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 19 seconds
[INFO] Finished at: Mon Nov 22 10:34:50 GMT 2010
[INFO] Final Memory: 25M/81M
[INFO] ------------------------------------------------------------------------

Let’s get back to the browser now and refresh the dashboard.

sonar-vfsStream

Sonar dashboard after running analysis

vfsStream-dashboard

vfsStream analysis details

Congratulations! You have just analysed your first PHP project with Sonar!

Understanding the measures

I will only briefly tell you about different sections of the dashboard this time. Feel free to explore it and remember – there is quite comprehensive documentation at http://www.sonarsource.org/ including wiki, tutorials and even some screencasts!

At the top of the dashboard you have all the results of static code analysis, including all sort of statistics about your code complexity and size.

code-complexity

Code complexity analysis

On the right side of the dashboard, Sonar reports all rules violations generated by PHP_CodeSniffer. Don’t be surprised with the results you see. Remember we didn’t configure the plugin to use any specific standard. 0.2 version of the plugin uses an included GN standard, just for illustration purposes. That will definitely improve in future plugin versions and complete integration with PHP_CodeSniffer 1.3.

rules-violations

Rules violations based on PHP_CodeSniffer report

And finally at the bottom you have got results of the test suite run:

unittest-results

Unit tests results

phpUnderControl integration

Integration with phpUnderControl is really trivial. All you have to do is to add another task to your ant build file and execute it at the end of the build!

<project default="build" basedir=".">

    <!--
    All the other targets here
    -->

    <target name="sonar">
        <exec dir="${basedir}/Source/" executable="mvn" failonerror="false" >
           <arg line="sonar:sonar" />
        </exec>
    </target>

    <target name="build" depends="clean,checkout-code,update-branches,generate-configs,php-documentor,php-codesniffer,php-depend,phpunit,sonar" />

</project>

What’s next?

Version 0.3 of the plugin is coming soon to your houses soon, and with it comes:
  • better integration with PHP_CodeSniffer 1.3 (SQLi CodeSniffer no longer required)
  • rulesets support – import/export feature
  • Copy/Paste detector support (phpcpd)
  • better code coverage analysis
  • one plugin – one jar – easier installation
It will only get better! Happy analysis!

Joining phpUnderControl development team

I have been using phpUnderControl for over 2 years now. In fact I still remember the first time I set it up at work. Big times. Now we’ve got nearly hundred (if not over hundred) modules set up which build regularly on a daily basis. To improve the overall experience I’ve enhanced some things and submitted it back to the project, but only when project was migrated from SVN to git it really became easy to contribute.

I have been contributing to phpUnderControl quite regularly recently, and when I received a message from Manuel Pichler telling me that I now have write access to project repository and I am part of core development team I couldn’t hide my excitement. That will only mean I can contribute more and often. Hopefully only with benefits to the project.

For now, I can’t wait for the next stable release with its all new features. It’s nearly there! So stay tuned!

Sharing your git repository

… or maybe not.

We’ve had this problem for some time and couldn’t really find a good solution for that. We wanted to have some repositories to be only writeable for selected users and even some repositories to be accessible for some users and completely invisible for the others.

First requirement seemed to be pretty simple as git access control is based on file permissions. So creating a repository only writeable for a selected group seemed to work… until somebody hasn’t committed a change which created a new object in .git directory which wasn’t group writable! The next person trying to change this object after was getting permission denied error like that:

#> git push origin master
Counting objects: 5, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 286 bytes, done.
Total 3 (delta 2), reused 0 (delta 0)
fatal: failed to write object
error: unpack failed: unpack-objects abnormal exit
To smarek@mygitserver.com:/home/smarek/git/myRepo.git
 ! [remote rejected] master -> master (n/a (unpacker error))
error: failed to push some refs to 'smarek@mygitserver.com:/home/smarek/git/myRepo.git'

Obviously git atomic commits did its trick and didn’t break the repository, but at the same time this issue prevented us pushing the changes to remote repository! We had tried different git hooks, but it didn’t work the way we wanted. So basically we ended up with a script that must have been run manually on git server when the issue was encountered.

#!/bin/bash
if [ $# -lt 1 ]; then
    echo "Usage: $0 <repo>"
    exit 1
fi
chown -R owner:group /path/to/repo/$1.git/objects
chmod -R g+w /path/to/repo/$1.git/objects

Until now. Friend of mine (thanks rodrigez) actually discovered a native git feature, that allows you to control access to a repository – core.sharedRepository. It accepts the following values:

  • umask (or false) – the default value. Git uses permissions reported by umask
  • group (or true) – makes the repository group-writable
  • all (or world or everybody) – same as group, but make the repository readable by all users
  • 0xxx: 0xxx is an octal number and each file will have mode 0xxx. 0xxx will override users umask value. 0640 will create a repository which is group-readable but not writable. 0660 is equivalent to group.

You can set that using either git config command if your repository already exists, or you want to make the default value either global or system wide:

#> git config core.sharedRepository group

or during brand new repository creation:

#> git init --shared=group

So for me setting core.sharedRepository to group solves my first issues, while removing all access to other users to all files in the repository and setting core.sharedRepository to 0770 will restrict access to the repository to only limited number of people.

Git Up and Get Going

I have used git for the first time about a year ago. We’ve been talking about abandoning CVS for quite a while and Subversion seemed to be the best choice at the time. Yes we’ve looked at different version control systems, we tried sample migrations and still we couldn’t make a decision. And CVS… it was a constant battle, continuos corruptions, old hardware, hours long merges, but  it worked, so the general response was – why to change something that works.

We needed a strong kick in our butt and fortunately there was a man that was brave enough to kick until it hurt (thanks Rys!). With management convinced we only needed to plan the migration, schedule the training and just start using it.

That was about a year ago. Now, we use it on a daily basis, and I can’t imagine how we could live without it before. Yes, it’s not as mature as Subversion, Windows tool are poor and far from ideal, but it definitely speeded up our development process. I remember all this scepticism at the time and I only bring it up now because in the past few weeks I have actually seen more and more developers and projects switching to git. I was really glad to see PHPUnit and phpUnderControl moving over to github. It makes contribution to these projects so much easier.

I think git is the future of the open source software and it makes its development so much easier and faster. So if you haven’t used it yet or you’re just simply afraid of it, please put your fears aside and git up and going!