Статьи

Написание PHP Git Hooks со статическим обзором

Если вы использовали Git более короткое время, вы, наверное, слышали о хуках Git. Если нет, то перехватчики Git, как Эндрю Удваре представил здесь на SitePoint в августе прошлого года, являются сценариями, которые выполняются на основе определенных событий в жизненном цикле Git как на клиенте, так и на сервере.

Hook illustration

Существуют хуки для пред- и пост-фиксации, пред- и пост-обновления, пре-push, pre-rebase и так далее. Примеры хуков написаны на Bash, одном из языков оболочки Linux. Но они могут быть написаны практически на любом языке, который вам удобен или опытен.

Как отметил Тим Борончик в сентябре 2013 года, существует множество целенаправленных целей, к которым можно привязать крючки. Они включают в себя linting, проверку правописания коммитов, проверку исправлений на соответствие принятым стандартам кодирования, запуск composer и так далее.

PHP — отличный язык, не поймите меня неправильно, но это не обязательно лучший язык для сценариев оболочки. По общему признанию, это стало намного лучше, чем это было когда-то. Но по сравнению с такими языками, как Bash, Python и Ruby, он не совсем подходит для создания хитов Git; то есть до сих пор.

Благодаря Статическому обзору Сэмюэля Паркинсона вы можете теперь писать хиты Git с помощью собственного PHP, опционально опираясь на существующие базовые классы. В сегодняшнем посте я собираюсь рассказать вам о том, что предлагается, и в var_dump() собственный класс для проверки любых длительных вызовов var_dump() .

Установка библиотеки

Как и большинство, если не все современные библиотеки и пакеты PHP, StaticReview устанавливается через Composer. Чтобы установить его в свой проект, запустите composer require sjparkinson/static-review в корне вашего проекта. С этим, давайте начнем.

Рабочий пример

Как и в любом другом коде, лучший способ понять его — это просмотреть реальный пример, такой как приведенный ниже, взятый из репозитория проекта StaticReview.

Во-первых, как и все сценарии оболочки, он определяет, что будет запускать сценарий. В данном случае это PHP. После этого включается скрипт автозагрузки Composer, так что скрипт имеет доступ ко всем необходимым классам, а также предупреждение, если скрипт автозагрузки будет недоступен.

 #!/usr/bin/env php 
 <? php $included =  include file_exists ( __DIR__ .   '/../vendor/autoload.php' ) 
     ?  __DIR__ .   '/../vendor/autoload.php' 
     :  __DIR__ .   '/../../../autoload.php' ; 

 if   (!  $included )   { echo 'You must set up the project dependencies, run the following commands:'   .  PHP_EOL .   'curl -sS https://getcomposer.org/installer | php'   .  PHP_EOL .   'php composer.phar install'   .  PHP_EOL ; 

     exit ( 1 ); 
 } 

Далее, как и в большинстве современных PHP-скриптов, импортируются все необходимые классы и инициализируются три переменные. Это CLImate Reporter , CLImate и GitVersionControl . Объект Reporter предоставляет информацию о хуке, был ли хук успешным или неудачным. Объект CLImate упрощает вывод цветного текста и текстовых форматов. А объект GitVersionControl упрощает взаимодействие с Git.

 // Reference the required classes and the reviews you want to use. 
 use   League \C LImate \C LImate ; 
 use   StaticReview \Reporter\Reporter ; 
 use   StaticReview \Review\Composer\ComposerLintReview ; 
 use   StaticReview \Review\General\LineEndingsReview ; 
 use   StaticReview \Review\General\NoCommitTagReview ; 
 use   StaticReview \Review\PHP\PhpLeadingLineReview ; 
 use   StaticReview \Review\PHP\PhpLintReview ; 
 use   StaticReview \StaticReview ; 
 use   StaticReview \VersionControl\GitVersionControl ; $reporter =   new   Reporter (); $climate =   new   CLImate (); $Git =   new   GitVersionControl (); 

Затем он создает новый объект StaticReview и передает типы обзоров для запуска в ловушке. В случае ниже, это добавляет пять. Эти отзывы:

  • Проверяет, содержит ли файл какие-либо окончания строк CRLF
  • Проверяет, начинается ли заданный файл с правильной последовательности символов
  • Проверяет, содержит ли файл NOCOMMIT .
  • Проверяет PHP-файлы, используя встроенный PHP-линтер, php -l .
  • Проверяет, является ли файл composer.json действительным.

Затем, это говорит обзору проверить любые поставленные файлы.

 $review =   new   StaticReview ( $reporter ); 

 // Add any reviews to the StaticReview instance, supports a fluent interface. $review -> addReview ( new   LineEndingsReview ()) 
        -> addReview ( new   PhpLeadingLineReview ()) 
        -> addReview ( new   NoCommitTagReview ()) 
        -> addReview ( new   PhpLintReview ()) 
        -> addReview ( new   ComposerLintReview ()); 

 // Review the staged files. $review -> review ( $Git -> getStagedFiles ()); 

Подобно другим формам проверки, если о проблемах сообщают какие-либо из классов проверки, каждая проблема распечатывается на терминал красным цветом, перед которым , и фиксация не завершается. Однако, если нет проблем, то сообщение об успехе Looking good. Have you tested everything? Looking good. Have you tested everything? , распечатывается, и фиксация разрешена для завершения.

 // Check if any matching issues were found. 
 if   ( $reporter -> hasIssues ())   { $climate -> out ( '' )-> out ( '' ); 
     foreach   ( $reporter -> getIssues ()   as  $issue )   { $climate -> red ( $issue ); 
     } $climate -> out ( '' )-> red ( '✘ Please fix the errors above.' ); 
     exit ( 1 ); 
 }   else   { $climate -> out ( '' )-> green ( ' Looking good.' )-> white ( 'Have you tested everything?' ); 
     exit ( 0 ); 
 } 

Пока что ничего такого, с чем вы не были бы знакомы, если бы вы раньше работали с Git-хуками Но как, в частности, работает класс обзора? Каждый класс Review расширяет AbstractReview , который реализует ReviewInterface . Этот интерфейс требует реализации двух методов: canReview() и review() .

canReview , как следует из названия, определяет, можно ли запустить review , и review выполняет реальную рецензию. Возьмите ComposerLintReview.php в качестве примера, который вы можете увидеть ниже. canReview() проверяет, называется ли проверяемый файл composer.json . Если так, то review() может быть вызван.

Затем создается команда, которая вызывает функцию проверки Composer в composer.json и передает ее в метод getProcess , реализованный в AbstractReview , для запуска процесса. Если процесс не успешен, сообщение об ошибке создается и устанавливается для объекта Reporter, передавая его вызову метода error() Reporter, а также файлу, который был просмотрен.

 public   function  canReview ( FileInterface  $file ) 
 { 
     // only if the filename is "composer.json" 
     return   ( $file -> getFileName ()   ===   'composer.json' ); 
 } 

 public   function  review ( ReporterInterface  $reporter ,   FileInterface  $file ) 
 { $cmd =  sprintf ( 'composer validate %s' ,  $file -> getFullPath ()); $process =  $this -> getProcess ( $cmd ); $process -> run (); 

     if   (!  $process -> isSuccessful ())   { $message =   'The composer configuration is not valid' ; $reporter -> error ( $message ,  $this ,  $file ); 
     } 
 } 

Короче говоря, это все, что требуется для создания ловушки Git для проверки файлов по одному из событий в жизненном цикле Git.

Пользовательский отзыв

Если вы vendor/sjparkinson/static-review/src/Review/ , то увидите, что существует довольно много готовых классов Review. Они охватывают Composer, PHP и обзоры общего назначения. Но что, если мы захотим создать его сами, который подойдет для нашего конкретного случая использования?

Что если мы обеспокоены тем, что можем оставить операторы var_dump в нашем коде? Мы бы не стали, верно? Но эй, никогда не бывает больно, потому что старые привычки могут иногда сильно умирать. Так как же будет выглядеть пользовательский отзыв? Давайте проработаем один и узнаем.

Сначала мы создадим новую структуру каталогов для хранения нашего кода, совместимого с PSR-4 . Используйте следующую команду в корневом каталоге проекта.

 mkdir - p src / SitePoint / StaticReview / PHP 

Затем в composer.json добавьте следующее в существующую конфигурацию и запустите composer dumpautoload :

 "autoload" :   { 
   "psr-4" :   { 
     "SitePoint\\" :   "src/SitePoint/" 
   } 
 } 

Это обновит автозагрузчик Composer, чтобы также автоматически загружать наше новое пространство имен. После этого создайте новый класс с именем VarDumpReview.php в src/SitePoint/StaticReview/PHP . В него добавьте следующий код:

 <? php namespace   SitePoint \StaticReview\PHP ; 

 use   StaticReview \File\FileInterface ; 
 use   StaticReview \Reporter\ReporterInterface ; 
 use   StaticReview \Review\AbstractReview ; 

 class   VarDumpReview   extends   AbstractReview 
 { 
     public   function  canReview ( FileInterface  $file ) 
     { $extension =  $file -> getExtension (); 
         return   ( $extension ===   'php'   ||  $extension ===   'phtml' ); 
     } 

     public   function  review ( ReporterInterface  $reporter ,   FileInterface  $file ) 
     { $cmd =  sprintf ( 'grep --fixed-strings --ignore-case --quiet "var_dump" %s' ,  $file -> getFullPath ()); $process =  $this -> getProcess ( $cmd ); $process -> run (); 

         if   ( $process -> isSuccessful ())   { $message =   'A call to `var_dump()` was found' ; $reporter -> error ( $message ,  $this ,  $file ); 
         } 
     } 
 } 

Основанный на PhpLintReview.php и ComposerLintReview.php , canReview проверяет, является ли проверяемый файл на основе расширения файлом PHP. Если да, то review использует grep для сканирования файла на наличие ссылок на var_dump .

Если они найдены, регистрируется ошибка, которая сообщает пользователю, что был найден вызов var_dump , и фиксация не удалась. Если вы запустите его, вы можете ожидать вывода, как на скриншоте ниже.

StaticReview failure

Создание Крюка

Остался только один последний шаг — создание Git-хука из нашего класса хуков. В новой директории Hooks в корне моего проекта я скопировал код хука, с которым мы работали в начале статьи, сделав одно небольшое изменение.

Я добавил наш новый файл обзора в список отзывов следующим образом:

 $review -> addReview ( new   LineEndingsReview ()) 
        -> addReview ( new   PhpLeadingLineReview ()) 
        -> addReview ( new   NoCommitTagReview ()) 
        -> addReview ( new   PhpLintReview ()) 
        -> addReview ( new   ComposerLintReview ()) 
        -> addReview ( new   VarDumpReview ()); 

После этого создайте ловушку перед фиксацией, выполнив следующую команду.

 ./ vendor / bin / static - review . php hook : install hooks / example - pre - commit . php . Git / hooks / pre - commit 

И с этим, если вы посмотрите в .git/hooks , вы увидите символическую ссылку, созданную из pre-commit, в наш новый файл hooks. Чтобы проверить ловушку, сделайте вызов var_dump() в любом файле PHP, var_dump() файл в очередь и var_dump() его зафиксировать.

Вы даже не должны иметь права создавать сообщение фиксации до того, как появится сообщение об ошибке. Если вы затем обновите файл, чтобы убрать вызов var_dump() , вы должны увидеть сообщение об var_dump() , прежде чем сможете добавить сообщение фиксации, как показано на рисунке ниже.

StaticReview success

Завершение

И это все, что нужно для создания простых или мощных хитов Git с использованием одного из самых универсальных языков PHP. Я только столкнулся со Статическим Обзором благодаря постоянно бдительному Бруно Скворчу. Но я очень благодарен, что он предложил проверить это.

Теперь я могу выполнить еще одну, очень важную задачу разработки, используя мой любимый язык разработки программного обеспечения — PHP. Вы уже используете Static Review? Если это так, поделитесь своим опытом в комментариях. Мне интересно знать, как люди, более опытные, чем я, используют это.