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
test: # Test stage config for all branches
php_unit:
allow_failures: 10
php_cs_fixer:
allowed_warnings: -1
success: # Success stage config for all branches
shell: ./notify
branch-release: # Test config for release branch
run-option: replace # This can be set to either before, after or replace
test:
php_unit:
allow_failures: 0
php_cs_fixer:
allowed_warnings: 0
branch-master: # Test config for release branch
run-option: after # This can be set to either before, after or replace
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
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.
* `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
`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
* 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.`

View file

@ -109,7 +109,7 @@ class Builder implements LoggerAwareInterface
$pluginFactory = $this->buildPluginFactory($build);
$this->pluginExecutor = new Plugin\Util\Executor($pluginFactory, $this->buildLogger);
$executorClass = 'PHPCensor\Helper\UnixCommandExecutor';
$executorClass = 'PHPCensor\Helper\CommandExecutor';
$this->commandExecutor = new $executorClass(
$this->buildLogger,
ROOT_DIR,
@ -291,14 +291,18 @@ class Builder implements LoggerAwareInterface
/**
* Find a binary required by a plugin.
*
* @param string $binary
* @param bool $quiet
* @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)
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.
*/
abstract class BaseCommandExecutor implements CommandExecutorInterface
class CommandExecutor implements CommandExecutorInterface
{
/**
* @var BuildLogger
@ -33,12 +33,14 @@ abstract class BaseCommandExecutor implements CommandExecutorInterface
/**
* The path which findBinary will look in.
*
* @var string
*/
protected $rootDir;
/**
* Current build path
*
* @var string
*/
protected $buildPath;
@ -124,7 +126,9 @@ abstract class BaseCommandExecutor implements CommandExecutorInterface
/**
* Reads from array of streams as data becomes available.
*
* @param array $descriptors
*
* @return string[] data read from each descriptor
*/
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 bool $quiet
*
* @throws Exception
*
* @return null|string
*
* @return false|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));
@ -189,29 +246,42 @@ abstract class BaseCommandExecutor implements CommandExecutorInterface
foreach ($binary as $bin) {
$this->logger->logDebug(sprintf('Looking for binary: %s', $bin));
if (is_dir($composerBin) && is_file($composerBin . DIRECTORY_SEPARATOR . $bin)) {
$this->logger->logDebug(sprintf('Found in %s: %s', $composerBin, $bin));
if ('system' === $priorityPath) {
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)) {
$this->logger->logDebug(sprintf('Found in %s: %s', 'root', $bin));
if ($binaryGlobal = $this->findBinaryGlobal($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)) {
$this->logger->logDebug(sprintf('Found in %s: %s', 'vendor/bin', $bin));
if ($binarySystem = $this->findBinarySystem($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 (is_file($findCmdResult)) {
$this->logger->logDebug(sprintf('Found in %s: %s', '', $bin));
return $findCmdResult;
if ($binarySystem = $this->findBinarySystem($bin)) {
return $binarySystem;
}
}
}
@ -222,17 +292,12 @@ abstract class BaseCommandExecutor implements CommandExecutorInterface
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
* If the bin-dir is configured, return the full path to it
*
* @param string $path Current build path
*
* @return string|null
*/
public function getComposerBinDir($path)
@ -254,6 +319,7 @@ abstract class BaseCommandExecutor implements CommandExecutorInterface
/**
* Set the buildPath property.
*
* @param string $path
*/
public function setBuildPath($path)

View file

@ -21,18 +21,20 @@ interface CommandExecutorInterface
/**
* Find a binary required by a plugin.
*
*
* @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
*
* @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.
*
* @param string $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;
/**
* @var string
*/
protected $priorityPath = 'local';
/**
* @param Builder $builder
* @param Build $build
@ -42,9 +47,28 @@ abstract class Plugin
$this->build = $build;
$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));
}
/**
* 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
*/

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -57,7 +57,7 @@ class Lint extends Plugin
$this->builder->quiet = true;
$success = true;
$php = $this->builder->findBinary('php');
$php = $this->findBinary('php');
foreach ($this->directories as $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));
}
$pdepend = $this->builder->findBinary('pdepend');
$pdepend = $this->findBinary('pdepend');
$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()
{
$phingExecutable = $this->builder->findBinary('phing');
$phingExecutable = $this->findBinary('phing');
$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();
$phpcs = $this->builder->findBinary('phpcs');
$phpcs = $this->findBinary('phpcs');
$this->builder->logExecOutput(false);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -28,7 +28,7 @@ class PhpSpec extends Plugin
$curdir = getcwd();
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');
$output = $this->builder->getLastOutput();

View file

@ -119,7 +119,7 @@ class PhpUnit extends Plugin implements ZeroConfigPluginInterface
$options->removeArgument('configuration');
$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);
$this->processResults($jsonFile);
@ -149,7 +149,7 @@ class PhpUnit extends Plugin implements ZeroConfigPluginInterface
$options->addArgument('configuration', $buildPath . $configFile);
$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());
$this->processResults($jsonFile);

View file

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

View file

@ -2,12 +2,12 @@
namespace Tests\PHPCensor\Helper;
use PHPCensor\Helper\UnixCommandExecutor;
use PHPCensor\Helper\CommandExecutor;
class CommandExecutorTest extends \PHPUnit_Framework_TestCase
{
/**
* @var UnixCommandExecutor
* @var CommandExecutor
*/
protected $testedExecutor;
@ -17,7 +17,7 @@ class CommandExecutorTest extends \PHPUnit_Framework_TestCase
$mockBuildLogger = $this->prophesize('PHPCensor\Logging\BuildLogger');
$class = 'PHPCensor\Helper\UnixCommandExecutor';
$class = 'PHPCensor\Helper\CommandExecutor';
$this->testedExecutor = new $class($mockBuildLogger->reveal(), __DIR__);
}
@ -67,13 +67,6 @@ EOD;
$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
* @expectedMessageRegex WorldWidePeace