diff --git a/PHPCI/Builder.php b/PHPCI/Builder.php index 6246cc2f..69e23ff1 100644 --- a/PHPCI/Builder.php +++ b/PHPCI/Builder.php @@ -36,11 +36,6 @@ class Builder implements LoggerAwareInterface */ public $ignore = array(); - /** - * @var string - */ - protected $ciDir; - /** * @var string */ @@ -287,10 +282,7 @@ class Builder implements LoggerAwareInterface */ protected function setupBuild() { - $buildId = 'project' . $this->build->getProject()->getId() - . '-build' . $this->build->getId(); - $this->ciDir = dirname(dirname(__FILE__) . '/../') . '/'; - $this->buildPath = $this->ciDir . 'build/' . $buildId . '/'; + $this->buildPath = PHPCI_DIR . 'PHPCI/build/' . $this->build->getId() . '/'; $this->build->currentBuildPath = $this->buildPath; $this->interpolator->setupInterpolationVars( diff --git a/PHPCI/Command/DaemoniseCommand.php b/PHPCI/Command/DaemoniseCommand.php index 2850ff5f..d2f1f236 100644 --- a/PHPCI/Command/DaemoniseCommand.php +++ b/PHPCI/Command/DaemoniseCommand.php @@ -75,7 +75,7 @@ class DaemoniseCommand extends Command $this->run = true; $this->sleep = 0; $runner = new RunCommand($this->logger); - $runner->setBaxBuilds(1); + $runner->setMaxBuilds(1); $emptyInput = new ArgvInput(array()); diff --git a/PHPCI/Command/RunCommand.php b/PHPCI/Command/RunCommand.php index 6f7ea0d1..8149d362 100644 --- a/PHPCI/Command/RunCommand.php +++ b/PHPCI/Command/RunCommand.php @@ -9,6 +9,7 @@ namespace PHPCI\Command; +use b8\Config; use Monolog\Logger; use PHPCI\Logging\BuildDBLogHandler; use PHPCI\Logging\LoggedBuildContextTidier; @@ -73,14 +74,15 @@ class RunCommand extends Command // For verbose mode we want to output all informational and above // messages to the symphony output interface. - if ($input->hasOption('verbose')) { + if ($input->getOption('verbose')) { $this->logger->pushHandler( new OutputLogHandler($this->output, Logger::INFO) ); } - $this->logger->pushProcessor(new LoggedBuildContextTidier()); + $running = $this->validateRunningBuilds(); + $this->logger->pushProcessor(new LoggedBuildContextTidier()); $this->logger->addInfo("Finding builds to process"); $store = Factory::getStore('Build'); $result = $store->getByStatus(0, $this->maxBuilds); @@ -89,10 +91,17 @@ class RunCommand extends Command $builds = 0; foreach ($result['items'] as $build) { - $builds++; $build = BuildFactory::getBuild($build); + // Skip build (for now) if there's already a build running in that project: + if (in_array($build->getProjectId(), $running)) { + $this->logger->addInfo('Skipping Build #'.$build->getId() . ' - Project build already in progress.'); + continue; + } + + $builds++; + try { // Logging relevant to this build should be stored // against the build itself. @@ -118,8 +127,53 @@ class RunCommand extends Command return $builds; } - public function setBaxBuilds($numBuilds) + public function setMaxBuilds($numBuilds) { $this->maxBuilds = (int)$numBuilds; } + + protected function validateRunningBuilds() + { + /** @var \PHPCI\Store\BuildStore $store */ + $store = Factory::getStore('Build'); + $running = $store->getByStatus(1); + $rtn = array(); + + $timeout = Config::getInstance()->get('phpci.build.failed_after', 1800); + + foreach ($running['items'] as $build) { + /** @var \PHPCI\Model\Build $build */ + $build = BuildFactory::getBuild($build); + + $now = time(); + $start = $build->getStarted()->getTimestamp(); + + if (($now - $start) > $timeout) { + $this->logger->addInfo('Build #'.$build->getId().' marked as failed due to timeout.'); + $build->setStatus(Build::STATUS_FAILED); + $store->save($build); + $this->removeBuildDirectory($build); + continue; + } + + $rtn[$build->getProjectId()] = true; + } + + return $rtn; + } + + protected function removeBuildDirectory($build) + { + $buildPath = PHPCI_DIR . 'PHPCI/build/' . $build->getId() . '/'; + + if (is_dir($buildPath)) { + $cmd = 'rm -Rf "%s"'; + + if (IS_WIN) { + $cmd = 'rmdir /S /Q "%s"'; + } + + shell_exec($cmd); + } + } } diff --git a/PHPCI/Controller/SettingsController.php b/PHPCI/Controller/SettingsController.php index 3589cd5e..bc5558ba 100644 --- a/PHPCI/Controller/SettingsController.php +++ b/PHPCI/Controller/SettingsController.php @@ -45,8 +45,14 @@ class SettingsController extends Controller $emailSettings = $this->settings['phpci']['email_settings']; } + $buildSettings = array(); + if (isset($this->settings['phpci']['build'])) { + $buildSettings = $this->settings['phpci']['build']; + } + $this->view->github = $this->getGithubForm(); $this->view->emailSettings = $this->getEmailForm($emailSettings); + $this->view->buildSettings = $this->getBuildForm($buildSettings); $this->view->isWriteable = $this->canWriteConfig(); if (!empty($this->settings['phpci']['github']['token'])) { @@ -87,6 +93,21 @@ class SettingsController extends Controller die; } + public function build() + { + $this->settings['phpci']['build'] = $this->getParams(); + + $error = $this->storeSettings(); + + if ($error) { + header('Location: ' . PHPCI_URL . 'settings?saved=2'); + } else { + header('Location: ' . PHPCI_URL . 'settings?saved=1'); + } + + die; + } + /** * Github redirects users back to this URL when t */ @@ -249,4 +270,36 @@ class SettingsController extends Controller { return is_writeable(APPLICATION_PATH . 'PHPCI/config.yml'); } + + protected function getBuildForm($values = array()) + { + $form = new Form(); + $form->setMethod('POST'); + $form->setAction(PHPCI_URL . 'settings/build'); + + $field = new Form\Element\Select('failed_after'); + $field->setRequired(false); + $field->setLabel('Consider a build failed after'); + $field->setClass('form-control'); + $field->setContainerClass('form-group'); + $field->setOptions([ + 300 => '5 Minutes', + 900 => '15 Minutes', + 1800 => '30 Minutes', + 3600 => '1 Hour', + 10800 => '3 Hours', + ]); + $field->setValue(1800); + $form->addField($field); + + + $field = new Form\Element\Submit(); + $field->setValue('Save »'); + $field->setClass('btn btn-success pull-right'); + $form->addField($field); + + $form->setValues($values); + + return $form; + } } diff --git a/PHPCI/View/Settings/index.phtml b/PHPCI/View/Settings/index.phtml index 9724053a..8637ad2b 100644 --- a/PHPCI/View/Settings/index.phtml +++ b/PHPCI/View/Settings/index.phtml @@ -28,6 +28,13 @@

+
+

Build Settings

+
+ +
+
+

Github Application