Added param 'priority_path' (For all plugins) for control paths priority when we search plugin binary. Issue #104.

This commit is contained in:
Dmitry Khomutov 2017-07-19 10:26:51 +07:00
parent e1c6709639
commit 59837a8ff1
No known key found for this signature in database
GPG key ID: 7EB36C9576F9ECB9
27 changed files with 165 additions and 95 deletions

View file

@ -102,16 +102,16 @@ plugins.
```yml ```yml
test: # Test stage config for all branches test: # Test stage config for all branches
php_unit: php_cs_fixer:
allow_failures: 10 allowed_warnings: -1
success: # Success stage config for all branches success: # Success stage config for all branches
shell: ./notify shell: ./notify
branch-release: # Test config for release branch branch-release: # Test config for release branch
run-option: replace # This can be set to either before, after or replace run-option: replace # This can be set to either before, after or replace
test: test:
php_unit: php_cs_fixer:
allow_failures: 0 allowed_warnings: 0
branch-master: # Test config for release branch branch-master: # Test config for release branch
run-option: after # This can be set to either before, after or replace run-option: after # This can be set to either before, after or replace
success: success:
@ -125,7 +125,7 @@ When you have configured a branch eg "stable" in the project settings in the UI.
"branch-<branch>", in this case "branch-stable" to the `.php-censor.yml`. In this config, specify all stages and "branch-<branch>", in this case "branch-stable" to the `.php-censor.yml`. In this config, specify all stages and
plugins you wish to run. plugins you wish to run.
Also add a new config value `run-option`, that can heve 3 values: Also add a new config value `run-option`, that can have 3 values:
* `before` - will cause the branch specific plugins to run before the default ones. * `before` - will cause the branch specific plugins to run before the default ones.
* `after` - will cause the branch specific plugins to run after the default ones. * `after` - will cause the branch specific plugins to run after the default ones.

View file

@ -41,7 +41,7 @@ Troubleshooting
--------------- ---------------
If standard logging of PHP Censor is not enough, to get standard output from any command, including PHPUnit, edit If standard logging of PHP Censor is not enough, to get standard output from any command, including PHPUnit, edit
`BaseCommandExecutor::executeCommand()` to see what exactly is wrong `CommandExecutor::executeCommand()` to see what exactly is wrong
* Run `composer update` in phpunit plugin directory of PHP Censor to get all of its dependencies * Run `composer update` in phpunit plugin directory of PHP Censor to get all of its dependencies
* If phpunit is inside of the project's composer.json, it might interfere with PHP Censor's phpunit installation * If phpunit is inside of the project's composer.json, it might interfere with PHP Censor's phpunit installation
* Make sure you have XDebug installed.`The Xdebug extension is not loaded. No code coverage will be generated.` * Make sure you have XDebug installed.`The Xdebug extension is not loaded. No code coverage will be generated.`

View file

@ -109,7 +109,7 @@ class Builder implements LoggerAwareInterface
$pluginFactory = $this->buildPluginFactory($build); $pluginFactory = $this->buildPluginFactory($build);
$this->pluginExecutor = new Plugin\Util\Executor($pluginFactory, $this->buildLogger); $this->pluginExecutor = new Plugin\Util\Executor($pluginFactory, $this->buildLogger);
$executorClass = 'PHPCensor\Helper\UnixCommandExecutor'; $executorClass = 'PHPCensor\Helper\CommandExecutor';
$this->commandExecutor = new $executorClass( $this->commandExecutor = new $executorClass(
$this->buildLogger, $this->buildLogger,
ROOT_DIR, ROOT_DIR,
@ -291,14 +291,18 @@ class Builder implements LoggerAwareInterface
/** /**
* Find a binary required by a plugin. * Find a binary required by a plugin.
*
* @param string $binary * @param string $binary
* @param bool $quiet * @param bool $quiet Returns null instead of throwing an exception.
* @param string $priorityPath
* *
* @return null|string * @return null|string
*
* @throws \Exception when no binary has been found and $quiet is false.
*/ */
public function findBinary($binary, $quiet = false) public function findBinary($binary, $quiet = false, $priorityPath = 'local')
{ {
return $this->commandExecutor->findBinary($binary, $quiet); return $this->commandExecutor->findBinary($binary, $quiet, $priorityPath);
} }
/** /**

View file

@ -9,7 +9,7 @@ use Psr\Log\LogLevel;
/** /**
* Handles running system commands with variables. * Handles running system commands with variables.
*/ */
abstract class BaseCommandExecutor implements CommandExecutorInterface class CommandExecutor implements CommandExecutorInterface
{ {
/** /**
* @var BuildLogger * @var BuildLogger
@ -33,12 +33,14 @@ abstract class BaseCommandExecutor implements CommandExecutorInterface
/** /**
* The path which findBinary will look in. * The path which findBinary will look in.
*
* @var string * @var string
*/ */
protected $rootDir; protected $rootDir;
/** /**
* Current build path * Current build path
*
* @var string * @var string
*/ */
protected $buildPath; protected $buildPath;
@ -124,7 +126,9 @@ abstract class BaseCommandExecutor implements CommandExecutorInterface
/** /**
* Reads from array of streams as data becomes available. * Reads from array of streams as data becomes available.
*
* @param array $descriptors * @param array $descriptors
*
* @return string[] data read from each descriptor * @return string[] data read from each descriptor
*/ */
private function readAlternating(array $descriptors) private function readAlternating(array $descriptors)
@ -169,16 +173,69 @@ abstract class BaseCommandExecutor implements CommandExecutorInterface
} }
/** /**
* Find a binary required by a plugin * @param string $composerBin
*
* @param string $binary * @param string $binary
* @param bool $quiet *
* * @return false|string
* @throws Exception
*
* @return null|string
*/ */
public function findBinary($binary, $quiet = false) protected function findBinaryLocal($composerBin, $binary)
{
if (is_dir($composerBin) && is_file($composerBin . '/' . $binary)) {
$this->logger->logDebug(sprintf('Found in %s (local): %s', $composerBin, $binary));
return $composerBin . '/' . $binary;
}
return false;
}
/**
* @param string $binary
*
* @return false|string
*/
protected function findBinaryGlobal($binary)
{
if (is_file($this->rootDir . 'vendor/bin/' . $binary)) {
$this->logger->logDebug(sprintf('Found in %s (global): %s', 'vendor/bin', $binary));
return $this->rootDir . 'vendor/bin/' . $binary;
}
return false;
}
/**
* Uses 'which' to find a system binary by name
*
* @param string $binary
*
* @return false|string
*/
protected function findBinarySystem($binary)
{
$tempBinary = trim(shell_exec('which ' . $binary));
if (is_file($tempBinary)) {
$this->logger->logDebug(sprintf('Found in %s (system): %s', '', $binary));
return $tempBinary;
}
return false;
}
/**
* Find a binary required by a plugin.
*
* @param string $binary
* @param bool $quiet Returns null instead of throwing an exception.
* @param string $priorityPath
*
* @return null|string
*
* @throws \Exception when no binary has been found and $quiet is false.
*/
public function findBinary($binary, $quiet = false, $priorityPath = 'local')
{ {
$composerBin = $this->getComposerBinDir(realpath($this->buildPath)); $composerBin = $this->getComposerBinDir(realpath($this->buildPath));
@ -189,29 +246,42 @@ abstract class BaseCommandExecutor implements CommandExecutorInterface
foreach ($binary as $bin) { foreach ($binary as $bin) {
$this->logger->logDebug(sprintf('Looking for binary: %s', $bin)); $this->logger->logDebug(sprintf('Looking for binary: %s', $bin));
if (is_dir($composerBin) && is_file($composerBin . DIRECTORY_SEPARATOR . $bin)) { if ('system' === $priorityPath) {
$this->logger->logDebug(sprintf('Found in %s: %s', $composerBin, $bin)); if ($binarySystem = $this->findBinarySystem($bin)) {
return $binarySystem;
}
return $composerBin . DIRECTORY_SEPARATOR . $bin; if ($binaryLocal = $this->findBinaryLocal($composerBin, $bin)) {
} return $binaryLocal;
}
if (is_file($this->rootDir . DIRECTORY_SEPARATOR . $bin)) { if ($binaryGlobal = $this->findBinaryGlobal($bin)) {
$this->logger->logDebug(sprintf('Found in %s: %s', 'root', $bin)); return $binaryGlobal;
}
} elseif ('global' === $priorityPath) {
if ($binaryGlobal = $this->findBinaryGlobal($bin)) {
return $binaryGlobal;
}
return $this->rootDir . DIRECTORY_SEPARATOR . $bin; if ($binaryLocal = $this->findBinaryLocal($composerBin, $bin)) {
} return $binaryLocal;
}
if (is_file($this->rootDir . 'vendor' . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . $bin)) { if ($binarySystem = $this->findBinarySystem($bin)) {
$this->logger->logDebug(sprintf('Found in %s: %s', 'vendor/bin', $bin)); return $binarySystem;
}
} else {
if ($binaryLocal = $this->findBinaryLocal($composerBin, $bin)) {
return $binaryLocal;
}
return $this->rootDir . 'vendor' . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . $bin; if ($binaryGlobal = $this->findBinaryGlobal($bin)) {
} return $binaryGlobal;
}
$findCmdResult = $this->findGlobalBinary($bin); if ($binarySystem = $this->findBinarySystem($bin)) {
if (is_file($findCmdResult)) { return $binarySystem;
$this->logger->logDebug(sprintf('Found in %s: %s', '', $bin)); }
return $findCmdResult;
} }
} }
@ -222,17 +292,12 @@ abstract class BaseCommandExecutor implements CommandExecutorInterface
throw new Exception(sprintf('Could not find %s', implode('/', $binary))); throw new Exception(sprintf('Could not find %s', implode('/', $binary)));
} }
/**
* Find a binary which is installed globally on the system
* @param string $binary
* @return null|string
*/
abstract protected function findGlobalBinary($binary);
/** /**
* Try to load the composer.json file in the building project * Try to load the composer.json file in the building project
* If the bin-dir is configured, return the full path to it * If the bin-dir is configured, return the full path to it
*
* @param string $path Current build path * @param string $path Current build path
*
* @return string|null * @return string|null
*/ */
public function getComposerBinDir($path) public function getComposerBinDir($path)
@ -254,6 +319,7 @@ abstract class BaseCommandExecutor implements CommandExecutorInterface
/** /**
* Set the buildPath property. * Set the buildPath property.
*
* @param string $path * @param string $path
*/ */
public function setBuildPath($path) public function setBuildPath($path)

View file

@ -21,18 +21,20 @@ interface CommandExecutorInterface
/** /**
* Find a binary required by a plugin. * Find a binary required by a plugin.
* *
* @param string $binary * @param string $binary
* @param bool $quiet Returns null instead of throwing an execption. * @param bool $quiet Returns null instead of throwing an exception.
* @param string $priorityPath
* *
* @return null|string * @return null|string
* *
* @throws \Exception when no binary has been found and $quiet is false. * @throws \Exception when no binary has been found and $quiet is false.
*/ */
public function findBinary($binary, $quiet = false); public function findBinary($binary, $quiet = false, $priorityPath = 'local');
/** /**
* Set the buildPath property. * Set the buildPath property.
*
* @param string $path * @param string $path
*/ */
public function setBuildPath($path); public function setBuildPath($path);

View file

@ -1,19 +0,0 @@
<?php
namespace PHPCensor\Helper;
/**
* Unix/Linux specific extension of the CommandExecutor class.
*/
class UnixCommandExecutor extends BaseCommandExecutor
{
/**
* Uses 'which' to find a system binary by name.
* @param string $binary
* @return null|string
*/
protected function findGlobalBinary($binary)
{
return trim(shell_exec('which ' . $binary));
}
}

View file

@ -31,6 +31,11 @@ abstract class Plugin
*/ */
protected $options; protected $options;
/**
* @var string
*/
protected $priorityPath = 'local';
/** /**
* @param Builder $builder * @param Builder $builder
* @param Build $build * @param Build $build
@ -42,9 +47,28 @@ abstract class Plugin
$this->build = $build; $this->build = $build;
$this->options = $options; $this->options = $options;
if (!empty($options['priority_path']) && in_array($options['priority_path'], ['global', 'system'])) {
$this->priorityPath = $options['priority_path'];
}
$this->builder->logDebug('Plugin options: ' . json_encode($options)); $this->builder->logDebug('Plugin options: ' . json_encode($options));
} }
/**
* Find a binary required by a plugin.
*
* @param string $binary
* @param bool $quiet Returns null instead of throwing an exception.
*
* @return null|string
*
* @throws \Exception when no binary has been found and $quiet is false.
*/
public function findBinary($binary, $quiet = false)
{
return $this->builder->findBinary($binary, $quiet, $this->priorityPath);
}
/** /**
* @return Build * @return Build
*/ */

View file

@ -49,7 +49,7 @@ class Atoum extends Plugin
if (isset($options['executable'])) { if (isset($options['executable'])) {
$this->executable = $this->builder->buildPath . DIRECTORY_SEPARATOR.$options['executable']; $this->executable = $this->builder->buildPath . DIRECTORY_SEPARATOR.$options['executable'];
} else { } else {
$this->executable = $this->builder->findBinary('atoum'); $this->executable = $this->findBinary('atoum');
} }
if (isset($options['args'])) { if (isset($options['args'])) {

View file

@ -37,7 +37,7 @@ class Behat extends Plugin
if (isset($options['executable'])) { if (isset($options['executable'])) {
$this->executable = $options['executable']; $this->executable = $options['executable'];
} else { } else {
$this->executable = $this->builder->findBinary('behat'); $this->executable = $this->findBinary('behat');
} }
if (!empty($options['features'])) { if (!empty($options['features'])) {

View file

@ -114,7 +114,7 @@ class Codeception extends Plugin implements ZeroConfigPluginInterface
*/ */
protected function runConfigFile($configPath) protected function runConfigFile($configPath)
{ {
$codeception = $this->builder->findBinary('codecept'); $codeception = $this->findBinary('codecept');
if (!$codeception) { if (!$codeception) {
$this->builder->logFailure(sprintf('Could not find %s', 'codecept')); $this->builder->logFailure(sprintf('Could not find %s', 'codecept'));

View file

@ -94,7 +94,7 @@ class Composer extends Plugin implements ZeroConfigPluginInterface
*/ */
public function execute() public function execute()
{ {
$composerLocation = $this->builder->findBinary(['composer', 'composer.phar']); $composerLocation = $this->findBinary(['composer', 'composer.phar']);
$cmd = $composerLocation . ' --no-ansi --no-interaction '; $cmd = $composerLocation . ' --no-ansi --no-interaction ';
if ($this->preferDist) { if ($this->preferDist) {

View file

@ -37,7 +37,7 @@ class Grunt extends Plugin
$path = $this->builder->buildPath; $path = $this->builder->buildPath;
$this->directory = $path; $this->directory = $path;
$this->task = null; $this->task = null;
$this->grunt = $this->builder->findBinary('grunt'); $this->grunt = $this->findBinary('grunt');
$this->gruntfile = 'Gruntfile.js'; $this->gruntfile = 'Gruntfile.js';
// Handle options: // Handle options:

View file

@ -37,7 +37,7 @@ class Gulp extends Plugin
$path = $this->builder->buildPath; $path = $this->builder->buildPath;
$this->directory = $path; $this->directory = $path;
$this->task = null; $this->task = null;
$this->gulp = $this->builder->findBinary('gulp'); $this->gulp = $this->findBinary('gulp');
$this->gulpfile = 'gulpfile.js'; $this->gulpfile = 'gulpfile.js';
// Handle options: // Handle options:

View file

@ -57,7 +57,7 @@ class Lint extends Plugin
$this->builder->quiet = true; $this->builder->quiet = true;
$success = true; $success = true;
$php = $this->builder->findBinary('php'); $php = $this->findBinary('php');
foreach ($this->directories as $dir) { foreach ($this->directories as $dir) {
if (!$this->lintDirectory($php, $dir)) { if (!$this->lintDirectory($php, $dir)) {

View file

@ -77,7 +77,7 @@ class Pdepend extends Plugin
throw new \Exception(sprintf('The location %s is not writable or does not exist.', $this->location)); throw new \Exception(sprintf('The location %s is not writable or does not exist.', $this->location));
} }
$pdepend = $this->builder->findBinary('pdepend'); $pdepend = $this->findBinary('pdepend');
$cmd = $pdepend . ' --summary-xml="%s" --jdepend-chart="%s" --overview-pyramid="%s" %s "%s"'; $cmd = $pdepend . ' --summary-xml="%s" --jdepend-chart="%s" --overview-pyramid="%s" %s "%s"';

View file

@ -70,7 +70,7 @@ class Phing extends Plugin
*/ */
public function execute() public function execute()
{ {
$phingExecutable = $this->builder->findBinary('phing'); $phingExecutable = $this->findBinary('phing');
$cmd[] = $phingExecutable . ' -f ' . $this->getBuildFilePath(); $cmd[] = $phingExecutable . ' -f ' . $this->getBuildFilePath();

View file

@ -171,7 +171,7 @@ class PhpCodeSniffer extends Plugin implements ZeroConfigPluginInterface
{ {
list($ignore, $standard, $suffixes, $severity, $errorSeverity, $warningSeverity) = $this->getFlags(); list($ignore, $standard, $suffixes, $severity, $errorSeverity, $warningSeverity) = $this->getFlags();
$phpcs = $this->builder->findBinary('phpcs'); $phpcs = $this->findBinary('phpcs');
$this->builder->logExecOutput(false); $this->builder->logExecOutput(false);

View file

@ -97,7 +97,7 @@ class PhpCpd extends Plugin implements ZeroConfigPluginInterface
$ignore = $ignore . $filesToIgnore; $ignore = $ignore . $filesToIgnore;
} }
$phpcpd = $this->builder->findBinary('phpcpd'); $phpcpd = $this->findBinary('phpcpd');
$tmpFileName = tempnam('/tmp', 'phpcpd'); $tmpFileName = tempnam('/tmp', 'phpcpd');

View file

@ -89,7 +89,7 @@ class PhpCsFixer extends Plugin
$directory = '.'; $directory = '.';
} }
$phpCsFixer = $this->builder->findBinary('php-cs-fixer'); $phpCsFixer = $this->findBinary('php-cs-fixer');
$cmd = $phpCsFixer . ' fix ' . $directory . ' %s'; $cmd = $phpCsFixer . ' fix ' . $directory . ' %s';
$success = $this->builder->executeCommand($cmd, $this->args); $success = $this->builder->executeCommand($cmd, $this->args);

View file

@ -97,7 +97,7 @@ class PhpDocblockChecker extends Plugin implements ZeroConfigPluginInterface
public function execute() public function execute()
{ {
// Check that the binary exists: // Check that the binary exists:
$checker = $this->builder->findBinary('phpdoccheck'); $checker = $this->findBinary('phpdoccheck');
// Build ignore string: // Build ignore string:
$ignore = ''; $ignore = '';

View file

@ -74,7 +74,7 @@ class PhpLoc extends Plugin implements ZeroConfigPluginInterface
$ignore = implode('', $ignore); $ignore = implode('', $ignore);
} }
$phploc = $this->builder->findBinary('phploc'); $phploc = $this->findBinary('phploc');
$success = $this->builder->executeCommand($phploc . ' %s "%s"', $ignore, $this->directory); $success = $this->builder->executeCommand($phploc . ' %s "%s"', $ignore, $this->directory);
$output = $this->builder->getLastOutput(); $output = $this->builder->getLastOutput();

View file

@ -103,7 +103,7 @@ class PhpMessDetector extends Plugin implements ZeroConfigPluginInterface
return false; return false;
} }
$phpmdBinaryPath = $this->builder->findBinary('phpmd'); $phpmdBinaryPath = $this->findBinary('phpmd');
$this->executePhpMd($phpmdBinaryPath); $this->executePhpMd($phpmdBinaryPath);

View file

@ -94,7 +94,7 @@ class PhpParallelLint extends Plugin implements ZeroConfigPluginInterface
{ {
list($ignore) = $this->getFlags(); list($ignore) = $this->getFlags();
$phplint = $this->builder->findBinary('parallel-lint'); $phplint = $this->findBinary('parallel-lint');
$cmd = $phplint . ' -e %s' . ' %s "%s"'; $cmd = $phplint . ' -e %s' . ' %s "%s"';
$success = $this->builder->executeCommand( $success = $this->builder->executeCommand(

View file

@ -28,7 +28,7 @@ class PhpSpec extends Plugin
$curdir = getcwd(); $curdir = getcwd();
chdir($this->builder->buildPath); chdir($this->builder->buildPath);
$phpspec = $this->builder->findBinary(['phpspec', 'phpspec.php']); $phpspec = $this->findBinary(['phpspec', 'phpspec.php']);
$success = $this->builder->executeCommand($phpspec . ' --format=junit --no-code-generation run'); $success = $this->builder->executeCommand($phpspec . ' --format=junit --no-code-generation run');
$output = $this->builder->getLastOutput(); $output = $this->builder->getLastOutput();

View file

@ -119,7 +119,7 @@ class PhpUnit extends Plugin implements ZeroConfigPluginInterface
$options->removeArgument('configuration'); $options->removeArgument('configuration');
$arguments = $this->builder->interpolate($options->buildArgumentString()); $arguments = $this->builder->interpolate($options->buildArgumentString());
$cmd = $this->builder->findBinary('phpunit') . ' %s "%s"'; $cmd = $this->findBinary('phpunit') . ' %s "%s"';
$success = $this->builder->executeCommand($cmd, $arguments, $directory); $success = $this->builder->executeCommand($cmd, $arguments, $directory);
$this->processResults($jsonFile); $this->processResults($jsonFile);
@ -149,7 +149,7 @@ class PhpUnit extends Plugin implements ZeroConfigPluginInterface
$options->addArgument('configuration', $buildPath . $configFile); $options->addArgument('configuration', $buildPath . $configFile);
$arguments = $this->builder->interpolate($options->buildArgumentString()); $arguments = $this->builder->interpolate($options->buildArgumentString());
$cmd = $this->builder->findBinary('phpunit') . ' %s %s'; $cmd = $this->findBinary('phpunit') . ' %s %s';
$success = $this->builder->executeCommand($cmd, $arguments, $options->getTestsPath()); $success = $this->builder->executeCommand($cmd, $arguments, $options->getTestsPath());
$this->processResults($jsonFile); $this->processResults($jsonFile);

View file

@ -128,7 +128,7 @@ class XMPP extends Plugin
*/ */
public function execute() public function execute()
{ {
$sendxmpp = $this->builder->findBinary('sendxmpp'); $sendxmpp = $this->findBinary('sendxmpp');
/* /*
* Without recipients we can't send notification * Without recipients we can't send notification

View file

@ -2,12 +2,12 @@
namespace Tests\PHPCensor\Helper; namespace Tests\PHPCensor\Helper;
use PHPCensor\Helper\UnixCommandExecutor; use PHPCensor\Helper\CommandExecutor;
class CommandExecutorTest extends \PHPUnit_Framework_TestCase class CommandExecutorTest extends \PHPUnit_Framework_TestCase
{ {
/** /**
* @var UnixCommandExecutor * @var CommandExecutor
*/ */
protected $testedExecutor; protected $testedExecutor;
@ -17,7 +17,7 @@ class CommandExecutorTest extends \PHPUnit_Framework_TestCase
$mockBuildLogger = $this->prophesize('PHPCensor\Logging\BuildLogger'); $mockBuildLogger = $this->prophesize('PHPCensor\Logging\BuildLogger');
$class = 'PHPCensor\Helper\UnixCommandExecutor'; $class = 'PHPCensor\Helper\CommandExecutor';
$this->testedExecutor = new $class($mockBuildLogger->reveal(), __DIR__); $this->testedExecutor = new $class($mockBuildLogger->reveal(), __DIR__);
} }
@ -67,13 +67,6 @@ EOD;
$this->assertEquals($data, trim($this->testedExecutor->getLastError())); $this->assertEquals($data, trim($this->testedExecutor->getLastError()));
} }
public function testFindBinary_ReturnsPathInSpecifiedRoot()
{
$thisFileName = "CommandExecutorTest.php";
$returnValue = $this->testedExecutor->findBinary($thisFileName, true);
$this->assertEquals(__DIR__ . DIRECTORY_SEPARATOR . $thisFileName, $returnValue);
}
/** /**
* @expectedException \Exception * @expectedException \Exception
* @expectedMessageRegex WorldWidePeace * @expectedMessageRegex WorldWidePeace