Linting PHP Files in Parallel on Travis

php-lint-travis-krita

With PHP 7 around the corner here is a small tip how you can at least lint the code in your project to be PHP 7 syntax compatible. That allows you to easier obtain forward-compatible PHP code with ease. So if you already integrate with Travis, all you need to do is to add some two-to-four lines to your .travis.yaml file and you’re done. Here is how:

Linting with PHP on the Command Line

The PHP command supports syntax checking a file (often called linting, if that is no news to you, skip over to the next section). The standard call for that is the lower-case L switch followed by the filename to verify:

php -l 

That command will have an exit status of 0 if no errors could be detected or 255 if an error is found. Next to the exit status, a message will be printed (to standard output) like “No syntax errors detected in fine.php” or “Errors parsing broken.php” depending on success or failure.

If you need an error message, you can enable log_errors (set it to “on“) and leave error_log empty so that in PHP-CLI errors will be “logged” to standard error.

Invoking PHP in Parallel

With some command-line-magic you can then use the find command to locate all files to validate, pass the filename to xargs which allows execution of the said PHP lint in parallel. Here is an example of that:

find {src,tests} -name "*.php" ! -path '*/NonPHP7.php' -print0 \
  | xargs -0 -n1 -P8 php -l

This finds all files with the .php extension within the src and tests directories. That’s a typical repository with source and tests.

Additionally the example shows the exclusions of all paths that match */NonPHP7File.php – for example if you have files for backwards compatibility you know that will never validate in PHP 7 (and will not be used with that PHP version).

All matching filenames are passed to xargs which will fire php -l in parallel with eight executions (processes) for each file individually (-n1).

Because xargs will stop processing on the first non-zero exit status, it will stop when the first PHP file is found that has errors (exit status of PHP lint is 0 with no error and 255 on error).

Until here this is merely borrowed from another post, PHP lint checking multiple files in parallel (Nov 2011 by Sefaan Lippens), which gives a similar example.

Integrating with Travis

The command above can be added to your Travis build easily. All it needs is to create an entry for PHP 7.0 running it as build script. For example in the matrix section under the include subsection:

  include:
    # Lint code with PHP 7.0
    - php: 7.0
      script: find {src,tests} -name "*.php" ! -path '*/NonPHP7.php' -print0 | xargs -0 -n1 -P8 php -l

The build then will fail if the command in script will have a non-zero exit status.

I was using a command-line similar to this one but over the time I had a few places to tweak. First of all, it creates a lot of output for all the files which are correct. That normally is not of interest. Of interest are in case of failure the name of the file that violated the linting.

I decided to make use of grep with an inverted match to filter out all messages about validity so only the errors are output:

grep -v '^No syntax errors detected'

This works nicely for the output – only files with errors will be shown – but it does change the exit status: It will return 0 if a lint-error is found, 1 if no lint-error is found and 2 if an error (like failure to access a file) occurred. So this will make the Travis build fail in case there are no syntax errors.

Changing Exit Status Inline on the Fly

What I needed to do was to change the exit status code. One command that is able to do that is test. The logic here is to make the exit status of 1 the success case (0) and every other status is a failed build anyway. So here the command-line in full:

find {src,tests} -name "*.php" ! -path '*/NonPHP7.php' -print0 \
  | xargs -0 -n1 -P8 php -l \
  | grep -v '^No syntax errors detected' \
  ; test $? -eq 1

Even this tip is specific to a PHP scenario on Travis, it can be used in other environments as well. I hope it has the one or other detail that is helpful for the day-to-day command-line-foo. Happy operations.


Gaining even more speed, for example in the local build, is outlined in another blog post: Speedpills 4 Linting PHP Files in Parallel (Oct 2019)


Image: Krita brushes and composition (rockt!); Travis CI logo and some Elephpant vector from the wilds. This blog post has been produced with 100% Free Software.

This entry was posted in Hakre's Tips, PHP Development, Pressed, Tools and tagged , , , , , , , , . Bookmark the permalink.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.