Containers and continuous integration for PHP developers. Part 2. Composer and code sniffer (phpcs).

Containers and continuous integration for PHP developers. Part 2. Composer and code sniffer (phpcs).

Part 2 of the series using composer container and code sniffer (phpcs) tool with Gitlab CI runner.
Vladimir Roudakov

Table of content.

Composer.

Composer to PHP developer is what npm for nodeJS developer. It acts as

  • dependency manager
  • script runner
  • miscellaneous configuration for 3rd part tools

Dependency manager main goal is to collect information about exact version of all dependencies (symfony or laravel packages, drupal modules, etc). composer.lock file stores exact commit for each dependency allowing composer to download it instead of committing directly to the repository.

Script runner allows to combine complex commands and use simple shortcut to execute it. One such example can be installation of Drupal, migration of the initial data and default login script all executed as single composer command.

Miscellaneous configuration for 3rd part tools can be configuration instructions for patches, 3rd part libraries

If you want to know more about composer, check out great 4-part composer blog series by Jay Friendly at Morpht.

Creating project.

Composer's create-project command is shortcut for downloading and setting up the project. You can use the command to download boilerplate project such as symfony, drupal or laravel

Example 1.

To create simple symfony project using symfony/skeleton boilerplate run on composer:1.8 composer image

chapter02-composer-symfony: image: composer:1.8 script: - composer create-project symfony/skeleton app

We can check the output using list command ls -la app/

Using Docker executor with image composer:1.8 ... Pulling docker image composer:1.8 ... ... $ composer create-project symfony/skeleton app Installing symfony/skeleton (v4.3.1.1) ... Created project in app ... Running after script... $ ls -la app total 160 drwxr-xr-x 8 root root 4096 Jun 6 15:58 . drwxrwxrwx 5 root root 4096 Jun 6 15:58 .. -rw-r--r-- 1 root root 961 Jun 6 15:58 .env -rw-r--r-- 1 root root 143 Jun 6 15:58 .gitignore drwxr-xr-x 2 root root 4096 Jun 6 15:58 bin -rw-r--r-- 1 root root 1365 Jun 6 15:58 composer.json -rw-r--r-- 1 root root 60818 Jun 6 15:58 composer.lock drwxr-xr-x 3 root root 4096 Jun 6 15:58 config drwxr-xr-x 2 root root 4096 Jun 6 15:58 public drwxr-xr-x 3 root root 4096 Jun 6 15:58 src -rw-r--r-- 1 root root 3210 Jun 6 15:58 symfony.lock drwxrwxrwx 4 root root 4096 Jun 6 15:58 var drwxr-xr-x 5 root root 4096 Jun 6 15:58 vendor

Complete output is available here.

PHP code sniffer.

PHP Code Sniffer is number of tools to check your code according to coding standards (phpcs) and fix it automatically (phpcbf).

Example 2.

Drupal content management system documentation contains instructions explain how to Install Coder Sniffer and how to use it via Command Line. Folder chapter02 contains sample Drupal module with deliberate coding standard errors. Following the documentation, let's get the dependencies

before_script: - composer global require drupal/coder:8.3.1 - composer global require dealerdirect/phpcodesniffer-composer-installer

Tell phpcs tool where to get Drupal and DrupalPractice configurations and check if the standards were added.

before_script: ... - $COMPOSER_HOME/vendor/bin/phpcs --config-set installed_paths $COMPOSER_HOME/vendor/drupal/coder/coder_sniffer - $COMPOSER_HOME/vendor/bin/phpcs -i

And execute phpcs tool with Drupal and DrupalPractice standards configurations for the following extensions php,module,inc,install,test,profile,theme,scss,yml

script: - $COMPOSER_HOME/vendor/bin/phpcs --standard=Drupal,DrupalPractice\ --extensions=php,module,inc,install,test,profile,theme,scss,yml

We should see the following output containing errors

$ $COMPOSER_HOME/vendor/bin/phpcs --standard=Drupal,DrupalPractice \ --extensions=php,module,inc,install,test,profile,theme,scss,yml chapter02 FILE: ...ng-containers-php/chapter02/drupal_module/drupal_module.info.yml ---------------------------------------------------------------------- FOUND 1 ERROR AND 3 WARNINGS AFFECTING 4 LINES ---------------------------------------------------------------------- 1 | WARNING | [ ] Remove "version" from the info file, it will be | | added by drupal.org packaging automatically 6 | WARNING | [ ] All dependencies must be prefixed with the project | | name, for example "drupal:" 7 | WARNING | [ ] All dependencies must be prefixed with the project | | name, for example "drupal:" 8 | ERROR | [x] Expected 1 newline at end of file; 2 found ---------------------------------------------------------------------- PHPCBF CAN FIX THE 1 MARKED SNIFF VIOLATIONS AUTOMATICALLY ---------------------------------------------------------------------- FILE: ...tainers-php/chapter02/drupal_module/src/Command/PhpcsCommand.php ---------------------------------------------------------------------- FOUND 17 ERRORS AND 3 WARNINGS AFFECTING 15 LINES ---------------------------------------------------------------------- 3 | ERROR | [x] Namespaced classes, interfaces and traits should | | not begin with a file doc comment 3 | ERROR | [x] Inline comments must end in full-stops, | | exclamation marks, colons, question marks, or | | closing parentheses 10 | WARNING | [x] Unused use statement ... ---------------------------------------------------------------------- PHPCBF CAN FIX THE 19 MARKED SNIFF VIOLATIONS AUTOMATICALLY ----------------------------------------------------------------------

Complete output is available here.

Example 3.

For symfony application as we can see from Code Sniffer Symfony page there is another tool php-cs-fixer. It automatically checks and fixes the code.

The setup to run Symfony coding standard check with differences (flag: --diff) after copying custom object from chapter02/drupal_module/src/Command folder: 

c0203-composer-drupal-phpcs: image: composer:1.8 before_script: - composer global require friendsofphp/php-cs-fixer - composer create-project symfony/skeleton app - cp -R chapter02/drupal_module/src/Command app/src/ script: - $COMPOSER_HOME/vendor/bin/php-cs-fixer fix app/src/ [email protected] --verbose --diff

The output:

$ cp -R chapter02/drupal_module/src/Command app/src/ $ $COMPOSER_HOME/vendor/bin/php-cs-fixer fix app/src/ [email protected] --verbose --diff Loaded config default. .F Legend: ?-unknown, I-invalid file syntax, file ignored, S-Skipped, .-no changes, F-fixed, E-error 1) app/src/Command/PhpcsCommand.php (class_attributes_separation, single_line_after_imports, no_unused_imports, single_blank_line_before_namespace, braces) ---------- begin diff ---------- --- Original +++ New @@ @@ <?php // src/Command/ExpensesReindexCommand.php + @@ @@ use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Finder\Finder; -use Symfony\Component\Filesystem\Filesystem; - class PhpcsCommand extends Command { -// the name of the command (the part after "bin/console") - protected static $defaultName = 'app:phpcs-example'; + // the name of the command (the part after "bin/console") + protected static $defaultName = 'app:phpcs-example'; ... ----------- end diff ----------- Fixed all files in 0.037 seconds, 6.000 MB memory used Job succeeded

Complete output is available here.

Conclusion

You can use your CI tools and official composer image from Docker Hub to run any composer command automatically in your CI.

Links