diff --git a/PHPCI/Application.php b/PHPCI/Application.php index 5de5a69a..47f13217 100644 --- a/PHPCI/Application.php +++ b/PHPCI/Application.php @@ -2,52 +2,52 @@ /** * PHPCI - Continuous Integration for PHP * -* @copyright Copyright 2013, Block 8 Limited. -* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md -* @link http://www.phptesting.org/ +* @copyright Copyright 2013, Block 8 Limited. +* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md +* @link http://www.phptesting.org/ */ namespace PHPCI; -use b8, - b8\Registry; + +use b8; +use b8\Registry; /** * PHPCI Front Controller -* @author Dan Cryer +* @author Dan Cryer */ class Application extends b8\Application { - public function handleRequest() - { - $controllerName = \b8\Registry::getInstance()->get('ControllerName'); + public function handleRequest() + { + $controllerName = \b8\Registry::getInstance()->get('ControllerName'); + $sessionAction = ($controllerName == 'Session' && in_array($this->action, array('login', 'logout'))); + $webhookAction = in_array($controllerName, array('Bitbucket', 'Github')); - if(!in_array($controllerName, array('Bitbucket', 'Github')) && !($controllerName == 'Session' && in_array($this->action, array('login', 'logout')))) - { - $this->validateSession(); - } + if (!$webhookAction && !$sessionAction) { + $this->validateSession(); + } - $view = new b8\View('Layout'); - $view->content = parent::handleRequest(); + $view = new b8\View('Layout'); + $view->content = parent::handleRequest(); - return $view->render(); - } + return $view->render(); + } - protected function validateSession() - { - if(!empty($_SESSION['user_id'])) - { - $user = b8\Store\Factory::getStore('User')->getByPrimaryKey($_SESSION['user_id']); + protected function validateSession() + { + if (!empty($_SESSION['user_id'])) { + $user = b8\Store\Factory::getStore('User')->getByPrimaryKey($_SESSION['user_id']); - if($user) - { - Registry::getInstance()->set('user', $user); - return; - } + if ($user) { + Registry::getInstance()->set('user', $user); + return; + } - unset($_SESSION['user_id']); - } + unset($_SESSION['user_id']); + } - header('Location: /session/login'); - die; - } -} \ No newline at end of file + header('Location: /session/login'); + die; + } +} diff --git a/PHPCI/BuildFactory.php b/PHPCI/BuildFactory.php index 96d1da18..77917c26 100644 --- a/PHPCI/BuildFactory.php +++ b/PHPCI/BuildFactory.php @@ -2,42 +2,41 @@ /** * PHPCI - Continuous Integration for PHP * -* @copyright Copyright 2013, Block 8 Limited. -* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md -* @link http://www.phptesting.org/ +* @copyright Copyright 2013, Block 8 Limited. +* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md +* @link http://www.phptesting.org/ */ namespace PHPCI; -use PHPCI\Model\Build, - PHPCI\Model\Build\LocalBuild, - PHPCI\Model\Build\GithubBuild, - PHPCI\Model\Build\BitbucketBuild; + +use PHPCI\Model\Build; +use PHPCI\Model\Build\LocalBuild; +use PHPCI\Model\Build\GithubBuild; +use PHPCI\Model\Build\BitbucketBuild; /** * PHPCI Build Factory - Takes in a generic "Build" and returns a type-specific build model. -* @author Dan Cryer +* @author Dan Cryer */ class BuildFactory { - public static function getBuild(Build $base) - { - switch($base->getProject()->getType()) - { - case 'local': - $type = 'LocalBuild'; - break; + public static function getBuild(Build $base) + { + switch($base->getProject()->getType()) + { + case 'local': + $type = 'LocalBuild'; + break; + case 'github': + $type = 'GithubBuild'; + break; + case 'bitbucket': + $type = 'BitbucketBuild'; + break; + } - case 'github': - $type = 'GithubBuild'; - break; + $type = '\\PHPCI\\Model\\Build\\' . $type; - case 'bitbucket': - $type = 'BitbucketBuild'; - break; - } - - $type = '\\PHPCI\\Model\\Build\\' . $type; - - return new $type($base->getDataArray()); - } -} \ No newline at end of file + return new $type($base->getDataArray()); + } +} diff --git a/PHPCI/Builder.php b/PHPCI/Builder.php index 9b68ec6a..da0efbfc 100644 --- a/PHPCI/Builder.php +++ b/PHPCI/Builder.php @@ -2,283 +2,344 @@ /** * PHPCI - Continuous Integration for PHP * -* @copyright Copyright 2013, Block 8 Limited. -* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md -* @link http://www.phptesting.org/ +* @copyright Copyright 2013, Block 8 Limited. +* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md +* @link http://www.phptesting.org/ */ namespace PHPCI; + use PHPCI\Model\Build; use b8\Store; use Symfony\Component\Yaml\Parser as YamlParser; /** * PHPCI Build Runner -* @author Dan Cryer +* @author Dan Cryer */ class Builder { - public $buildPath; - public $ignore = array(); + /** + * @var string + */ + public $buildPath; - protected $ciDir; - protected $directory; - protected $success = true; - protected $log = ''; - protected $verbose = false; - protected $plugins = array(); - protected $build; - protected $logCallback; - protected $config; + /** + * @var string[] + */ + public $ignore = array(); - public function __construct(Build $build, $logCallback = null) - { - $this->build = $build; - $this->store = Store\Factory::getStore('Build'); + /** + * @var string + */ + protected $ciDir; - if(!is_null($logCallback) && is_callable($logCallback)) - { - $this->logCallback = $logCallback; - } - } + /** + * @var string + */ + protected $directory; - public function setConfigArray(array $config) - { - $this->config = $config; - } + /** + * @var bool + */ + protected $success = true; - public function getConfig($key) - { - return isset($this->config[$key]) ? $this->config[$key] : null; - } + /** + * @var string + */ + protected $log = ''; - public function execute() - { - $this->build->setStatus(1); - $this->build->setStarted(new \DateTime()); - $this->store->save($this->build); - $this->build->sendStatusPostback(); + /** + * @var bool + */ + protected $verbose = false; - if($this->setupBuild()) - { - $this->executePlugins('setup'); - $this->executePlugins('test'); + /** + * @var bool[] + */ + protected $plugins = array(); - $this->log(''); + /** + * @var \PHPCI\Model\Build + */ + protected $build; - $this->executePlugins('complete'); + /** + * @var callable + */ + protected $logCallback; - if($this->success) - { - $this->executePlugins('success'); - $this->logSuccess('BUILD SUCCESSFUL!'); - $this->build->setStatus(2); - } - else - { - $this->executePlugins('failure'); - $this->logFailure('BUILD FAILED!'); - $this->build->setStatus(3); - } + /** + * @var array + */ + protected $config; - $this->log(''); - } - else - { - $this->build->setStatus(3); - } + /** + * Set up the builder. + * @param \PHPCI\Model\Build + * @param callable + */ + public function __construct(Build $build, $logCallback = null) + { + $this->build = $build; + $this->store = Store\Factory::getStore('Build'); - $this->removeBuild(); + if (!is_null($logCallback) && is_callable($logCallback)) { + $this->logCallback = $logCallback; + } + } - $this->build->sendStatusPostback(); - $this->build->setFinished(new \DateTime()); - $this->build->setLog($this->log); - $this->build->setPlugins(json_encode($this->plugins)); - $this->store->save($this->build); - } + /** + * Set the config array, as read from phpci.yml + * @param array + */ + public function setConfigArray(array $config) + { + $this->config = $config; + } - public function executeCommand() - { - $command = call_user_func_array('sprintf', func_get_args()); - - $this->log('Executing: ' . $command, ' '); + /** + * Access a variable from the phpci.yml file. + * @param string + */ + public function getConfig($key) + { + return isset($this->config[$key]) ? $this->config[$key] : null; + } - $output = ''; - $status = 0; - exec($command, $output, $status); + /** + * Run the active build. + */ + public function execute() + { + // Update the build in the database, ping any external services. + $this->build->setStatus(1); + $this->build->setStarted(new \DateTime()); + $this->store->save($this->build); + $this->build->sendStatusPostback(); - if(!empty($output) && ($this->verbose || $status != 0)) - { - $this->log($output, ' '); - } + try { + if ($this->setupBuild()) { + // Run setup steps: + $this->executePlugins('setup'); - return ($status == 0) ? true : false; - } + // Run the any tests: + $this->executePlugins('test'); + $this->log(''); - public function log($message, $prefix = '') - { + // Run build complete steps: + $this->executePlugins('complete'); - if(is_array($message)) - { - - foreach ($message as $item) - { - if(is_callable($this->logCallback)) - { - $this->logCallback($prefix . $item); - } - - $this->log .= $prefix . $item . PHP_EOL; - } - - } - else - { - $message = $prefix . $message; + // Run success or failure plugins: + if ($this->success) { + $this->executePlugins('success'); + $this->logSuccess('BUILD SUCCESSFUL!'); + $this->build->setStatus(2); + } else { + $this->executePlugins('failure'); + $this->logFailure('BUILD FAILED!'); + $this->build->setStatus(3); + } - $this->log .= $message . PHP_EOL; + $this->log(''); + } else { + $this->build->setStatus(3); + } + } catch (\Exception $ex) { + $this->logFailure($ex->getMessage()); + $this->build->setStatus(3); + } + + // Clean up: + $this->removeBuild(); - if(isset($this->logCallback) && is_callable($this->logCallback)) - { - $cb = $this->logCallback; - $cb($message); - } - } + // Update the build in the database, ping any external services, etc. + $this->build->sendStatusPostback(); + $this->build->setFinished(new \DateTime()); + $this->build->setLog($this->log); + $this->build->setPlugins(json_encode($this->plugins)); + $this->store->save($this->build); + } - $this->build->setLog($this->log); - $this->build->setPlugins(json_encode($this->plugins)); - $this->store->save($this->build); - } + /** + * Used by this class, and plugins, to execute shell commands. + */ + public function executeCommand() + { + $command = call_user_func_array('sprintf', func_get_args()); + + $this->log('Executing: ' . $command, ' '); - public function logSuccess($message) - { - $this->log("\033[0;32m" . $message . "\033[0m"); - } + $output = ''; + $status = 0; + exec($command, $output, $status); - public function logFailure($message) - { - $this->log("\033[0;31m" . $message . "\033[0m"); - } + if (!empty($output) && ($this->verbose || $status != 0)) { + $this->log($output, ' '); + } - protected function setupBuild() - { - $commitId = $this->build->getCommitId(); - $buildId = 'project' . $this->build->getProject()->getId() . '-build' . $this->build->getId(); - $this->ciDir = realpath(dirname(__FILE__) . '/../') . '/'; - $this->buildPath = $this->ciDir . 'build/' . $buildId . '/'; + return ($status == 0) ? true : false; + } - // Create a working copy of the project: - if(!$this->build->createWorkingCopy($this, $this->buildPath)) { - return false; - } + /** + * Add an entry to the build log. + * @param string|string[] + * @param string + */ + public function log($message, $prefix = '') + { + if (is_array($message)) { + foreach ($message as $item) { + if (is_callable($this->logCallback)) { + call_user_func_array($this->logCallback, $prefix . $item); + } + + $this->log .= $prefix . $item . PHP_EOL; + } + } else { + $message = $prefix . $message; + $this->log .= $message . PHP_EOL; - // Does the project's phpci.yml request verbose mode? - if(!isset($this->config['build_settings']['verbose']) || !$this->config['build_settings']['verbose']) { - $this->verbose = false; - } - else { - $this->verbose = true; - } + if (isset($this->logCallback) && is_callable($this->logCallback)) { + call_user_func_array($this->logCallback, $prefix . $item); + } + } - // Does the project have any paths it wants plugins to ignore? - if(isset($this->config['build_settings']['ignore'])) { - $this->ignore = $this->config['build_settings']['ignore']; - } + $this->build->setLog($this->log); + $this->build->setPlugins(json_encode($this->plugins)); + $this->store->save($this->build); + } - $this->logSuccess('Working copy created: ' . $this->buildPath); - return true; - } + /** + * Add a success-coloured message to the log. + * @param string + */ + public function logSuccess($message) + { + $this->log("\033[0;32m" . $message . "\033[0m"); + } - protected function removeBuild() - { - $this->log('Removing build.'); - shell_exec(sprintf('rm -Rf "%s"', $this->buildPath)); - } + /** + * Add a failure-coloured message to the log. + * @param string + */ + public function logFailure($message) + { + $this->log("\033[0;31m" . $message . "\033[0m"); + } - protected function executePlugins($stage) - { - // Ignore any stages for which we don't have plugins set: - if(!array_key_exists($stage, $this->config) || !is_array($this->config[$stage])) - { - return; - } + /** + * Set up a working copy of the project for building. + */ + protected function setupBuild() + { + $commitId = $this->build->getCommitId(); + $buildId = 'project' . $this->build->getProject()->getId() . '-build' . $this->build->getId(); + $this->ciDir = realpath(dirname(__FILE__) . '/../') . '/'; + $this->buildPath = $this->ciDir . 'build/' . $buildId . '/'; - foreach($this->config[$stage] as $plugin => $options) - { - $this->log(''); - $this->log('RUNNING PLUGIN: ' . $plugin); + // Create a working copy of the project: + if (!$this->build->createWorkingCopy($this, $this->buildPath)) { + return false; + } - // Is this plugin allowed to fail? - if($stage == 'test' && !isset($options['allow_failures'])) - { - $options['allow_failures'] = false; - } + // Does the project's phpci.yml request verbose mode? + if (!isset($this->config['build_settings']['verbose']) || !$this->config['build_settings']['verbose']) { + $this->verbose = false; + } else { + $this->verbose = true; + } - $class = str_replace('_', ' ', $plugin); - $class = ucwords($class); - $class = 'PHPCI\\Plugin\\' . str_replace(' ', '', $class); + // Does the project have any paths it wants plugins to ignore? + if (isset($this->config['build_settings']['ignore'])) { + $this->ignore = $this->config['build_settings']['ignore']; + } - if(!class_exists($class)) - { - $this->logFailure('Plugin does not exist: ' . $plugin); + $this->logSuccess('Working copy created: ' . $this->buildPath); + return true; + } - if($stage == 'test') - { - $this->plugins[$plugin] = false; + /** + * Execute a the appropriate set of plugins for a given build stage. + */ + protected function executePlugins($stage) + { + // Ignore any stages for which we don't have plugins set: + if (!array_key_exists($stage, $this->config) || !is_array($this->config[$stage])) { + return; + } - if(!$options['allow_failures']) - { - $this->success = false; - } - } + foreach ($this->config[$stage] as $plugin => $options) { + $this->log(''); + $this->log('RUNNING PLUGIN: ' . $plugin); - continue; - } + // Is this plugin allowed to fail? + if ($stage == 'test' && !isset($options['allow_failures'])) { + $options['allow_failures'] = false; + } - try - { - $obj = new $class($this, $options); + $class = str_replace('_', ' ', $plugin); + $class = ucwords($class); + $class = 'PHPCI\\Plugin\\' . str_replace(' ', '', $class); - if(!$obj->execute()) - { - if($stage == 'test') - { - $this->plugins[$plugin] = false; + if (!class_exists($class)) { + $this->logFailure('Plugin does not exist: ' . $plugin); - if(!$options['allow_failures']) - { - $this->success = false; - } - } + if ($stage == 'test') { + $this->plugins[$plugin] = false; - $this->logFailure('PLUGIN STATUS: FAILED'); - continue; - } - } - catch(\Exception $ex) - { - $this->logFailure('EXCEPTION: ' . $ex->getMessage()); + if (!$options['allow_failures']) { + $this->success = false; + } + } - if($stage == 'test') - { - $this->plugins[$plugin] = false; + continue; + } - if(!$options['allow_failures']) - { - $this->success = false; - } - } + try { + $obj = new $class($this, $options); - $this->logFailure('PLUGIN STATUS: FAILED'); - continue; - } + if (!$obj->execute()) { + if ($stage == 'test') { + $this->plugins[$plugin] = false; - if($stage == 'test') - { - $this->plugins[$plugin] = true; - } + if (!$options['allow_failures']) { + $this->success = false; + } + } - $this->logSuccess('PLUGIN STATUS: SUCCESS!'); - } - } -} \ No newline at end of file + $this->logFailure('PLUGIN STATUS: FAILED'); + continue; + } + } catch (\Exception $ex) { + $this->logFailure('EXCEPTION: ' . $ex->getMessage()); + + if ($stage == 'test') { + $this->plugins[$plugin] = false; + + if (!$options['allow_failures']) { + $this->success = false; + } + } + + $this->logFailure('PLUGIN STATUS: FAILED'); + continue; + } + + if ($stage == 'test') { + $this->plugins[$plugin] = true; + } + + $this->logSuccess('PLUGIN STATUS: SUCCESS!'); + } + } + + /** + * Clean up our working copy. + */ + protected function removeBuild() + { + $this->log('Removing build.'); + shell_exec(sprintf('rm -Rf "%s"', $this->buildPath)); + } +} diff --git a/PHPCI/Plugin.php b/PHPCI/Plugin.php index 1ab3f170..5aa06e9e 100644 --- a/PHPCI/Plugin.php +++ b/PHPCI/Plugin.php @@ -2,19 +2,19 @@ /** * PHPCI - Continuous Integration for PHP * -* @copyright Copyright 2013, Block 8 Limited. -* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md -* @link http://www.phptesting.org/ +* @copyright Copyright 2013, Block 8 Limited. +* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md +* @link http://www.phptesting.org/ */ namespace PHPCI; /** * PHPCI Plugin Interface - Used by all build plugins. -* @author Dan Cryer +* @author Dan Cryer */ interface Plugin { - public function __construct(\PHPCI\Builder $phpci, array $options = array()); - public function execute(); -} \ No newline at end of file + public function __construct(\PHPCI\Builder $phpci, array $options = array()); + public function execute(); +} diff --git a/bootstrap.php b/bootstrap.php index f63d4b03..018883ef 100644 --- a/bootstrap.php +++ b/bootstrap.php @@ -2,48 +2,45 @@ /** * PHPCI - Continuous Integration for PHP * -* @copyright Copyright 2013, Block 8 Limited. -* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md -* @link http://www.phptesting.org/ +* @copyright Copyright 2013, Block 8 Limited. +* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md +* @link http://www.phptesting.org/ */ // Let PHP take a guess as to the default timezone, if the user hasn't set one: date_default_timezone_set(@date_default_timezone_get()); // Set up a basic autoloader for PHPCI: -spl_autoload_register(function ($class) -{ - $file = str_replace(array('\\', '_'), '/', $class); - $file .= '.php'; +$autoload = function ($class) { + $file = str_replace(array('\\', '_'), '/', $class); + $file .= '.php'; - if(substr($file, 0, 1) == '/') - { - $file = substr($file, 1); - } + if (substr($file, 0, 1) == '/') { + $file = substr($file, 1); + } - if(is_file(dirname(__FILE__) . '/' . $file)) - { - include(dirname(__FILE__) . '/' . $file); + if (is_file(dirname(__FILE__) . '/' . $file)) { + include(dirname(__FILE__) . '/' . $file); + return; + } +}; - return; - } -}, true, true); +spl_autoload_register($autoload, true, true); // Define our APPLICATION_PATH, if not already defined: -if(!defined('APPLICATION_PATH')) { - define('APPLICATION_PATH', dirname(__FILE__) . '/'); +if (!defined('APPLICATION_PATH')) { + define('APPLICATION_PATH', dirname(__FILE__) . '/'); } // Load Composer autoloader: require_once(APPLICATION_PATH . 'vendor/autoload.php'); // Load configuration if present: -if(file_exists(APPLICATION_PATH . 'config.php')) -{ - require(APPLICATION_PATH . 'config.php'); +if (file_exists(APPLICATION_PATH . 'config.php')) { + require(APPLICATION_PATH . 'config.php'); } // Set up the registry: b8\Registry::getInstance()->set('app_namespace', 'PHPCI'); b8\Registry::getInstance()->set('DefaultController', 'Index'); -b8\Registry::getInstance()->set('ViewPath', dirname(__FILE__) . '/PHPCI/View/'); \ No newline at end of file +b8\Registry::getInstance()->set('ViewPath', dirname(__FILE__) . '/PHPCI/View/'); diff --git a/console b/console index 464ca3b0..f62a3aac 100755 --- a/console +++ b/console @@ -3,9 +3,9 @@ /** * PHPCI - Continuous Integration for PHP * -* @copyright Copyright 2013, Block 8 Limited. -* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md -* @link http://www.phptesting.org/ +* @copyright Copyright 2013, Block 8 Limited. +* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md +* @link http://www.phptesting.org/ */ define('PHPCI_BIN_DIR', dirname(__FILE__) . '/vendor/bin/'); @@ -13,17 +13,17 @@ define('PHPCI_DIR', dirname(__FILE__) . '/'); // If this is the first time ./console has been run, we probably don't have Composer or any of our dependencies yet. // So we need to install and run Composer. -if(!file_exists(PHPCI_DIR . 'vendor/autoload.php') || !file_exists(PHPCI_DIR . 'composer.phar')) { - print 'INSTALLING: Composer' . PHP_EOL; +if (!file_exists(PHPCI_DIR . 'vendor/autoload.php') || !file_exists(PHPCI_DIR . 'composer.phar')) { + print 'INSTALLING: Composer' . PHP_EOL; file_put_contents(PHPCI_DIR . 'composerinstaller.php', file_get_contents('https://getcomposer.org/installer')); shell_exec('php ' . PHPCI_DIR . 'composerinstaller.php'); unlink(PHPCI_DIR . 'composerinstaller.php'); print 'RUNNING: Composer' . PHP_EOL; shell_exec('php '.PHPCI_DIR.'composer.phar install'); -} +} -require('bootstrap.php'); +require('bootstrap.php'); use PHPCI\Command\RunCommand; use PHPCI\Command\GenerateCommand; diff --git a/index.php b/index.php index 09fd8c7d..622e04c2 100644 --- a/index.php +++ b/index.php @@ -12,4 +12,4 @@ session_start(); require_once('bootstrap.php'); $fc = new PHPCI\Application(); -print $fc->handleRequest(); \ No newline at end of file +print $fc->handleRequest();