Checking a custom coding standard with PHP_CodeSniffer

PHP_CodeSniffer is a tool for checking source code compliance with a defined coding standard. There are some predefined standards (PEAR, Zend, PSR1, PSR2, etc.), but the true power of PHP_CodeSniffer lies in the possibility of defining custom standards.

We've been using PHPCS on Shopio for a long time, but we've utilized just the Zend coding standard provided within the PHPCS distribution. I recently found some time to dig deeper into PHPCS and I played a lot with custom standards.

How can I define a custom PHPCS standard?

A custom standard is just an XML file (usually located in the project directory) which imports rules that already exist in PHPCS. It's usually better to import an existing standard and customize it with additional rules. And if there are some rules that you don't like, you can disable them (or reconfigure their parameters). The following example shows a custom ruleset that just imports the Zend coding standard:

<?xml version="1.0"?>
<ruleset name="My Custom Standard">
    <rule ref="Zend" />
</ruleset>

Using the custom ruleset is also simple, as you just need to pass the path to the XML file with the custom standard: phpcs --standard=ruleset.xml file.php.

As I've already mentioned, you can reconfigure the way that some of the rules behave. The first one I tried was the line length. We all use fullHD screens for development, so there is no need to limit the line length to 80 characters. With the following snippet, you can get errors and warnings only for extremely long lines (which usually indicates code-smell):

<rule ref="Generic.Files.LineLength">
    <properties>
        <property name="lineLimit" value="250" />
        <property name="absoluteLineLimit" value="300" />
    </properties>
</rule>

Other often-discovered issues are mixed indentation (tabs and spaces), and mixed newlines (you should always use Unix EOLs). It can be a tedious task to fix them manually, but I've got good news for you: there is a tool called SFK (Swiss File Knife) which can easily handle such changes in a second.

If you are still getting hundreds of coding standards violations, I would suggest that you disable some rules by setting their severity to 0 and fix the remaining errors. When you have more time for codebase cleaning, enable some of previously disabled rules and repeat the process until you get 0 errors with all ‚sniffs‘ (rules) enabled.

<rule ref="Generic.Files.LineLength">
    <severity>0</severity>
</rule>

Ignoring some of the errors

You can exclude specific parts of the source code from being scanned by PHPCS by wrapping the problematic part with //@codingStandardsIgnoreStart and //@codingStandardsIgnoreEnd comments. You should reach for those as a last resort, such as when the piece of the code cannot be refactored or rewritten. It is also good to include a reason for exclusion in the comment.

Adding more rules to the ruleset

When you (and the whole team) are comfortable with writing code according to specified coding standard and the PHPCS is run regularly (typically as a part of a Jenkins CI build), you can be more strict and add more rules to the ruleset. It can be easily done by checking some already existing standards and choosing some rules from them. You can do it incrementally – choose one rule that looks good, add it to your ruleset and see what happens after you run PHPCS.

You can check out the coding standard we use for Shopio.cz to see everything that can be checked by PHPCS.

Enable realtime PHP_CodeSniffer checking in PHPStorm

PHPStorm (great IDE btw.) has integrated support for PHP_CodeSniffer. It can work easily with standards predefined in PHP_CodeSniffer. But it can also check the code with your custom standard. The only thing you need to do is to select the „Custom“ standard, which allows you to select the directory where the standard definition file is located. You can select your project directory (you have to have your custom standard file called ruleset.xml) and it will load the standard automatically!

See the detailed guide, Using PHP Code Sniffer Tool

Conclusion

Are you using PHP_CodeSniffer for your projects? Do you want to show off your ruleset file? Or if you are not using PHP_CodeSniffer, I would be happy to hear why.

Clean up your Sass with SCSS Lint

As you may have already noticed, I'm a little obsessed with code quality, particularly its automatic checking and monitoring (Czech only, sorry). In this article, I want to show you how to ensure that your SCSS files have consistent formatting style. And it may even help you to detect some mistakes!

At w3w we've been using SASS for quite a while. Shopio's new responsive template is based upon Twitter Boostrap (we are using an unofficial Sass version of Twitter Boostrap v2.3.2 – we used the it before it was cool!). We are using Sass together with Compass framework. Apart from that, I also worked on two mobile apps based upon Sencha Touch. It is a HTML5+JS+CSS framework for cross-platform mobile app development, with styling powered by Saas.

Demo

See this code snippet (demo.scss file):

$highContrastMode: true;

@if ($highContrastMode) {
  body {
    background: black;
    color: yellow;
  }
} else {
  body {
    background: white;
    color: gray;
  }
}

If we have the $highContrastMode variable set to true, we want to render yellow text on black background; if not, we don't care about those with poor vision. Would it work as described? No! We missed the @ character before the else keyword! Compass compiles it without complaint as the code is completely valid SASS. And we will have a cute else body selector in the compiled css.

How could we have prevented this? By using scss-lint!

If we had scss-lint as part of our CI build process, we would have been notified immediately. When you run scss-lint on the code snippet above (scss-lint demo.scss), it complains about a lot of things, including the else error:

demo.scss:8 [W] Rule declaration should be preceded by an empty line

Custom style

At Shopio, the SCSS coding style is not the same as the default coding style in scss-lint. When we ran it for the first time, unsurprisingly, we got a few thousand errors and warnings.

Luckily, scss-lint allows you to configure custom settings that will then be used for checking. So I asked Stuart questions such as, „Do you use 2 or 4 spaces for indentation?“, „Do you prefer single or double quotes?“ or, „Do you use colour names or hex codes?“. After receiving the answers and doing some testing I was able to come up with a .scss-lint.yml file, which suits our needs (there are many more options in the docs!). It still results in a few hundreds warnings, which we are fixing continually.

Continuous integration

scss-lint offers a XML output option (with --format=XML) which can be consumed by Jenkins or similar tools. But for some strange reason, the XML output does not work on my Windows machine. (I hope it would work on our Jenkins machine)

Conclusion

It's not hard to setup the scss-lint to check SCSS files and the benefits are obvious. It will ensure that you use a consistent coding style and it may even prevent some errors. And if your coding style is different from the default one, then you can simply redefine the rules.

Thanks Stuart for language and technical review.

Integrating JavaScript files with JSHint, Phing and Jenkins [EN]

I wrote an article about integrating JavaScript Node.js projects with Jenkins more than year ago. Recently I wanted to solve a bit different issue. I wanted to add JSHint validation as a part of a Phing build (our project is PHP/Zend Framework based with some JS files).

It can be done it a few steps (I will go through them in more detail later):

  1. Install Node.js
  2. Install JSHint
  3. Add JSHint task to a buildfile
  4. Set up reporting in Jenkins

1) Installing Node.js

Node.js can be installed via MSI installer on Windows, via package manager in most Linux distros (except for Debian stable which we are using). So I had to compile it myself (Ubuntu PPA packages does not work because of unmet dependencies). As long as we use Node.js just for JSHint validation, there is no need to upgrade it to latest versions, and therefore I put the package in our salt repository and it can be installed automatically next time (we have whole Jenkins server salted).

2) Installing JSHint

If you have the Node.js running, installing JSHint is pretty easy. You just run

npm install jshint -g

To verify that it is installed correctly, run jshint -v which should print the jshint version.

3) Adding JSHint task to a buildfile

This is the hardest step in the whole process. There was no JsHintTask in the standard Phing distribution, so I had to write it myself. I have issued a PullRequest, so it may be part of some future version of Phing.

The first step is to download the task and put it somewhere, where Phing can access it. Next code snippet assumes, that it is a part of the project and it is located in the support/phing/JsHintTask.php file.

Second step is to link the file from the buildfile:

<path id="project.class.path">
        <pathelement dir="${project.basedir}/support/phing/"/>
</path>

<taskdef name="jshint" classname="JsHintTask">
        <classpath refid="project.class.path"/>
</taskdef>

Last step is to create a jshint target (you can check the detailed description of the parameters in the docs). Most important is the checkstyleReportPath attribute, which defines where the checkstyle report will be saved and the fileset element, which defines which files should be checked.

<target name="jshint" description="Javascript Lint">
        <mkdir dir="${project.basedir}/build/checkstyle-jshint"/>
        <jshint
                        haltOnError="false"
                        haltOnWarning="false"
                        checkstyleReportPath="${project.basedir}/build/checkstyle-jshint/checkstyle-jshint.xml"
                >
                <fileset dir="${project.basedir}/public_html/www/js">
                        <include name="**/**.js"/>
                        <exclude name="js-cache/**"/>
                        <exclude name="jquery-1.*.min.js"/>
                        <exclude name="bootstrap/bootstrap.js"/>
                </fileset>
        </jshint>
</target>

JSHint supports config file, where you can set which issues you want to get reported. It is easy – you just create .jshintrc file in the project root directory and JSHint will load it automatically. File should contain a JSON object with configuration options. See the docs. And you can check the .jshintrc file we are using:

{
        "maxerr"        :       1000,
        "camelcase"     :       true,
        "immed"         :       true,
        "latedef"       :       true,
        "newcap"        :       true,
        "quotmark"      :       "single",
        "trailing"      :       true,
        "jquery"        :       true,
        "white"         :       true,
        "globals"       :       {}
}

4) Setting up the reporting in Jenkins

Just add a Post-build action – Report Violations and put the path in there. 

After the build finishes, you can check the errors in the Violations section of the build report.

Conclusion

It is really easy to set-up JavaScript files validation in a PHP project, so why not have it? If you have any trouble setting it up, just ask in the comments and I'll try to help you. I would be also happy, if you share your way of validating JS files.

Jak v Jenkinsu buildovat branche z forků?

bakalářce jsem psal o tom, jak nastavit a používat Jenkins pro statickou analýzu PHP projektů. V té době jsme ještě na Shopiu používali Subversion, takže build byl nastavený pro trunk a všechno bylo krásné a sluníčkové.

Po přechodu na git (a Github) jsme začali používat koncept „forků“ a PullRequestů (každý vývojář má svoji kopii – fork – hlavního repositáře, jednotlivé změny dělá v branchích a ty pak odešle jako PullRequest a jiný vývojář je zkontroluje a mergne).

Problémem bylo, že přestože většinou spouštíme testy lokálně před vytvořením PullRequestu, tak občas po mergnutí build na Jenkinsu spadnul na neprocházejících testech. Jenkins běží na Linuxu, vyvíjíme na Windows, takže občas šlo o problém s konci řádků, ale většinou o nějaký problém s pořadím testů (na Linuxu je jiné, a ano, vím že je velmi špatně mít testy závislé na stavu prostředí, ale lepší mít takové než žádné). A občas šlo samozřejmě o chybu a nespuštěné testy na localhostu („Tohle přece žádný test rozbít nemůže!“). Takže by bylo super testy spouštět automaticky pro každou změnu v jakékoliv branchi ve forku každého vývojáře.

V Jenkinsu to nakonec šlo nastavit velmi snadno – vytvořit jsem pro každý fork samostatný projekt a nastavil cesty k jednotlivým Githubovým repositářům. Pak je důležité nastavit, aby se v rámci buildu forku spouštěl jen phpunit a nic jiného – chceme co nejdříve vědět, že testy neprocházejí a nějaké porušení coding standards nás v tu chvíli tolik netrápí.

Druhou věcí, co je potřeba nastavit jsou branche pro buildování: 

A samozřejmě nastavit, aby v případě failu přišel mail danému vývojáři: 

Ještě jedna věc – je dobré, pokud mají tyhle rychlé buildy přidělené svoje vlákno, aby nečekaly dobu ve frontě, než doběhne jiný projekt (tohle zatím nastavené nemáme, ale budeme mít brzy).

Pro opensource projekty existuje super věc – TravisCI, který dělá přibližně to samé – builduje všechny vaše branche a na Githubu se dokonce stav branche ukazuje u PullRequestu

HipHop for PHP

Dalším zajímavým nástrojem, který by bylo možné zařadit do kontinuální integrace, je HipHop for PHP vyvinutý společností Facebook Inc. Jeho primárním účelem je převod skriptů v jazyce PHP do jazyka C++, nicméně je možné ho využít pro statickou analýzu (umí odhalit chyby, které jiné nástroje neodhalí). A případně ho zařadit jako jeden z nástrojů kontinuální integrace.

Instalace nástroje

Nástroj je nutné zkompilovat ze zdrojových kódů, nejsou k dispozici instalační balíčky. Zároveň je nutné nejdříve zkompilovat několik knihoven třetích stran. K dispozici jsou postupy na wiki projektu na githubu, zvolte ten odpovídající vaší linuxové distribuci.

Já jsem instaloval na VirtualMasteru, takže jsem zvolil návod pro Ubuntu 10.04

Pokud si chcete HipHop jen vyzkoušet, tak je zbytečné trávit čas kompilací. Proto jsem na VirtualMasteru vytvořil veřejnou šablonu s připraveným HipHop for PHP

Použití nástroje

Poté, co máme nástroj nainstalovaný (buď podle postupu a nebo vytvořením serveru z image výše), nastavíme potřebné cesty:

cd /root/hiphop/
export HPHP_HOME=`/bin/pwd`
export HPHP_LIB=`/bin/pwd`/bin

A zkusíme spustit analýzu. Já jsem zkoušel Zend Framework 1.

cd /tmp
svn export http://framework.zend.com/svn/framework/standard/trunk/library zf1
cd zf1
/root/hiphop/hiphop-php/src/hphp/hphp -t analyze --input-dir ./Zend/ --include-path ./

Výstup je poté uložen v /tmp/hphp_AFDvIh/CodeError.js (resp. v podobně nazvaném adresáři).

Když jsem prosěl výstup z kontroly ZF1, tak jsem postupně přidal 12 issues do ZF – od ZF-12225 do ZF-12236

Zařazení nástroje do CI

Sebastian Bergmann vyvinul nástroj obalující HipHop do PHP s možností exportu výsledků ve formátu pro CheckStyle. Nicméně do CI jsem ho zatím nenasadil, protože se bojím, že bych kompilací a instalací zkompilovaných věcí mohl poblbnout server.

Závěrem

Pokud chcete ztratit iluze o svých zdrojácích, zkuste na ně spustit HipHop :)

phpDocumentor 2 místo DocBloxu

bakalářce jsem popisoval rozhodování mezi různými nástroji na generování PHP API dokumentace v rámci kontinuální integrace. Teď se výběr zjednodušil, proto z nástroje DocBlox se stal se phpDocumentor 2. Sice se v článku mluví o „merge“, ale ve skutečnosti jde o přejmenování s tím, že původní phpDocumentor se přestane vyvíjet.

Nainstalovat ho můžeme pomocí:

pear channel-discover pear.phpdoc.org
pear install phpdoc/phpDocumentor-alpha

Kromě výchozí šablony jsou k dispozici i nějaké další, ale nešly mi doinstalovat starým postupem tak jako u DocBloxu, ale musel jsem přes PEAR:

pear install phpdoc/phpDocumentor_Template_checkstyle
pear install phpdoc/phpDocumentor_Template_zend

Přehled všech dostupných šablon najdete na http://pear.phpdoc.org/

Generování funguje pořád stejně, jen je potřeba vyměnit docblox za phpdoc:

phpdoc -f phpdoc01.php
phpdoc -f phpdoc01.php --template checkstyle

Na výchozí šabloně mě překvapilo, že v detailu třídy nikde není vypsané její jméno. Holt je to ještě alpha.

Až bude phpDocumentor 2 stabilní, tak určitě bude dobré znovu zvážit výběr nástroje na generování API dokumentace. Přechod z DocBloxu je jasný, ale pokud se objeví i šablona podobná té v ApiGenu, tak bych kvůli cachování analyzovaných souborů (zrychlení oceníte hlavně u větších projektů) zvážil přechod na phpDocumentor.

Čím generujte API dokumentaci v PHP vy?

PHP_CodeBrowser 1.0.3 a změna PEAR kanálu

Pro reportování chyb z PHP_CodeSniffer, PHPCPD a PMD jsem při nasazení kontinuální integrace použil PHP_CodeBrowser. Nicméně, nelíbilo se mi, že jsou v reportu vypsané i soubory, které žádné chyby neobsahují – pak se hůře hledají ty, ve kterých chyby jsou.

Doprogramoval jsem tedy možnost takové soubory skrýt.

--excludeOK    Exclude files with no issues from the report

Před pár dny vyšla verze 1.0.3, která už vylepšení obsahuje. Zároveň došlo ke změně PEAR kanálu pro instalaci balíčku.

Pro upgrade je tedy potřeba starou verzi nejdříve odinstalovat:

pear uninstall phpunit/PHP_CodeBrowser

Pak přidat nový kanál a nainstalovat PHP_CodeBrowser z něj:

pear channel-discover pear.phpqatools.org
pear install phpqatools/PHP_CodeBrowser

A do build skriptu stačí přidat přepínač --excludeOK, takže příkaz pro generování pomocí phpcb bude vypadat takto:

phpcb  --log ${project.basedir}/build --source ${project.basedir} --output ${project.basedir}/build/code-browser --excludeOK

Používáte také PHP_CodeBrowser nebo si v Jenkinsu vystačíte s Violations?

Kontinuální integrace při vývoji webových aplikací v PHP (bakalářská práce)

Když jsem si vybíral téma na bakalářskou práci, tak jsem chtěl zpracovat něco, co bude užitečné a někdo si to přečte, protože ho to bude zajímat. Nakonec jsem si vybral Continuous Integration (neboli hezky česky Kontinuální integraci).

Věřím, že se mi to docela povedlo a práce je užitečná a snad i docela čtivá.

Vzhledem k tomu, že mám obhajobu až v červnu, tak ještě nemám posudky, tudíž není akademicky posvěcená. Ale věci kolem kontinuální integrace se pořád mění, tak mi přijde škoda ji nechat dva měsíce zbytečně zastarávat.

Zároveň vzhledem k tomu, že u BP není zvykem vydávat aktualizované verze, plánuju tu a tam napsat na blog o různých novinkách, které kolem CI vyzkouším (takže sledujte blog, případně Twitter)

Kontinuální integrace při vývoji webových aplikací v PHP (Bakalářská práce)

Ke stažení ve formátu PDF

Co na ni říkáte? Pokud vám pomůže s nasazením kontinuální integrace na váš projekt, tak budu rád, když mi napíšete do komentářů nebo na e-mail.

Moje články o kontinuální integraci:

Integrating JavaScript/Node.js projects with JSHint, Mocha and Jenkins [EN]

Update 15. 9. 2013: See how I set up CI for JS files inside a PHP project (using Phing)

I've set up the Continuous Integration for PHP projects on Jenkins recently. It went quite well, but the fact that CI tools for PHP are not as mature as those for Java was obvious. (Most of the PHP CI tools are ports of their Java originals.)

Apart from PHP projects, my colleague just started working on a new project, using JavaScript and Node.js, so I thought it would be nice to add it to Jenkins too.

After some experiments, I came to this:

  • Java: It is normal to use CI in Java world.
  • PHP: QA and CI are being adapted in PHP world.
  • JavaScript: Very few people are using CI. Lots of WTF.

However, I was able to create a basic setup with Mocha for unit testing and JSHint for static analysis. Here is how I did it:

JavaScript environment

First, I wanted to add JS environment to the server we use for PHP integration. But then I realized that Node.js is available only in Debian unstable and it has more dependencies (from unstable) then the Jenkins and Java altogether. I didn't want to break anything on this server, so I used Jenkins' Slave feature and connected to server used for JS development (so all the JS stuff is already running there).

Setting up Mocha

Mocha is a JavaScript test framework. It worked fine on the server: 

So I just needed to find out, if it has some output usable for CI. Surprisingly, it has and it works fine despite the fact, it is poorly documented :-) 

Setting up JSHint

JSHint can be installed via npm:

npm install jshint -g

It checks JS like this:

jshint myfile.js

And yes, it can produce XML report:

jshint ./app --jslint-reporter > jshint.xml

Making it all work

You need Copy To Slave, xUnit and Violations plugins in Jenkins.

We will need two Jenkins jobs. First will run all the stuff, gather the XMLs with results and trigger the reporting job. The second job will just process results and display them. This is necessary, because I realized that Violations plugin runs earlier that the Copy to Slave, and therefore, it had no data.

In the first job, we bind it to our Node.js slave and add a build step (Execute shell):

cd /var/jenkins/workspace/nodejs && mocha -R xunit > xunit.xml && jshint ./app ./public/javascripts/app/ --config .jshintrc --jslint-reporter > jshint.xml || exit 0

Then we need to gather the results from slave node via Copy to Slave plugin: 

Second job

Second job has no build steps, it only processes the results. The test results worked for me, when I set them as PHPUnit ones:

The JSHint results can be processed via Violations plugin: 

However, there is an issue when using Violations plugin for JS files. It is not possible to browse the errors in files, as it is possible for other reports. But I'm not only one who experiences this issue.

Conclusion:

We have basic continuous integration for JS code up and running. 

JavaScript community is growing strong, so I hope that there will soon be loads of different CI tools for JS. I'm only afraid of their fragmentation (There are many new JS frameworks built every day).