diff --git a/PHPCI/Model/Build.php b/PHPCI/Model/Build.php index 20ff6a34..c5b0dc1a 100644 --- a/PHPCI/Model/Build.php +++ b/PHPCI/Model/Build.php @@ -88,20 +88,73 @@ class Build extends BuildBase */ protected function handleConfig(Builder $builder, $buildPath) { + $build_config = null; + + // Try phpci.yml first: if (is_file($buildPath . '/phpci.yml')) { $build_config = file_get_contents($buildPath . '/phpci.yml'); } - if (!is_file($buildPath . '/phpci.yml') || !$build_config) { + // Try getting the project build config from the database: + if (empty($build_config)) { $build_config = $this->getProject()->getBuildConfig(); - if (!$build_config) { - $builder->logFailure('Project does not contain a phpci.yml file.'); - return false; + } + + // Fall back to zero config plugins: + if (empty($build_config)) { + $build_config = $this->getZeroConfigPlugins($builder); + } + + if (is_string($build_config)) { + $yamlParser = new YamlParser(); + $build_config = $yamlParser->parse($build_config); + } + + $builder->setConfigArray($build_config); + return true; + } + + protected function getZeroConfigPlugins(Builder $builder) + { + $pluginDir = PHPCI_DIR . 'PHPCI/Plugin/'; + $dir = new \DirectoryIterator($pluginDir); + + $config = array( + 'build_settings' => array( + 'ignore' => array( + 'vendor/', + ) + ) + ); + + foreach ($dir as $item) { + if ($item->isDot()) { + continue; + } + + if (!$item->isFile()) { + continue; + } + + if ($item->getExtension() != 'php') { + continue; + } + + $className = '\PHPCI\Plugin\\'.$item->getBasename('.php'); + + $reflectedPlugin = new \ReflectionClass($className); + + if (!$reflectedPlugin->implementsInterface('\PHPCI\ZeroConfigPlugin')) { + continue; + } + + foreach (array('setup', 'test', 'complete', 'success', 'failure') as $stage) { + if ($className::canExecute($stage, $builder, $this)) { + $config[$stage][$className] = array(); + } } } - $yamlParser = new YamlParser(); - $builder->setConfigArray($yamlParser->parse($build_config)); - return $builder->getConfig('build_settings'); + return $config; } } diff --git a/PHPCI/Plugin/Composer.php b/PHPCI/Plugin/Composer.php index d40ac100..70462eba 100644 --- a/PHPCI/Plugin/Composer.php +++ b/PHPCI/Plugin/Composer.php @@ -9,6 +9,7 @@ namespace PHPCI\Plugin; +use PHPCI; use PHPCI\Builder; use PHPCI\Model\Build; @@ -18,13 +19,24 @@ use PHPCI\Model\Build; * @package PHPCI * @subpackage Plugins */ -class Composer implements \PHPCI\Plugin +class Composer implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin { protected $directory; protected $action; protected $preferDist; protected $phpci; + public static function canExecute($stage, Builder $builder, Build $build) + { + $path = $builder->buildPath . '/composer.json'; + + if (file_exists($path) && $stage == 'setup') { + return true; + } + + return false; + } + public function __construct(Builder $phpci, Build $build, array $options = array()) { $path = $phpci->buildPath; diff --git a/PHPCI/Plugin/Lint.php b/PHPCI/Plugin/Lint.php index ebab146e..73b4beaf 100644 --- a/PHPCI/Plugin/Lint.php +++ b/PHPCI/Plugin/Lint.php @@ -9,6 +9,7 @@ namespace PHPCI\Plugin; +use PHPCI; use PHPCI\Builder; use PHPCI\Model\Build; @@ -18,7 +19,7 @@ use PHPCI\Model\Build; * @package PHPCI * @subpackage Plugins */ -class Lint implements \PHPCI\Plugin +class Lint implements PHPCI\Plugin { protected $directories; protected $recursive = true; diff --git a/PHPCI/Plugin/PhpCodeSniffer.php b/PHPCI/Plugin/PhpCodeSniffer.php index 2f0d7592..b942e44b 100755 --- a/PHPCI/Plugin/PhpCodeSniffer.php +++ b/PHPCI/Plugin/PhpCodeSniffer.php @@ -9,6 +9,7 @@ namespace PHPCI\Plugin; +use PHPCI; use PHPCI\Builder; use PHPCI\Model\Build; @@ -18,7 +19,7 @@ use PHPCI\Model\Build; * @package PHPCI * @subpackage Plugins */ -class PhpCodeSniffer implements \PHPCI\Plugin +class PhpCodeSniffer implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin { /** * @var \PHPCI\Builder @@ -50,6 +51,16 @@ class PhpCodeSniffer implements \PHPCI\Plugin */ protected $encoding; + /** + * @var int + */ + protected $allowed_errors; + + /** + * @var int + */ + protected $allowed_warnings; + /** * @var string, based on the assumption the root may not hold the code to be * tested, exteds the base path @@ -61,21 +72,33 @@ class PhpCodeSniffer implements \PHPCI\Plugin */ protected $ignore; + public static function canExecute($stage, Builder $builder, Build $build) + { + if ($stage == 'test') { + return true; + } + + return false; + } + /** * @param \PHPCI\Builder $phpci + * @param \PHPCI\Model\Build $build * @param array $options */ public function __construct(Builder $phpci, Build $build, array $options = array()) { - $this->phpci = $phpci; - $this->build = $build; - $this->suffixes = array('php'); - $this->directory = $phpci->buildPath; - $this->standard = 'PSR2'; - $this->tab_width = ''; - $this->encoding = ''; - $this->path = ''; - $this->ignore = $this->phpci->ignore; + $this->phpci = $phpci; + $this->build = $build; + $this->suffixes = array('php'); + $this->directory = $phpci->buildPath; + $this->standard = 'PSR2'; + $this->tab_width = ''; + $this->encoding = ''; + $this->path = ''; + $this->ignore = $this->phpci->ignore; + $this->allowed_warnings = -1; + $this->allowed_errors = -1; if (isset($options['suffixes'])) { $this->suffixes = (array)$options['suffixes']; @@ -104,6 +127,14 @@ class PhpCodeSniffer implements \PHPCI\Plugin if (isset($options['ignore'])) { $this->ignore = $options['ignore']; } + + if (isset($options['allowed_warnings'])) { + $this->allowed_warnings = (int)$options['allowed_warnings']; + } + + if (isset($options['allowed_errors'])) { + $this->allowed_errors = (int)$options['allowed_errors']; + } } /** @@ -121,7 +152,7 @@ class PhpCodeSniffer implements \PHPCI\Plugin } $cmd = $phpcs . ' --report=emacs %s %s %s %s %s "%s"'; - $success = $this->phpci->executeCommand( + $this->phpci->executeCommand( $cmd, $standard, $suffixes, @@ -133,14 +164,25 @@ class PhpCodeSniffer implements \PHPCI\Plugin $output = $this->phpci->getLastOutput(); + $success = true; $matches = array(); if (preg_match_all('/\: warning \-/', $output, $matches)) { - $this->build->storeMeta('phpcs-warnings', count($matches[0])); + $warnings = count($matches[0]); + $this->build->storeMeta('phpcs-warnings', $warnings); + + if ($this->allowed_warnings != -1 && $warnings > $this->allowed_warnings) { + $success = false; + } } $matches = array(); if (preg_match_all('/\: error \-/', $output, $matches)) { - $this->build->storeMeta('phpcs-errors', count($matches[0])); + $errors = count($matches[0]); + $this->build->storeMeta('phpcs-errors', $errors); + + if ($this->allowed_errors != -1 && $errors > $this->allowed_errors) { + $success = false; + } } return $success; diff --git a/PHPCI/Plugin/PhpLoc.php b/PHPCI/Plugin/PhpLoc.php index 809b6409..000b82cc 100644 --- a/PHPCI/Plugin/PhpLoc.php +++ b/PHPCI/Plugin/PhpLoc.php @@ -9,6 +9,7 @@ namespace PHPCI\Plugin; +use PHPCI; use PHPCI\Builder; use PHPCI\Model\Build; @@ -18,7 +19,7 @@ use PHPCI\Model\Build; * @package PHPCI * @subpackage Plugins */ -class PhpLoc implements \PHPCI\Plugin +class PhpLoc implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin { /** * @var string @@ -29,6 +30,15 @@ class PhpLoc implements \PHPCI\Plugin */ protected $phpci; + public static function canExecute($stage, Builder $builder, Build $build) + { + if ($stage == 'test') { + return true; + } + + return false; + } + public function __construct(Builder $phpci, Build $build, array $options = array()) { $this->phpci = $phpci; diff --git a/PHPCI/Plugin/PhpMessDetector.php b/PHPCI/Plugin/PhpMessDetector.php index 06bc72e8..f68d7aec 100755 --- a/PHPCI/Plugin/PhpMessDetector.php +++ b/PHPCI/Plugin/PhpMessDetector.php @@ -9,6 +9,7 @@ namespace PHPCI\Plugin; +use PHPCI; use PHPCI\Builder; use PHPCI\Model\Build; @@ -18,7 +19,7 @@ use PHPCI\Model\Build; * @package PHPCI * @subpackage Plugins */ -class PhpMessDetector implements \PHPCI\Plugin +class PhpMessDetector implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin { /** * @var \PHPCI\Builder @@ -49,6 +50,15 @@ class PhpMessDetector implements \PHPCI\Plugin */ protected $rules; + public static function canExecute($stage, Builder $builder, Build $build) + { + if ($stage == 'test') { + return true; + } + + return false; + } + /** * @param \PHPCI\Builder $phpci * @param array $options @@ -61,11 +71,16 @@ class PhpMessDetector implements \PHPCI\Plugin $this->ignore = $phpci->ignore; $this->path = ''; $this->rules = array('codesize', 'unusedcode', 'naming'); + $this->allowed_warnings = -1; if (!empty($options['path'])) { $this->path = $options['path']; } + if (array_key_exists('allowed_warnings', $options)) { + $this->allowed_warnings = (int)$options['allowed_warnings']; + } + foreach (array('rules', 'ignore', 'suffixes') as $key) { $this->overrideSetting($options, $key); } @@ -110,7 +125,7 @@ class PhpMessDetector implements \PHPCI\Plugin } $cmd = $phpmd . ' "%s" text %s %s %s'; - $success = $this->phpci->executeCommand( + $this->phpci->executeCommand( $cmd, $path, implode(',', $this->rules), @@ -118,9 +133,14 @@ class PhpMessDetector implements \PHPCI\Plugin $suffixes ); + $success = true; $errors = count(array_filter(explode(PHP_EOL, trim($this->phpci->getLastOutput())))); $this->build->storeMeta('phpmd-warnings', $errors); + if ($this->allowed_warnings != -1 && $errors > $this->allowed_warnings) { + $success = false; + } + return $success; } diff --git a/PHPCI/Plugin/PhpSpec.php b/PHPCI/Plugin/PhpSpec.php index 02aebba7..843017b9 100644 --- a/PHPCI/Plugin/PhpSpec.php +++ b/PHPCI/Plugin/PhpSpec.php @@ -9,6 +9,7 @@ namespace PHPCI\Plugin; +use PHPCI; use PHPCI\Builder; use PHPCI\Model\Build; @@ -18,7 +19,7 @@ use PHPCI\Model\Build; * @package PHPCI * @subpackage Plugins */ -class PhpSpec implements \PHPCI\Plugin +class PhpSpec implements PHPCI\Plugin { protected $phpci; diff --git a/PHPCI/Plugin/PhpUnit.php b/PHPCI/Plugin/PhpUnit.php index fde1b2fa..ab0cfc58 100755 --- a/PHPCI/Plugin/PhpUnit.php +++ b/PHPCI/Plugin/PhpUnit.php @@ -9,6 +9,7 @@ namespace PHPCI\Plugin; +use PHPCI; use PHPCI\Builder; use PHPCI\Model\Build; @@ -18,7 +19,7 @@ use PHPCI\Model\Build; * @package PHPCI * @subpackage Plugins */ -class PhpUnit implements \PHPCI\Plugin +class PhpUnit implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin { protected $args; protected $phpci; @@ -46,9 +47,44 @@ class PhpUnit implements \PHPCI\Plugin */ protected $xmlConfigFile; + public static function canExecute($stage, Builder $builder, Build $build) + { + if ($stage == 'test' && !is_null(self::findConfigFile($builder->buildPath))) { + return true; + } + + return false; + } + + public static function findConfigFile($buildPath) + { + if (file_exists($buildPath . '/phpunit.xml')) { + return $buildPath . '/phpunit.xml'; + } + + if (file_exists($buildPath . '/tests/phpunit.xml')) { + return $buildPath . '/tests/phpunit.xml'; + } + + if (file_exists($buildPath . '/phpunit.xml.dist')) { + return $buildPath . '/phpunit.xml.dist'; + } + + if (file_exists($buildPath . '/tests/phpunit.xml.dist')) { + return $buildPath . '/tests/phpunit.xml.dist'; + } + + return null; + } + public function __construct(Builder $phpci, Build $build, array $options = array()) { - $this->phpci = $phpci; + $this->phpci = $phpci; + + if (!count($options)) { + $this->runFrom = $phpci->buildPath; + $this->xmlConfigFile = self::findConfigFile($phpci->buildPath); + } if (isset($options['directory'])) { $this->directory = $options['directory']; diff --git a/PHPCI/ZeroConfigPlugin.php b/PHPCI/ZeroConfigPlugin.php new file mode 100644 index 00000000..b779cf5e --- /dev/null +++ b/PHPCI/ZeroConfigPlugin.php @@ -0,0 +1,21 @@ + + */ +interface ZeroConfigPlugin +{ + public static function canExecute($stage, Builder $builder, Build $build); +}