diff --git a/PHPCI/Builder.php b/PHPCI/Builder.php index 4547564a..ccb78c6b 100644 --- a/PHPCI/Builder.php +++ b/PHPCI/Builder.php @@ -47,11 +47,6 @@ class Builder implements LoggerAwareInterface */ protected $directory; - /** - * @var bool - */ - protected $success = true; - /** * @var bool */ @@ -192,7 +187,7 @@ class Builder implements LoggerAwareInterface $this->build->setStarted(new \DateTime()); $this->store->save($this->build); $this->build->sendStatusPostback(); - $this->success = true; + $success = true; try { // Set up the build: @@ -200,12 +195,12 @@ class Builder implements LoggerAwareInterface // Run the core plugin stages: foreach (array('setup', 'test') as $stage) { - $this->success &= $this->pluginExecutor->executePlugins($this->config, $stage); + $success &= $this->pluginExecutor->executePlugins($this->config, $stage); } // Set the status so this can be used by complete, success and failure // stages. - if ($this->success) { + if ($success) { $this->build->setStatus(Build::STATUS_SUCCESS); } else { $this->build->setStatus(Build::STATUS_FAILED); @@ -214,7 +209,7 @@ class Builder implements LoggerAwareInterface // Complete stage plugins are always run $this->pluginExecutor->executePlugins($this->config, 'complete'); - if ($this->success) { + if ($success) { $this->pluginExecutor->executePlugins($this->config, 'success'); $this->buildLogger->logSuccess('BUILD SUCCESSFUL!'); } else { diff --git a/PHPCI/Command/InstallCommand.php b/PHPCI/Command/InstallCommand.php index e6432103..aac34dca 100644 --- a/PHPCI/Command/InstallCommand.php +++ b/PHPCI/Command/InstallCommand.php @@ -195,7 +195,7 @@ class InstallCommand extends Command protected function writeConfigFile(array $config) { $dumper = new \Symfony\Component\Yaml\Dumper(); - $yaml = $dumper->dump($config); + $yaml = $dumper->dump($config, 2); file_put_contents(PHPCI_DIR . 'PHPCI/config.yml', $yaml); } diff --git a/PHPCI/Controller/ProjectController.php b/PHPCI/Controller/ProjectController.php index 850f6230..eea5a7a8 100644 --- a/PHPCI/Controller/ProjectController.php +++ b/PHPCI/Controller/ProjectController.php @@ -10,6 +10,8 @@ namespace PHPCI\Controller; use PHPCI\BuildFactory; +use PHPCI\Helper\Github; +use PHPCI\Helper\SshKey; use PHPCI\Model\Build; use PHPCI\Model\Project; use b8; @@ -145,37 +147,16 @@ class ProjectController extends \PHPCI\Controller $method = $this->request->getMethod(); - if ($method == 'POST') { - $values = $this->getParams(); - $pub = null; - } else { - $tempPath = sys_get_temp_dir() . '/'; + $pub = null; + $values = $this->getParams(); - // FastCGI fix for Windows machines, where temp path is not available to - // PHP, and defaults to the unwritable system directory. If the temp - // path is pointing to the system directory, shift to the 'TEMP' - // sub-folder, which should also exist, but actually be writable. - if ($tempPath == getenv("SystemRoot") . '/') { - $tempPath = getenv("SystemRoot") . '/TEMP/'; - } + if ($method != 'POST') { + $sshKey = new SshKey(); + $key = $sshKey->generate(); - $keyFile = $tempPath . md5(microtime(true)); - - if (!is_dir($tempPath)) { - mkdir($tempPath); - } - - if ($this->canGenerateKeys()) { - shell_exec('ssh-keygen -q -t rsa -b 2048 -f '.$keyFile.' -N "" -C "deploy@phpci"'); - - $pub = file_get_contents($keyFile . '.pub'); - $prv = file_get_contents($keyFile); - - $values = array('key' => $prv, 'pubkey' => $pub); - } else { - $pub = null; - $values = array(); - } + $values['key'] = $key['private_key']; + $values['pubkey'] = $key['public_key']; + $pub = $key['public_key']; } $form = $this->projectForm($values); @@ -351,7 +332,8 @@ class ProjectController extends \PHPCI\Controller $field = new Form\Element\TextArea('build_config'); $field->setRequired(false); - $field->setLabel('PHPCI build config for this project (if you cannot add a phpci.yml file in the project repository)'); + $label = 'PHPCI build config for this project (if you cannot add a phpci.yml file in the project repository)'; + $field->setLabel($label); $field->setClass('form-control'); $field->setContainerClass('form-group'); $field->setRows(6); @@ -380,46 +362,8 @@ class ProjectController extends \PHPCI\Controller */ protected function githubRepositories() { - $token = Config::getInstance()->get('phpci.github.token'); - - if (!$token) { - die(json_encode(null)); - } - - $cache = \b8\Cache::getCache(\b8\Cache::TYPE_APC); - $rtn = $cache->get('phpci_github_repos'); - - if (!$rtn) { - $orgs = $this->doGithubApiRequest('/user/orgs', array('access_token' => $token)); - - $params = array('type' => 'all', 'access_token' => $token); - $repos = array(); - $repos['user'] = $this->doGithubApiRequest('/user/repos', $params); - - - foreach ($orgs as $org) { - $repos[$org['login']] = $this->doGithubApiRequest('/orgs/'.$org['login'].'/repos', $params); - } - - $rtn = array(); - foreach ($repos as $repoGroup) { - foreach ($repoGroup as $repo) { - $rtn['repos'][] = $repo['full_name']; - } - } - - $cache->set('phpci_github_repos', $rtn); - } - - die(json_encode($rtn)); - } - - protected function doGithubApiRequest($url, $params) - { - $http = new \b8\HttpClient('https://api.github.com'); - $res = $http->get($url, $params); - - return $res['body']; + $github = new Github(); + die(json_encode($github->getRepositories())); } protected function getReferenceValidator($values) @@ -459,10 +403,4 @@ class ProjectController extends \PHPCI\Controller return true; }; } - - protected function canGenerateKeys() - { - $result = @shell_exec('ssh-keygen'); - return !empty($result); - } } diff --git a/PHPCI/Controller/SettingsController.php b/PHPCI/Controller/SettingsController.php index c2ea099b..2e0fc5ec 100644 --- a/PHPCI/Controller/SettingsController.php +++ b/PHPCI/Controller/SettingsController.php @@ -62,7 +62,7 @@ class SettingsController extends Controller $this->settings['phpci']['github']['secret'] = $this->getParam('githubsecret', ''); $error = $this->storeSettings(); - if($error) { + if ($error) { header('Location: ' . PHPCI_URL . 'settings?saved=2'); } else { header('Location: ' . PHPCI_URL . 'settings?saved=1'); diff --git a/PHPCI/Helper/BuildInterpolator.php b/PHPCI/Helper/BuildInterpolator.php index d4609793..fef51bee 100644 --- a/PHPCI/Helper/BuildInterpolator.php +++ b/PHPCI/Helper/BuildInterpolator.php @@ -58,4 +58,4 @@ class BuildInterpolator $values = array_values($this->interpolation_vars); return str_replace($keys, $values, $input); } -} \ No newline at end of file +} diff --git a/PHPCI/Helper/Github.php b/PHPCI/Helper/Github.php new file mode 100644 index 00000000..6ce2d556 --- /dev/null +++ b/PHPCI/Helper/Github.php @@ -0,0 +1,57 @@ +get($url, $params); + + return $res['body']; + } + + /** + * Get an array of repositories from Github's API. + */ + public function getRepositories() + { + $token = Config::getInstance()->get('phpci.github.token'); + + if (!$token) { + die(json_encode(null)); + } + + $cache = Cache::getCache(Cache::TYPE_APC); + $rtn = $cache->get('phpci_github_repos'); + + if (!$rtn) { + $orgs = $this->makeRequest('/user/orgs', array('access_token' => $token)); + + $params = array('type' => 'all', 'access_token' => $token); + $repos = array(); + $repos['user'] = $this->makeRequest('/user/repos', $params); + + + foreach ($orgs as $org) { + $repos[$org['login']] = $this->makeRequest('/orgs/'.$org['login'].'/repos', $params); + } + + $rtn = array(); + foreach ($repos as $repoGroup) { + foreach ($repoGroup as $repo) { + $rtn['repos'][] = $repo['full_name']; + } + } + + $cache->set('phpci_github_repos', $rtn); + } + + return $rtn; + } +} diff --git a/PHPCI/Helper/MailerFactory.php b/PHPCI/Helper/MailerFactory.php index 33bb8b74..d8625630 100644 --- a/PHPCI/Helper/MailerFactory.php +++ b/PHPCI/Helper/MailerFactory.php @@ -3,16 +3,16 @@ namespace PHPCI\Helper; -class MailerFactory { - +class MailerFactory +{ /** * @var array */ protected $emailConfig; - public function __construct($phpCiConfig = null) + public function __construct($config = null) { - $this->emailConfig = isset($phpCiSettings['email_settings']) ?: array(); + $this->emailConfig = isset($config['email_settings']) ?: array(); } /** @@ -33,7 +33,7 @@ class MailerFactory { return \Swift_Mailer::newInstance($transport); } - protected function getMailConfig($configName) + protected function getMailConfig($configName) { if (isset($this->emailConfig[$configName]) && $this->emailConfig[$configName] != "") { return $this->emailConfig[$configName]; @@ -54,5 +54,4 @@ class MailerFactory { } } } - -} \ No newline at end of file +} diff --git a/PHPCI/Helper/SshKey.php b/PHPCI/Helper/SshKey.php new file mode 100644 index 00000000..7c944e1a --- /dev/null +++ b/PHPCI/Helper/SshKey.php @@ -0,0 +1,46 @@ +canGenerateKeys()) { + shell_exec('ssh-keygen -q -t rsa -b 2048 -f '.$keyFile.' -N "" -C "deploy@phpci"'); + + $pub = file_get_contents($keyFile . '.pub'); + $prv = file_get_contents($keyFile); + + $return = array('private_key' => $prv, 'public_key' => $pub); + } + + return $return; + } + + public function canGenerateKeys() + { + $keygen = @shell_exec('ssh-keygen'); + $canGenerateKeys = !empty($keygen); + + return $canGenerateKeys; + } +} diff --git a/PHPCI/Logging/Handler.php b/PHPCI/Logging/Handler.php index 55e0e4a3..b38c37a1 100644 --- a/PHPCI/Logging/Handler.php +++ b/PHPCI/Logging/Handler.php @@ -26,12 +26,12 @@ class Handler */ protected $logger; - public function __construct(LoggerInterface $logger = NULL) + public function __construct(LoggerInterface $logger = null) { $this->logger = $logger; } - public static function register(LoggerInterface $logger = NULL) + public static function register(LoggerInterface $logger = null) { $handler = new static($logger); @@ -57,7 +57,10 @@ class Handler throw new \ErrorException( sprintf('%s: %s in %s line %d', $exception_level, $message, $file, $line), - 0, $level, $file, $line + 0, + $level, + $file, + $line ); } } @@ -70,21 +73,37 @@ class Handler $fatal_error = error_get_last(); try { - if (($e = error_get_last()) !== null) { - $e = new \ErrorException( - sprintf('%s: %s in %s line %d', $fatal_error['type'], $fatal_error['message'], $fatal_error['file'], $fatal_error['line']), - 0, $fatal_error['type'], $fatal_error['file'], $fatal_error['line'] + if (($error = error_get_last()) !== null) { + $error = new \ErrorException( + sprintf( + '%s: %s in %s line %d', + $fatal_error['type'], + $fatal_error['message'], + $fatal_error['file'], + $fatal_error['line'] + ), + 0, + $fatal_error['type'], + $fatal_error['file'], + $fatal_error['line'] ); - $this->log($e); + $this->log($error); } - } - catch (\Exception $e) - { - $e = new \ErrorException( - sprintf('%s: %s in %s line %d', $fatal_error['type'], $fatal_error['message'], $fatal_error['file'], $fatal_error['line']), - 0, $fatal_error['type'], $fatal_error['file'], $fatal_error['line'] + } catch (\Exception $e) { + $error = new \ErrorException( + sprintf( + '%s: %s in %s line %d', + $fatal_error['type'], + $fatal_error['message'], + $fatal_error['file'], + $fatal_error['line'] + ), + 0, + $fatal_error['type'], + $fatal_error['file'], + $fatal_error['line'] ); - $this->log($e); + $this->log($error); } } @@ -101,9 +120,14 @@ class Handler if (null !== $this->logger) { $message = sprintf( - '%s: %s (uncaught exception) at %s line %s', get_class($exception), $exception->getMessage(), $exception->getFile(), $exception->getLine() + '%s: %s (uncaught exception) at %s line %s', + get_class($exception), + $exception->getMessage(), + $exception->getFile(), + $exception->getLine() ); + $this->logger->error($message, array('exception' => $exception)); } } -} \ No newline at end of file +} diff --git a/PHPCI/Logging/OutputLogHandler.php b/PHPCI/Logging/OutputLogHandler.php index d573b03d..a0b8e5d9 100644 --- a/PHPCI/Logging/OutputLogHandler.php +++ b/PHPCI/Logging/OutputLogHandler.php @@ -28,6 +28,4 @@ class OutputLogHandler extends AbstractProcessingHandler { $this->output->writeln((string)$record['formatted']); } - - } diff --git a/PHPCI/Model/Base/BuildBase.php b/PHPCI/Model/Base/BuildBase.php index 59e4c21e..569c9d6b 100644 --- a/PHPCI/Model/Base/BuildBase.php +++ b/PHPCI/Model/Base/BuildBase.php @@ -631,31 +631,4 @@ class BuildBase extends Model { return Factory::getStore('BuildMeta', 'PHPCI')->getByBuildId($this->getId()); } - - - - - public static function getByPrimaryKey($value, $useConnection = 'read') - { - return Factory::getStore('Build', 'PHPCI')->getByPrimaryKey($value, $useConnection); - } - - - public static function getById($value, $useConnection = 'read') - { - return Factory::getStore('Build', 'PHPCI')->getById($value, $useConnection); - } - - public static function getByProjectId($value, $limit = null, $useConnection = 'read') - { - return Factory::getStore('Build', 'PHPCI')->getByProjectId($value, $limit, $useConnection); - } - - public static function getByStatus($value, $limit = null, $useConnection = 'read') - { - return Factory::getStore('Build', 'PHPCI')->getByStatus($value, $limit, $useConnection); - } - - - } diff --git a/PHPCI/Model/Base/BuildMetaBase.php b/PHPCI/Model/Base/BuildMetaBase.php index 83333102..b7f85490 100644 --- a/PHPCI/Model/Base/BuildMetaBase.php +++ b/PHPCI/Model/Base/BuildMetaBase.php @@ -337,26 +337,4 @@ class BuildMetaBase extends Model { return $this->setBuildId($value->getId()); } - - - - - public static function getByPrimaryKey($value, $useConnection = 'read') - { - return Factory::getStore('BuildMeta', 'PHPCI')->getByPrimaryKey($value, $useConnection); - } - - - public static function getById($value, $useConnection = 'read') - { - return Factory::getStore('BuildMeta', 'PHPCI')->getById($value, $useConnection); - } - - public static function getByBuildId($value, $limit = null, $useConnection = 'read') - { - return Factory::getStore('BuildMeta', 'PHPCI')->getByBuildId($value, $limit, $useConnection); - } - - - } diff --git a/PHPCI/Model/Base/ProjectBase.php b/PHPCI/Model/Base/ProjectBase.php index aeeee67c..9e2f5922 100644 --- a/PHPCI/Model/Base/ProjectBase.php +++ b/PHPCI/Model/Base/ProjectBase.php @@ -516,26 +516,4 @@ class ProjectBase extends Model { return Factory::getStore('Build', 'PHPCI')->getByProjectId($this->getId()); } - - - - - public static function getByPrimaryKey($value, $useConnection = 'read') - { - return Factory::getStore('Project', 'PHPCI')->getByPrimaryKey($value, $useConnection); - } - - - public static function getById($value, $useConnection = 'read') - { - return Factory::getStore('Project', 'PHPCI')->getById($value, $useConnection); - } - - public static function getByTitle($value, $limit = null, $useConnection = 'read') - { - return Factory::getStore('Project', 'PHPCI')->getByTitle($value, $limit, $useConnection); - } - - - } diff --git a/PHPCI/Model/Base/UserBase.php b/PHPCI/Model/Base/UserBase.php index f0b0e393..514a0db9 100644 --- a/PHPCI/Model/Base/UserBase.php +++ b/PHPCI/Model/Base/UserBase.php @@ -273,26 +273,4 @@ class UserBase extends Model $this->_setModified('name'); } - - - - - public static function getByPrimaryKey($value, $useConnection = 'read') - { - return Factory::getStore('User', 'PHPCI')->getByPrimaryKey($value, $useConnection); - } - - - public static function getById($value, $useConnection = 'read') - { - return Factory::getStore('User', 'PHPCI')->getById($value, $useConnection); - } - - public static function getByEmail($value, $useConnection = 'read') - { - return Factory::getStore('User', 'PHPCI')->getByEmail($value, $useConnection); - } - - - } diff --git a/PHPCI/Model/Build/GithubBuild.php b/PHPCI/Model/Build/GithubBuild.php index 02118c60..f358355a 100644 --- a/PHPCI/Model/Build/GithubBuild.php +++ b/PHPCI/Model/Build/GithubBuild.php @@ -98,7 +98,9 @@ class GithubBuild extends RemoteGitBuild { $rtn = $this->data['commit_message']; - $rtn = preg_replace('/\#([0-9]+)/', '#$1', $rtn); + $reference = $this->getProject()->getReference(); + $commitLink = '#$1'; + $rtn = preg_replace('/\#([0-9]+)/', $commitLink, $rtn); $rtn = preg_replace('/\@([a-zA-Z0-9_]+)/', '@$1', $rtn); return $rtn; diff --git a/PHPCI/Model/Build/GitlabBuild.php b/PHPCI/Model/Build/GitlabBuild.php index 8c1e038b..1ce777ae 100644 --- a/PHPCI/Model/Build/GitlabBuild.php +++ b/PHPCI/Model/Build/GitlabBuild.php @@ -43,10 +43,11 @@ class GitlabBuild extends RemoteGitBuild */ public function getFileLinkTemplate() { - return sprintf('http://%s/%s/blob/%s/{FILE}#L{LINE}', - $this->getProject()->getAccessInformation("domain"), - $this->getProject()->getReference(), - $this->getBranch() + return sprintf( + 'http://%s/%s/blob/%s/{FILE}#L{LINE}', + $this->getProject()->getAccessInformation("domain"), + $this->getProject()->getReference(), + $this->getBranch() ); } diff --git a/PHPCI/Model/Build/LocalBuild.php b/PHPCI/Model/Build/LocalBuild.php index e5837595..9f2be613 100644 --- a/PHPCI/Model/Build/LocalBuild.php +++ b/PHPCI/Model/Build/LocalBuild.php @@ -60,7 +60,8 @@ class LocalBuild extends Build // If it is indeed a bare repository, then extract it into our build path: if ($gitConfig['core']['bare']) { - $builder->executeCommand('mkdir %2$s; git --git-dir="%1$s" archive %3$s | tar -x -C "%2$s"', $reference, $buildPath, $this->getBranch()); + $cmd = 'mkdir %2$s; git --git-dir="%1$s" archive %3$s | tar -x -C "%2$s"'; + $builder->executeCommand($cmd, $reference, $buildPath, $this->getBranch()); return true; } diff --git a/PHPCI/Model/Build/RemoteGitBuild.php b/PHPCI/Model/Build/RemoteGitBuild.php index bc4192b1..144f69f6 100644 --- a/PHPCI/Model/Build/RemoteGitBuild.php +++ b/PHPCI/Model/Build/RemoteGitBuild.php @@ -54,7 +54,8 @@ class RemoteGitBuild extends Build */ protected function cloneByHttp(Builder $builder, $cloneTo) { - $success = $builder->executeCommand('git clone -b %s %s "%s"', $this->getBranch(), $this->getCloneUrl(), $cloneTo); + $cmd = 'git clone -b %s %s "%s"'; + $success = $builder->executeCommand($cmd, $this->getBranch(), $this->getCloneUrl(), $cloneTo); if (!empty($commit) && $commit != 'Manual') { $cmd = 'cd "%s" && git checkout %s'; @@ -136,10 +137,12 @@ class RemoteGitBuild extends Build $path = dirname($cloneTo . '/temp'); $wrapperFile = $path . '.sh'; + $sshFlags = '-o CheckHostIP=no -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o PasswordAuthentication=no'; + // Write out the wrapper script for this build: $script = <<phpci = $phpci; + $this->build = $build; $this->features = ''; if (isset($options['executable'])) { diff --git a/PHPCI/Plugin/CleanBuild.php b/PHPCI/Plugin/CleanBuild.php index a7db4fc9..73a7305f 100644 --- a/PHPCI/Plugin/CleanBuild.php +++ b/PHPCI/Plugin/CleanBuild.php @@ -23,10 +23,12 @@ class CleanBuild implements \PHPCI\Plugin { protected $remove; protected $phpci; + protected $build; public function __construct(Builder $phpci, Build $build, array $options = array()) { $this->phpci = $phpci; + $this->build = $build; $this->remove = isset($options['remove']) && is_array($options['remove']) ? $options['remove'] : array(); } diff --git a/PHPCI/Plugin/Codeception.php b/PHPCI/Plugin/Codeception.php index bac0e7be..5b811896 100644 --- a/PHPCI/Plugin/Codeception.php +++ b/PHPCI/Plugin/Codeception.php @@ -30,6 +30,8 @@ class Codeception implements \PHPCI\Plugin */ protected $phpci; + protected $build; + /** * @var string|string[] $xmlConfigFile The path (or array of paths) of an xml config for PHPUnit */ @@ -38,6 +40,7 @@ class Codeception implements \PHPCI\Plugin public function __construct(Builder $phpci, Build $build, array $options = array()) { $this->phpci = $phpci; + $this->build = $build; if (isset($options['config'])) { $this->xmlConfigFile = $options['config']; @@ -79,7 +82,9 @@ class Codeception implements \PHPCI\Plugin if (IS_WIN) { $cmd = 'cd /d "%s" && ' . $codecept . ' run -c "%s" '. $this->args; } - $success = $this->phpci->executeCommand($cmd, $this->phpci->buildPath, $this->phpci->buildPath . $configPath); + + $configPath = $this->phpci->buildPath . $configPath; + $success = $this->phpci->executeCommand($cmd, $this->phpci->buildPath, $configPath); return $success; } diff --git a/PHPCI/Plugin/Composer.php b/PHPCI/Plugin/Composer.php index 70462eba..3a13b672 100644 --- a/PHPCI/Plugin/Composer.php +++ b/PHPCI/Plugin/Composer.php @@ -25,6 +25,7 @@ class Composer implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin protected $action; protected $preferDist; protected $phpci; + protected $build; public static function canExecute($stage, Builder $builder, Build $build) { @@ -41,8 +42,9 @@ class Composer implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin { $path = $phpci->buildPath; $this->phpci = $phpci; + $this->build = $build; $this->directory = isset($options['directory']) ? $path . '/' . $options['directory'] : $path; - $this->action = isset($options['action']) ? $options['action'] : 'update'; + $this->action = isset($options['action']) ? $options['action'] : 'install'; $this->preferDist = isset($options['prefer_dist']) ? $options['prefer_dist'] : true; } diff --git a/PHPCI/Plugin/CopyBuild.php b/PHPCI/Plugin/CopyBuild.php index 39d41e3f..021d5e80 100644 --- a/PHPCI/Plugin/CopyBuild.php +++ b/PHPCI/Plugin/CopyBuild.php @@ -23,11 +23,13 @@ class CopyBuild implements \PHPCI\Plugin protected $directory; protected $ignore; protected $phpci; + protected $build; public function __construct(Builder $phpci, Build $build, array $options = array()) { $path = $phpci->buildPath; $this->phpci = $phpci; + $this->build = $build; $this->directory = isset($options['directory']) ? $options['directory'] : $path; $this->ignore = isset($options['respect_ignore']) ? (bool)$options['respect_ignore'] : false; } diff --git a/PHPCI/Plugin/Email.php b/PHPCI/Plugin/Email.php index f6317197..0b23a1d7 100644 --- a/PHPCI/Plugin/Email.php +++ b/PHPCI/Plugin/Email.php @@ -46,7 +46,6 @@ class Email implements \PHPCI\Plugin Build $build, \Swift_Mailer $mailer, array $options = array() - ) { $this->phpci = $phpci; $this->build = $build; diff --git a/PHPCI/Plugin/Env.php b/PHPCI/Plugin/Env.php index 09ffbb5a..a55cf47d 100644 --- a/PHPCI/Plugin/Env.php +++ b/PHPCI/Plugin/Env.php @@ -21,11 +21,13 @@ use PHPCI\Model\Build; class Env implements \PHPCI\Plugin { protected $phpci; + protected $build; protected $env_vars; public function __construct(Builder $phpci, Build $build, array $options = array()) { - $this->phpci = $phpci; + $this->phpci = $phpci; + $this->build = $build; $this->env_vars = $options; } diff --git a/PHPCI/Plugin/Git.php b/PHPCI/Plugin/Git.php index 54f1f160..00c1f78f 100644 --- a/PHPCI/Plugin/Git.php +++ b/PHPCI/Plugin/Git.php @@ -31,7 +31,6 @@ class Git implements \PHPCI\Plugin $this->actions = $options; } - public function execute() { $buildPath = $this->phpci->buildPath; @@ -58,68 +57,80 @@ class Git implements \PHPCI\Plugin return $success; } - protected function runAction($action, $options = array()) + protected function runAction($action, array $options = array()) { - // If options isn't an array, it should be. - if (!is_array($options)) { - $options = array(); + switch ($action) { + case 'merge': + return $this->runMergeAction($options); + + case 'tag': + return $this->runTagAction($options); + + case 'pull': + return $this->runPullAction($options); + + case 'push': + return $this->runPushAction($options); } - // Handle git merges. - if ($action == 'merge' && array_key_exists('branch', $options)) { - $cmd = 'git checkout %s && git merge ' . $this->build->getBranch(); - return $this->phpci->executeCommand($cmd, $this->directory, $options['branch']); - } - - // Handle tagging: - if ($action == 'tag') { - $tagName = date('Ymd-His'); - $message = 'Tag created by PHPCI: ' . date('Y-m-d H:i:s'); - - if (array_key_exists('name', $options)) { - $tagName = $this->phpci->interpolate($options['name']); - } - - if (array_key_exists('message', $options)) { - $message = $this->phpci->interpolate($options['message']); - } - - $cmd = 'git tag %s -m "%s"'; - return $this->phpci->executeCommand($cmd, $tagName, $message); - } - - // Handle pull: - if ($action == 'pull') { - $branch = $this->build->getBranch(); - $remote = 'origin'; - - if (array_key_exists('branch', $options)) { - $branch = $this->phpci->interpolate($options['branch']); - } - - if (array_key_exists('remote', $options)) { - $remote = $this->phpci->interpolate($options['remote']); - } - - return $this->phpci->executeCommand('git pull %s %s', $remote, $branch); - } - - // Handle push: - if ($action == 'push') { - $branch = $this->build->getBranch(); - $remote = 'origin'; - - if (array_key_exists('branch', $options)) { - $branch = $this->phpci->interpolate($options['branch']); - } - - if (array_key_exists('remote', $options)) { - $remote = $this->phpci->interpolate($options['remote']); - } - - return $this->phpci->executeCommand('git push %s %s', $remote, $branch); - } return false; } + + protected function runMergeAction($options) + { + if (array_key_exists('branch', $options)) { + $cmd = 'git checkout %s && git merge ' . $this->build->getBranch(); + return $this->phpci->executeCommand($cmd, $this->directory, $options['branch']); + } + } + + protected function runTagAction($options) + { + $tagName = date('Ymd-His'); + $message = 'Tag created by PHPCI: ' . date('Y-m-d H:i:s'); + + if (array_key_exists('name', $options)) { + $tagName = $this->phpci->interpolate($options['name']); + } + + if (array_key_exists('message', $options)) { + $message = $this->phpci->interpolate($options['message']); + } + + $cmd = 'git tag %s -m "%s"'; + return $this->phpci->executeCommand($cmd, $tagName, $message); + } + + protected function runPullAction($options) + { + $branch = $this->build->getBranch(); + $remote = 'origin'; + + if (array_key_exists('branch', $options)) { + $branch = $this->phpci->interpolate($options['branch']); + } + + if (array_key_exists('remote', $options)) { + $remote = $this->phpci->interpolate($options['remote']); + } + + return $this->phpci->executeCommand('git pull %s %s', $remote, $branch); + } + + protected function runPushAction($options) + { + $branch = $this->build->getBranch(); + $remote = 'origin'; + + if (array_key_exists('branch', $options)) { + $branch = $this->phpci->interpolate($options['branch']); + } + + if (array_key_exists('remote', $options)) { + $remote = $this->phpci->interpolate($options['remote']); + } + + return $this->phpci->executeCommand('git push %s %s', $remote, $branch); + } } diff --git a/PHPCI/Plugin/Grunt.php b/PHPCI/Plugin/Grunt.php index ddbe7aa3..0c845184 100644 --- a/PHPCI/Plugin/Grunt.php +++ b/PHPCI/Plugin/Grunt.php @@ -24,12 +24,14 @@ class Grunt implements \PHPCI\Plugin protected $task; protected $preferDist; protected $phpci; + protected $build; protected $grunt; protected $gruntfile; public function __construct(Builder $phpci, Build $build, array $options = array()) { $path = $phpci->buildPath; + $this->build = $build; $this->phpci = $phpci; $this->directory = $path; $this->task = null; diff --git a/PHPCI/Plugin/Irc.php b/PHPCI/Plugin/Irc.php index 6b294d66..0defc037 100644 --- a/PHPCI/Plugin/Irc.php +++ b/PHPCI/Plugin/Irc.php @@ -13,16 +13,18 @@ use PHPCI\Model\Build; */ class Irc implements \PHPCI\Plugin { - private $phpci; - private $message; - private $server; - private $port; - private $room; - private $nick; + protected $phpci; + protected $build; + protected $message; + protected $server; + protected $port; + protected $room; + protected $nick; public function __construct(Builder $phpci, Build $build, array $options = array()) { $this->phpci = $phpci; + $this->build = $build; $this->message = $options['message']; $buildSettings = $phpci->getConfig('build_settings'); diff --git a/PHPCI/Plugin/Lint.php b/PHPCI/Plugin/Lint.php index 73b4beaf..3ca785ec 100644 --- a/PHPCI/Plugin/Lint.php +++ b/PHPCI/Plugin/Lint.php @@ -25,10 +25,12 @@ class Lint implements PHPCI\Plugin protected $recursive = true; protected $ignore; protected $phpci; + protected $build; public function __construct(Builder $phpci, Build $build, array $options = array()) { $this->phpci = $phpci; + $this->build = $build; $this->directories = array(''); $this->ignore = $phpci->ignore; diff --git a/PHPCI/Plugin/Mysql.php b/PHPCI/Plugin/Mysql.php index e2fda714..c66f77cb 100755 --- a/PHPCI/Plugin/Mysql.php +++ b/PHPCI/Plugin/Mysql.php @@ -27,6 +27,7 @@ class Mysql implements \PHPCI\Plugin * @var \PHPCI\Builder */ protected $phpci; + protected $build; protected $queries = array(); protected $host; @@ -42,6 +43,8 @@ class Mysql implements \PHPCI\Plugin public function __construct(Builder $phpci, Build $build, array $options = array()) { $this->phpci = $phpci; + $this->build = $build; + $this->queries = $options; $config = \b8\Database::getConnection('write')->getDetails(); diff --git a/PHPCI/Plugin/Pgsql.php b/PHPCI/Plugin/Pgsql.php index 45155ecf..a05068d2 100644 --- a/PHPCI/Plugin/Pgsql.php +++ b/PHPCI/Plugin/Pgsql.php @@ -22,6 +22,7 @@ use PHPCI\Model\Build; class Pgsql implements \PHPCI\Plugin { protected $phpci; + protected $build; protected $queries = array(); protected $host; @@ -30,13 +31,14 @@ class Pgsql implements \PHPCI\Plugin public function __construct(Builder $phpci, Build $build, array $options = array()) { - $this->phpci = $phpci; - $this->queries = $options; + $this->phpci = $phpci; + $this->build = $build; + $this->queries = $options; $buildSettings = $phpci->getConfig('build_settings'); if (isset($buildSettings['pgsql'])) { - $sql = $buildSettings['pgsql']; + $sql = $buildSettings['pgsql']; $this->host = $sql['host']; $this->user = $sql['user']; $this->pass = $sql['pass']; diff --git a/PHPCI/Plugin/Phing.php b/PHPCI/Plugin/Phing.php index e90d4b4a..270b3aa9 100644 --- a/PHPCI/Plugin/Phing.php +++ b/PHPCI/Plugin/Phing.php @@ -29,10 +29,12 @@ class Phing implements \PHPCI\Plugin private $propertyFile; protected $phpci; + protected $build; public function __construct(Builder $phpci, Build $build, array $options = array()) { $this->setPhpci($phpci); + $this->build = $build; /* * Set working directory diff --git a/PHPCI/Plugin/PhpCpd.php b/PHPCI/Plugin/PhpCpd.php index bbefd7e6..2e0b908e 100644 --- a/PHPCI/Plugin/PhpCpd.php +++ b/PHPCI/Plugin/PhpCpd.php @@ -23,6 +23,7 @@ class PhpCpd implements \PHPCI\Plugin protected $directory; protected $args; protected $phpci; + protected $build; /** * @var string, based on the assumption the root may not hold the code to be @@ -38,6 +39,8 @@ class PhpCpd implements \PHPCI\Plugin public function __construct(Builder $phpci, Build $build, array $options = array()) { $this->phpci = $phpci; + $this->build = $build; + $this->path = $phpci->buildPath; $this->standard = 'PSR1'; $this->ignore = $phpci->ignore; diff --git a/PHPCI/Plugin/PhpCsFixer.php b/PHPCI/Plugin/PhpCsFixer.php index ca07e9ef..7b1cff2a 100644 --- a/PHPCI/Plugin/PhpCsFixer.php +++ b/PHPCI/Plugin/PhpCsFixer.php @@ -20,8 +20,16 @@ use PHPCI\Model\Build; */ class PhpCsFixer implements \PHPCI\Plugin { + /** + * @var \PHPCI\Builder + */ protected $phpci; + /** + * @var \PHPCI\Model\Build + */ + protected $build; + protected $workingDir = ''; protected $level = ' --level=all'; protected $verbose = ''; @@ -31,6 +39,8 @@ class PhpCsFixer implements \PHPCI\Plugin public function __construct(Builder $phpci, Build $build, array $options = array()) { $this->phpci = $phpci; + $this->build = $build; + $this->workingdir = $this->phpci->buildPath; $this->buildArgs($options); } diff --git a/PHPCI/Plugin/PhpMessDetector.php b/PHPCI/Plugin/PhpMessDetector.php index ce9f0193..2be7fed4 100755 --- a/PHPCI/Plugin/PhpMessDetector.php +++ b/PHPCI/Plugin/PhpMessDetector.php @@ -26,6 +26,11 @@ class PhpMessDetector implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin */ protected $phpci; + /** + * @var \PHPCI\Model\Build + */ + protected $build; + /** * @var array */ @@ -59,10 +64,7 @@ class PhpMessDetector implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin return false; } - /** - * @param \PHPCI\Builder $phpci - * @param array $options - */ + public function __construct(Builder $phpci, Build $build, array $options = array()) { $this->phpci = $phpci; diff --git a/PHPCI/Plugin/PhpSpec.php b/PHPCI/Plugin/PhpSpec.php index 843017b9..c8a36253 100644 --- a/PHPCI/Plugin/PhpSpec.php +++ b/PHPCI/Plugin/PhpSpec.php @@ -21,11 +21,26 @@ use PHPCI\Model\Build; */ class PhpSpec implements PHPCI\Plugin { + /** + * @var \PHPCI\Builder + */ protected $phpci; + /** + * @var \PHPCI\Model\Build + */ + protected $build; + + /** + * @var array + */ + protected $options; + public function __construct(Builder $phpci, Build $build, array $options = array()) { - $this->phpci = $phpci; + $this->phpci = $phpci; + $this->build = $build; + $this->options = $options; } /** diff --git a/PHPCI/Plugin/PhpUnit.php b/PHPCI/Plugin/PhpUnit.php index ab0cfc58..16de7aa0 100755 --- a/PHPCI/Plugin/PhpUnit.php +++ b/PHPCI/Plugin/PhpUnit.php @@ -12,6 +12,7 @@ namespace PHPCI\Plugin; use PHPCI; use PHPCI\Builder; use PHPCI\Model\Build; +use PHPCI\Plugin\Util\TapParser; /** * PHP Unit Plugin - Allows PHP Unit testing. @@ -23,6 +24,7 @@ class PhpUnit implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin { protected $args; protected $phpci; + protected $build; /** * @var string|string[] $directory The directory (or array of dirs) to run PHPUnit on @@ -58,20 +60,20 @@ class PhpUnit implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin public static function findConfigFile($buildPath) { - if (file_exists($buildPath . '/phpunit.xml')) { - return $buildPath . '/phpunit.xml'; + if (file_exists($buildPath . 'phpunit.xml')) { + return 'phpunit.xml'; } - if (file_exists($buildPath . '/tests/phpunit.xml')) { - return $buildPath . '/tests/phpunit.xml'; + if (file_exists($buildPath . 'tests/phpunit.xml')) { + return 'tests/phpunit.xml'; } - if (file_exists($buildPath . '/phpunit.xml.dist')) { - return $buildPath . '/phpunit.xml.dist'; + if (file_exists($buildPath . 'phpunit.xml.dist')) { + return 'phpunit.xml.dist'; } - if (file_exists($buildPath . '/tests/phpunit.xml.dist')) { - return $buildPath . '/tests/phpunit.xml.dist'; + if (file_exists($buildPath . 'tests/phpunit.xml.dist')) { + return 'tests/phpunit.xml.dist'; } return null; @@ -80,9 +82,9 @@ class PhpUnit implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin public function __construct(Builder $phpci, Build $build, array $options = array()) { $this->phpci = $phpci; + $this->build = $build; - if (!count($options)) { - $this->runFrom = $phpci->buildPath; + if (empty($options['config']) && empty($options['directory'])) { $this->xmlConfigFile = self::findConfigFile($phpci->buildPath); } @@ -118,6 +120,8 @@ class PhpUnit implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin { $success = true; + $this->phpci->logExecOutput(false); + // Run any config files first. This can be either a single value or an array. if ($this->xmlConfigFile !== null) { $success &= $this->runConfigFile($this->xmlConfigFile); @@ -128,6 +132,16 @@ class PhpUnit implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin $success &= $this->runDir($this->directory); } + $output = $this->phpci->getLastOutput(); + $tapParser = new TapParser($output); + $output = $tapParser->parse(); + $failures = $tapParser->getTotalFailures(); + + $this->build->storeMeta('phpunit-errors', $failures); + $this->build->storeMeta('phpunit-data', $output); + + $this->phpci->logExecOutput(true); + return $success; } @@ -150,7 +164,7 @@ class PhpUnit implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin } - $cmd = $phpunit . ' %s -c "%s" ' . $this->coverage . $this->path; + $cmd = $phpunit . ' --tap %s -c "%s" ' . $this->coverage . $this->path; $success = $this->phpci->executeCommand($cmd, $this->args, $this->phpci->buildPath . $configPath); if ($this->runFrom) { @@ -176,7 +190,7 @@ class PhpUnit implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin return false; } - $cmd = $phpunit . ' %s "%s"'; + $cmd = $phpunit . ' --tap %s "%s"'; $success = $this->phpci->executeCommand($cmd, $this->args, $this->phpci->buildPath . $dirPath); chdir($curdir); return $success; diff --git a/PHPCI/Plugin/Shell.php b/PHPCI/Plugin/Shell.php index b9949cd3..73439cad 100644 --- a/PHPCI/Plugin/Shell.php +++ b/PHPCI/Plugin/Shell.php @@ -20,9 +20,18 @@ use PHPCI\Model\Build; */ class Shell implements \PHPCI\Plugin { - protected $args; + /** + * @var \PHPCI\Builder + */ protected $phpci; + /** + * @var \PHPCI\Model\Build + */ + protected $build; + + protected $args; + /** * @var string[] $commands The commands to be executed */ @@ -30,7 +39,8 @@ class Shell implements \PHPCI\Plugin public function __construct(Builder $phpci, Build $build, array $options = array()) { - $this->phpci = $phpci; + $this->phpci = $phpci; + $this->build = $build; if (isset($options['command'])) { // Keeping this for backwards compatibility, new projects should use interpolation vars. diff --git a/PHPCI/Plugin/Util/Executor.php b/PHPCI/Plugin/Util/Executor.php index 39a5d35e..15754f84 100644 --- a/PHPCI/Plugin/Util/Executor.php +++ b/PHPCI/Plugin/Util/Executor.php @@ -6,7 +6,6 @@ use \PHPCI\Logging\BuildLogger; class Executor { - /** * @var BuildLogger */ @@ -103,5 +102,4 @@ class Executor return $rtn; } - } diff --git a/PHPCI/Plugin/Util/PluginInformationCollection.php b/PHPCI/Plugin/Util/PluginInformationCollection.php index 9017ba72..43716867 100644 --- a/PHPCI/Plugin/Util/PluginInformationCollection.php +++ b/PHPCI/Plugin/Util/PluginInformationCollection.php @@ -44,5 +44,4 @@ class PluginInformationCollection implements InstalledPluginInformation } return $arr; } - } diff --git a/PHPCI/Plugin/Util/TapParser.php b/PHPCI/Plugin/Util/TapParser.php new file mode 100644 index 00000000..595e83ef --- /dev/null +++ b/PHPCI/Plugin/Util/TapParser.php @@ -0,0 +1,100 @@ +tapString = trim($tapString); + } + + /** + * Parse a given TAP format string and return an array of tests and their status. + */ + public function parse() + { + // Split up the TAP string into an array of lines, then + // trim all of the lines so there's no leading or trailing whitespace. + $lines = explode("\n", $this->tapString); + $lines = array_map(function ($line) { + return trim($line); + }, $lines); + + // Check TAP version: + $versionLine = array_shift($lines); + + if ($versionLine != 'TAP version 13') { + throw new \Exception('TapParser only supports TAP version 13'); + } + + $matches = array(); + $totalTests = 0; + if (preg_match(self::TEST_COUNTS_PATTERN, $lines[0], $matches)) { + array_shift($lines); + $totalTests = (int)$matches[2]; + } + + if (preg_match(self::TEST_COUNTS_PATTERN, $lines[count($lines) - 1], $matches)) { + array_pop($lines); + $totalTests = (int)$matches[2]; + } + + $rtn = $this->processTestLines($lines); + + if ($totalTests != count($rtn)) { + throw new \Exception('Invalid TAP string, number of tests does not match specified test count.'); + } + + return $rtn; + } + + protected function processTestLines($lines) + { + $rtn = array(); + + foreach ($lines as $line) { + $matches = array(); + + if (preg_match(self::TEST_LINE_PATTERN, $line, $matches)) { + $ok = ($matches[1] == 'ok' ? true : false); + + if (!$ok) { + $this->failures++; + } + + $item = array( + 'pass' => $ok, + 'suite' => $matches[2], + 'test' => $matches[3], + ); + + $rtn[] = $item; + } elseif (preg_match(self::TEST_MESSAGE_PATTERN, $line, $matches)) { + $rtn[count($rtn) - 1]['message'] = $matches[1]; + } + } + + return $rtn; + } + + public function getTotalFailures() + { + return $this->failures; + } +} diff --git a/PHPCI/Plugin/Wipe.php b/PHPCI/Plugin/Wipe.php index 3efd8a44..7a0c2107 100644 --- a/PHPCI/Plugin/Wipe.php +++ b/PHPCI/Plugin/Wipe.php @@ -20,13 +20,24 @@ use PHPCI\Model\Build; */ class Wipe implements \PHPCI\Plugin { - protected $directory; + /** + * @var \PHPCI\Builder + */ protected $phpci; + /** + * @var \PHPCI\Model\Build + */ + protected $build; + + protected $directory; + + public function __construct(Builder $phpci, Build $build, array $options = array()) { $path = $phpci->buildPath; $this->phpci = $phpci; + $this->build = $build; $this->directory = isset($options['directory']) ? $options['directory'] : $path; } diff --git a/PHPCI/View/Project/view.phtml b/PHPCI/View/Project/view.phtml index c3aa629c..115839a7 100644 --- a/PHPCI/View/Project/view.phtml +++ b/PHPCI/View/Project/view.phtml @@ -1,4 +1,3 @@ -

getTitle()); ?>

@@ -19,7 +18,7 @@ - getType(), array('github', 'gitlab','bitbucket'))): ?> + getType(), array('github', 'gitlab', 'bitbucket'))): ?>

Webhooks

@@ -27,7 +26,6 @@
To automatically build this project when new commits are pushed, add the URL below - getType()) @@ -50,6 +48,7 @@ ?>
+ getPublicKey()): ?>
diff --git a/README.md b/README.md index defd1998..77d9ef0c 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ _**Please be aware that PHPCI is a beta-release project, so whilst it is very st **Current Build Status** -![Build Status](http://phpci.block8.net/build-status/image/2) +[![Build Status](http://phpci.block8.net/build-status/image/2)](http://phpci.block8.net/build-status/view/2) ##What it does: * Clones your project from Github, Bitbucket or a local path diff --git a/Tests/PHPCI/Helper/CommandExecutorTest.php b/Tests/PHPCI/Helper/CommandExecutorTest.php index 047f4258..4925e639 100644 --- a/Tests/PHPCI/Helper/CommandExecutorTest.php +++ b/Tests/PHPCI/Helper/CommandExecutorTest.php @@ -42,7 +42,7 @@ class CommandExecutorTest extends ProphecyTestCase public function testExecuteCommand_ReturnsFalseForInvalidCommands() { - $returnValue = $this->testedExecutor->buildAndExecuteCommand(array('eerfdcvcho "%s"', 'Hello World')); + $returnValue = $this->testedExecutor->buildAndExecuteCommand(array('eerfdcvcho "%s" > /dev/null 2>&1', 'Hello World')); $this->assertFalse($returnValue); } diff --git a/Tests/PHPCI/Plugin/PHPUnitTest.php b/Tests/PHPCI/Plugin/PHPUnitTest.php deleted file mode 100644 index 89b24694..00000000 --- a/Tests/PHPCI/Plugin/PHPUnitTest.php +++ /dev/null @@ -1,172 +0,0 @@ -mockCiBuilder = $this->getMock( - '\PHPCI\Builder', - array('findBinary', 'executeCommand'), - array(), - "mockBuilder_phpUnit", - false - ); - $this->mockCiBuilder->buildPath = "/"; - - $this->mockBuild = $this->getMock( - '\PHPCI\Model\Build', - array(), - array(), - "MockBuild", - false - ); - - $this->loadPhpUnitWithOptions(); - } - - protected function loadPhpUnitWithOptions($arrOptions = array()) - { - $this->testedPhpUnit = new PhpUnit($this->mockCiBuilder, $this->mockBuild, $arrOptions); - } - - /** - * @param \PHPUnit_Framework_MockObject_Matcher_Invocation $expectation - */ - protected function expectFindBinaryToBeCalled($expectation) - { - $this->mockCiBuilder->expects($expectation) - ->method("findBinary") - ->will($this->returnValue("phpunit")); - } - - /** - * @param \PHPUnit_Framework_MockObject_Matcher_Invocation $expectation - */ - public function expectExectuteCommandToBeCalled($expectation) - { - $this->mockCiBuilder->expects($expectation) - ->method("executeCommand"); - } - - /** - * @covers PHPUnit::execute - */ - public function testExecute_ReturnsTrueWithoutArgs() - { - $returnValue = $this->testedPhpUnit->execute(); - $expectedReturn = true; - - $this->assertEquals($expectedReturn, $returnValue); - } - - /** - * @covers PHPUnit::execute - * @covers PHPUnit::runDir - */ - public function testExecute_CallsExecuteCommandOnceWhenGivenStringDirectory() - { - chdir('/'); - - $this->loadPhpUnitWithOptions( - array( - 'directory' => "Fake/Test/Path" - ) - ); - - $this->expectFindBinaryToBeCalled($this->once()); - $this->expectExectuteCommandToBeCalled($this->once()); - - $returnValue = $this->testedPhpUnit->execute(); - } - - /** - * @covers PHPUnit::execute - * @covers PHPUnit::runConfigFile - */ - public function testExecute_CallsExecuteCommandOnceWhenGivenStringConfig() - { - chdir('/'); - - $this->loadPhpUnitWithOptions( - array( - 'config' => "Fake/Test/config.xml" - ) - ); - - $this->expectFindBinaryToBeCalled($this->once()); - $this->expectExectuteCommandToBeCalled($this->once()); - - $returnValue = $this->testedPhpUnit->execute(); - } - - /** - * @covers PHPUnit::execute - * @covers PHPUnit::runDir - */ - public function testExecute_CallsExecuteCommandManyTimesWhenGivenArrayDirectory() - { - chdir('/'); - - $this->loadPhpUnitWithOptions( - array( - 'directory' => array("dir1", "dir2") - ) - ); - - $this->expectFindBinaryToBeCalled($this->exactly(2)); - $this->expectExectuteCommandToBeCalled($this->exactly(2)); - - $returnValue = $this->testedPhpUnit->execute(); - } - - /** - * @covers PHPUnit::execute - * @covers PHPUnit::runConfigFile - */ - public function testExecute_CallsExecuteCommandManyTimesWhenGivenArrayConfig() - { - chdir('/'); - - $this->loadPhpUnitWithOptions( - array( - 'config' => array("configfile1.xml", "configfile2.xml") - ) - ); - - $this->expectFindBinaryToBeCalled($this->exactly(2)); - $this->expectExectuteCommandToBeCalled($this->exactly(2)); - - $returnValue = $this->testedPhpUnit->execute(); - } -} \ No newline at end of file diff --git a/composer.json b/composer.json index 40aada7d..a6dec175 100644 --- a/composer.json +++ b/composer.json @@ -53,4 +53,4 @@ "jakub-onderka/php-parallel-lint": "Parallel Linting Tool", "behat/behat": "Behat BDD Testing" } -} +} \ No newline at end of file diff --git a/composer.lock b/composer.lock index 62788338..1110c4b5 100644 --- a/composer.lock +++ b/composer.lock @@ -3,7 +3,7 @@ "This file locks the dependencies of your project to a known state", "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" ], - "hash": "0ac85acececb32f472d8aa807ed054e7", + "hash": "d6834b50e3ea80f4c6f0a05707d0e5f1", "packages": [ { "name": "block8/b8framework", @@ -93,16 +93,16 @@ }, { "name": "monolog/monolog", - "version": "1.8.0", + "version": "1.9.1", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "392ef35fd470638e08d0160d6b1cbab63cb23174" + "reference": "65026b610f8c19e61d7242f600530677b0466aac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/392ef35fd470638e08d0160d6b1cbab63cb23174", - "reference": "392ef35fd470638e08d0160d6b1cbab63cb23174", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/65026b610f8c19e61d7242f600530677b0466aac", + "reference": "65026b610f8c19e61d7242f600530677b0466aac", "shasum": "" }, "require": { @@ -130,7 +130,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.8.x-dev" + "dev-master": "1.9.x-dev" } }, "autoload": { @@ -157,7 +157,7 @@ "logging", "psr-3" ], - "time": "2014-03-23 19:50:26" + "time": "2014-04-24 13:29:03" }, { "name": "pimple/pimple", @@ -298,17 +298,17 @@ }, { "name": "symfony/console", - "version": "v2.4.3", + "version": "v2.4.4", "target-dir": "Symfony/Component/Console", "source": { "type": "git", "url": "https://github.com/symfony/Console.git", - "reference": "ef20f1f58d7f693ee888353962bd2db336e3bbcb" + "reference": "2e452005b1e1d003d23702d227e23614679eb5ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/ef20f1f58d7f693ee888353962bd2db336e3bbcb", - "reference": "ef20f1f58d7f693ee888353962bd2db336e3bbcb", + "url": "https://api.github.com/repos/symfony/Console/zipball/2e452005b1e1d003d23702d227e23614679eb5ca", + "reference": "2e452005b1e1d003d23702d227e23614679eb5ca", "shasum": "" }, "require": { @@ -349,21 +349,21 @@ ], "description": "Symfony Console Component", "homepage": "http://symfony.com", - "time": "2014-03-01 17:35:04" + "time": "2014-04-27 13:34:57" }, { "name": "symfony/yaml", - "version": "v2.4.3", + "version": "v2.4.4", "target-dir": "Symfony/Component/Yaml", "source": { "type": "git", "url": "https://github.com/symfony/Yaml.git", - "reference": "77a41c2835ab7cfe8bf6d15e25d3af8f3eb3bacd" + "reference": "65539ecde838f9c0d18b006b2101e3deb4b5c9ff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/77a41c2835ab7cfe8bf6d15e25d3af8f3eb3bacd", - "reference": "77a41c2835ab7cfe8bf6d15e25d3af8f3eb3bacd", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/65539ecde838f9c0d18b006b2101e3deb4b5c9ff", + "reference": "65539ecde838f9c0d18b006b2101e3deb4b5c9ff", "shasum": "" }, "require": { @@ -398,10 +398,482 @@ ], "description": "Symfony Yaml Component", "homepage": "http://symfony.com", - "time": "2014-03-12 18:29:58" + "time": "2014-04-18 20:37:09" + } + ], + "packages-dev": [ + { + "name": "phpspec/prophecy", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "976a65af02a2a0e17ce6c949f7b43437205628bb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/976a65af02a2a0e17ce6c949f7b43437205628bb", + "reference": "976a65af02a2a0e17ce6c949f7b43437205628bb", + "shasum": "" + }, + "require-dev": { + "phpspec/phpspec": "2.0.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-0": { + "Prophecy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "http://phpspec.org", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2014-01-24 11:03:43" + }, + { + "name": "phpspec/prophecy-phpunit", + "version": "v1.0.1", + "target-dir": "Prophecy/PhpUnit", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy-phpunit.git", + "reference": "640c8c3bc9e02d7878e5ed22b1f79818d6bb6caf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy-phpunit/zipball/640c8c3bc9e02d7878e5ed22b1f79818d6bb6caf", + "reference": "640c8c3bc9e02d7878e5ed22b1f79818d6bb6caf", + "shasum": "" + }, + "require": { + "phpspec/prophecy": "~1.0" + }, + "suggest": { + "phpunit/phpunit": "if it is not installed globally" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Prophecy\\PhpUnit\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christophe Coevoet", + "email": "stof@notk.org" + } + ], + "description": "PhpUnit test case integrating the Prophecy mocking library", + "homepage": "http://phpspec.org", + "keywords": [ + "phpunit", + "prophecy" + ], + "time": "2014-03-03 23:03:12" + }, + { + "name": "phpunit/php-code-coverage", + "version": "1.2.17", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "6ef2bf3a1c47eca07ea95f0d8a902a6340390b34" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6ef2bf3a1c47eca07ea95f0d8a902a6340390b34", + "reference": "6ef2bf3a1c47eca07ea95f0d8a902a6340390b34", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "phpunit/php-file-iterator": ">=1.3.0@stable", + "phpunit/php-text-template": ">=1.2.0@stable", + "phpunit/php-token-stream": ">=1.1.3@stable" + }, + "require-dev": { + "phpunit/phpunit": "3.7.*@dev" + }, + "suggest": { + "ext-dom": "*", + "ext-xdebug": ">=2.0.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "PHP/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "time": "2014-03-28 10:53:45" + }, + { + "name": "phpunit/php-file-iterator", + "version": "1.3.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/acd690379117b042d1c8af1fafd61bde001bf6bb", + "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "File/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "time": "2013-10-10 15:34:57" + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", + "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "Text/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "time": "2014-01-30 17:20:04" + }, + { + "name": "phpunit/php-timer", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/19689d4354b295ee3d8c54b4f42c3efb69cbc17c", + "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "PHP/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2013-08-02 07:42:54" + }, + { + "name": "phpunit/php-token-stream", + "version": "1.2.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/ad4e1e23ae01b483c16f600ff1bebec184588e32", + "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "classmap": [ + "PHP/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "time": "2014-03-03 05:10:30" + }, + { + "name": "phpunit/phpunit", + "version": "3.7.37", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "ae6cefd7cc84586a5ef27e04bae11ee940ec63dc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/ae6cefd7cc84586a5ef27e04bae11ee940ec63dc", + "reference": "ae6cefd7cc84586a5ef27e04bae11ee940ec63dc", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-dom": "*", + "ext-json": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "php": ">=5.3.3", + "phpunit/php-code-coverage": "~1.2", + "phpunit/php-file-iterator": "~1.3", + "phpunit/php-text-template": "~1.1", + "phpunit/php-timer": "~1.0", + "phpunit/phpunit-mock-objects": "~1.2", + "symfony/yaml": "~2.0" + }, + "require-dev": { + "pear-pear.php.net/pear": "1.9.4" + }, + "suggest": { + "phpunit/php-invoker": "~1.1" + }, + "bin": [ + "composer/bin/phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.7.x-dev" + } + }, + "autoload": { + "classmap": [ + "PHPUnit/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "", + "../../symfony/yaml/" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "http://www.phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "time": "2014-04-30 12:24:19" + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/5794e3c5c5ba0fb037b11d8151add2a07fa82875", + "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "phpunit/php-text-template": ">=1.1.1@stable" + }, + "suggest": { + "ext-soap": "*" + }, + "type": "library", + "autoload": { + "classmap": [ + "PHPUnit/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Mock Object library for PHPUnit", + "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "keywords": [ + "mock", + "xunit" + ], + "time": "2013-01-13 10:24:48" } ], - "packages-dev": null, "aliases": [ ], diff --git a/phpci.yml b/phpci.yml index 52330436..9dda1fa4 100644 --- a/phpci.yml +++ b/phpci.yml @@ -6,12 +6,17 @@ build_settings: - "PHPCI/Command" # PHPMD complains about un-used parameters, but they are required. - "public/install.php" # PHPCS really doesn't like PHP mixed with HTML (and so it shouldn't) +setup: + composer: + action: "install" + test: php_mess_detector: - allowed_warnings: 35 # Set max warnings at the current level - Disallow any further errors creeping in. + allowed_warnings: 10 # Set max warnings at the current level - Disallow any further errors creeping in. php_code_sniffer: standard: "PSR2" php_loc: + php_unit: failure: email: diff --git a/public/assets/js/build-plugins/phpunit.js b/public/assets/js/build-plugins/phpunit.js new file mode 100644 index 00000000..c09855a9 --- /dev/null +++ b/public/assets/js/build-plugins/phpunit.js @@ -0,0 +1,65 @@ +var phpunitPlugin = PHPCI.UiPlugin.extend({ + id: 'build-phpunit-errors', + css: 'col-lg-12 col-md-12 col-sm-12 col-xs-12', + title: 'PHPUnit', + lastData: null, + displayOnUpdate: false, + box: true, + + register: function() { + var self = this; + var query = PHPCI.registerQuery('phpunit-data', -1, {key: 'phpunit-data'}) + + $(window).on('phpunit-data', function(data) { + self.onUpdate(data); + }); + + $(window).on('build-updated', function(data) { + if (data.queryData.status > 1) { + self.displayOnUpdate = true; + query(); + } + }); + }, + + render: function() { + + return $('' + + '' + + '' + + ' ' + + '' + + '
Test
'); + }, + + onUpdate: function(e) { + if (this.lastData && this.lastData[0]) { + return; + } + + this.lastData = e.queryData; + + var tests = this.lastData[0].meta_value; + var tbody = $('#phpunit-data tbody'); + tbody.empty(); + + for (var i in tests) { + + var row = $('' + + ''+tests[i].suite+'' + + '::'+tests[i].test+'
' + + ''+(tests[i].message || '')+'' + + ''); + + if (!tests[i].pass) { + row.addClass('danger'); + } else { + row.addClass('success'); + } + + tbody.append(row); + } + } +}); + +PHPCI.registerPlugin(new phpunitPlugin()); diff --git a/public/assets/js/build-plugins/warnings.js b/public/assets/js/build-plugins/warnings.js index 8b86a1e7..cc2db78f 100644 --- a/public/assets/js/build-plugins/warnings.js +++ b/public/assets/js/build-plugins/warnings.js @@ -3,10 +3,11 @@ var warningsPlugin = PHPCI.UiPlugin.extend({ css: 'col-lg-6 col-md-6 col-sm-12 col-xs-12', title: 'Quality Trend', keys: { - 'phpmd-warnings': 'PHPMD Warnings', - 'phpcs-warnings': 'PHPCS Warnings', - 'phpcs-errors': 'PHPCS Errors', - 'phplint-errors': 'PHPLint Errors' + 'phpmd-warnings': 'PHPMD Warnings', + 'phpcs-warnings': 'PHPCS Warnings', + 'phpcs-errors': 'PHPCS Errors', + 'phplint-errors': 'PHPLint Errors', + 'phpunit-errors': 'PHPUnit Errors' }, data: {}, displayOnUpdate: false, @@ -19,7 +20,7 @@ var warningsPlugin = PHPCI.UiPlugin.extend({ queries.push(PHPCI.registerQuery(key, -1, {num_builds: 10, key: key})); } - $(window).on('phpmd-warnings phpcs-warnings phpcs-errors phplint-errors', function(data) { + $(window).on('phpmd-warnings phpcs-warnings phpcs-errors phplint-errors phpunit-errors', function(data) { self.onUpdate(data); }); diff --git a/public/index.php b/public/index.php index e1754b62..134e9a7b 100644 --- a/public/index.php +++ b/public/index.php @@ -16,4 +16,3 @@ require_once('../bootstrap.php'); $fc = new PHPCI\Application($config, new b8\Http\Request()); print $fc->handleRequest(); - diff --git a/vars.php b/vars.php index 46b88c79..2408d41d 100644 --- a/vars.php +++ b/vars.php @@ -26,7 +26,6 @@ if (!defined('PHPCI_IS_CONSOLE')) { define('PHPCI_IS_CONSOLE', false); } -$isWin = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') ? true : false; if (!defined('IS_WIN')) { - define('IS_WIN', $isWin); + define('IS_WIN', ((strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') ? true : false)); }