/** * Start the worker. */ public function startWorker() { $this->pheanstalk->watch($this->queue); $this->pheanstalk->ignore('default'); $buildStore = Factory::getStore('Build'); while ($this->run) { // Get a job from the queue: $job = $this->pheanstalk->reserve(); $this->checkJobLimit(); // Get the job data and run the job: $jobData = json_decode($job->getData(), true); if (!$this->verifyJob($job, $jobData)) { continue; } $this->logger->addInfo('Received build #' . $jobData['build_id'] . ' from Beanstalkd'); // If the job comes with config data, reset our config and database connections // and then make sure we kill the worker afterwards: if (!empty($jobData['config'])) { $this->logger->addDebug('Using job-specific config.'); $currentConfig = Config::getInstance()->getArray(); $config = new Config($jobData['config']); Database::reset($config); } try { $build = BuildFactory::getBuildById($jobData['build_id']); } catch (\Exception $ex) { $this->logger->addWarning('Build #' . $jobData['build_id'] . ' does not exist in the database.'); $this->pheanstalk->delete($job); } try { // Logging relevant to this build should be stored // against the build itself. $buildDbLog = new BuildDBLogHandler($build, Logger::INFO); $this->logger->pushHandler($buildDbLog); $builder = new Builder($build, $this->logger); $builder->execute(); // After execution we no longer want to record the information // back to this specific build so the handler should be removed. $this->logger->popHandler($buildDbLog); } catch (\PDOException $ex) { // If we've caught a PDO Exception, it is probably not the fault of the build, but of a failed // connection or similar. Release the job and kill the worker. $this->run = false; $this->pheanstalk->release($job); } catch (\Exception $ex) { $build->setStatus(Build::STATUS_FAILED); $build->setFinished(new \DateTime()); $build->setLog($build->getLog() . PHP_EOL . PHP_EOL . $ex->getMessage()); $buildStore->save($build); $build->sendStatusPostback(); } // Reset the config back to how it was prior to running this job: if (!empty($currentConfig)) { $config = new Config($currentConfig); Database::reset($config); } // Delete the job when we're done: $this->pheanstalk->delete($job); } }
/** * Initialise the controller, set up stores and services. */ public function init() { $this->buildStore = Store\Factory::getStore('Build'); $this->projectStore = Store\Factory::getStore('Project'); $this->projectService = new ProjectService($this->projectStore); $this->buildService = new BuildService($this->buildStore); }
/** * Creates an admin user in the existing PHPCI database */ protected function execute(InputInterface $input, OutputInterface $output) { require PHPCI_DIR . 'bootstrap.php'; // Try to create a user account: $adminEmail = $this->ask('Admin email address: ', true, FILTER_VALIDATE_EMAIL); if (empty($adminEmail)) { return; } $adminPass = $this->ask('Admin password: '******'Admin name: '); try { $user = new \PHPCI\Model\User(); $user->setEmail($adminEmail); $user->setName($adminName); $user->setIsAdmin(1); $user->setHash(password_hash($adminPass, PASSWORD_DEFAULT)); $store = \b8\Store\Factory::getStore('User'); $store->save($user); print 'User account created!' . PHP_EOL; } catch (\Exception $ex) { print 'There was a problem creating your account. :(' . PHP_EOL; print $ex->getMessage(); print PHP_EOL; } }
public function change() { $count = 100; $this->metaStore = \b8\Store\Factory::getStore('BuildMeta'); $this->errorStore = \b8\Store\Factory::getStore('BuildError'); while ($count == 100) { $data = $this->metaStore->getErrorsForUpgrade(100); $count = count($data); /** @var \PHPCI\Model\BuildMeta $meta */ foreach ($data as $meta) { try { switch ($meta->getMetaKey()) { case 'phpmd-data': $this->processPhpMdMeta($meta); break; case 'phpcs-data': $this->processPhpCsMeta($meta); break; case 'phpdoccheck-data': $this->processPhpDocCheckMeta($meta); break; case 'phpcpd-data': $this->processPhpCpdMeta($meta); break; case 'technicaldebt-data': $this->processTechnicalDebtMeta($meta); break; } } catch (\Exception $ex) { } $this->metaStore->delete($meta); } } }
/** * @param $buildId * @return Build * @throws \Exception */ public static function getBuildById($buildId) { $build = Factory::getStore('Build')->getById($buildId); if (empty($build)) { throw new \Exception('Build ID ' . $buildId . ' does not exist.'); } return self::getBuild($build); }
/** * @param string $store Name of the store you want to load. * @return \b8\Store */ public static function get($store) { $namespace = self::getModelNamespace($store); if (!is_null($namespace)) { return Factory::getStore($store, $namespace); } return null; }
protected function write(array $record) { $message = (string) $record['message']; $message = str_replace($this->build->currentBuildPath, '/', $message); $this->logValue .= $message . PHP_EOL; $this->build->setLog($this->logValue); Factory::getStore('Build')->save($this->build); }
/** * Loops through running. */ protected function execute(InputInterface $input, OutputInterface $output) { $runner = new RunCommand($this->logger); $runner->setMaxBuilds(1); $runner->setDaemon(false); /** @var \PHPCI\Store\BuildStore $store */ $store = Factory::getStore('Build'); $service = new BuildService($store); $lastBuild = array_shift($store->getLatestBuilds(null, 1)); $service->createDuplicateBuild($lastBuild); $runner->run(new ArgvInput(array()), $output); }
/** * Return the previous build from a specific branch, for this project. * @param string $branch * @return mixed|null */ public function getPreviousBuild($branch = 'master') { $criteria = array('branch' => $branch, 'project_id' => $this->getId()); $order = array('id' => 'DESC'); $builds = Store\Factory::getStore('Build')->getWhere($criteria, 1, 1, array(), $order); if (is_array($builds['items']) && count($builds['items'])) { $previous = array_shift($builds['items']); if (isset($previous) && $previous instanceof Build) { return $previous; } } return null; }
/** * List project groups. */ public function index() { $this->requireAdmin(); $groups = array(); $groupList = $this->groupStore->getWhere(array(), 100, 0, array(), array('title' => 'ASC')); foreach ($groupList['items'] as $group) { $thisGroup = array('title' => $group->getTitle(), 'id' => $group->getId()); $projects = b8\Store\Factory::getStore('Project')->getByGroupId($group->getId()); $thisGroup['projects'] = $projects['items']; $groups[] = $thisGroup; } $this->view->groups = $groups; }
public function change() { $table = $this->table('project_group'); $table->addColumn('title', 'string', array('limit' => 100, 'null' => false)); $table->save(); $group = new \PHPCI\Model\ProjectGroup(); $group->setTitle('Projects'); /** @var \PHPCI\Model\ProjectGroup $group */ $group = \b8\Store\Factory::getStore('ProjectGroup')->save($group); $table = $this->table('project'); $table->addColumn('group_id', 'integer', array('signed' => true, 'null' => false, 'default' => $group->getId())); $table->addForeignKey('group_id', 'project_group', 'id', array('delete' => 'RESTRICT', 'update' => 'CASCADE')); $table->save(); }
public function getLatestBuild($branch = 'master', $status = null) { $criteria = array('branch' => $branch, 'project_id' => $this->getId()); if (isset($status)) { $criteria['status'] = $status; } $order = array('id' => 'DESC'); $builds = Store\Factory::getStore('Build')->getWhere($criteria, 1, 0, array(), $order); if (is_array($builds['items']) && count($builds['items'])) { $latest = array_shift($builds['items']); if (isset($latest) && $latest instanceof Build) { return $latest; } } return null; }
protected function execute(InputInterface $input, OutputInterface $output) { $this->output = $output; // For verbose mode we want to output all informational and above // messages to the symphony output interface. if ($input->hasOption('verbose') && $input->getOption('verbose')) { $this->logger->pushHandler(new OutputLogHandler($this->output, Logger::INFO)); } $store = Factory::getStore('Build'); $result = $store->getByStatus(0); $this->logger->addInfo(Lang::get('found_n_builds', count($result['items']))); $buildService = new BuildService($store); while (count($result['items'])) { $build = array_shift($result['items']); $build = BuildFactory::getBuild($build); $this->logger->addInfo('Added build #' . $build->getId() . ' to queue.'); $buildService->addBuildToQueue($build); } }
/** * Pulls all pending builds from the database and runs them. */ protected function execute(InputInterface $input, OutputInterface $output) { $parser = new Parser(); $yaml = file_get_contents(APPLICATION_PATH . 'PHPCI/config.yml'); $this->settings = $parser->parse($yaml); $token = $this->settings['phpci']['github']['token']; if (!$token) { $this->logger->error(Lang::get('no_token')); return; } $buildStore = Factory::getStore('Build'); $this->logger->addInfo(Lang::get('finding_projects')); $projectStore = Factory::getStore('Project'); $result = $projectStore->getWhere(); $this->logger->addInfo(Lang::get('found_n_projects', count($result['items']))); foreach ($result['items'] as $project) { $http = new HttpClient('https://api.github.com'); $commits = $http->get('/repos/' . $project->getReference() . '/commits', array('access_token' => $token)); $last_commit = $commits['body'][0]['sha']; $last_committer = $commits['body'][0]['commit']['committer']['email']; $message = $commits['body'][0]['commit']['message']; $this->logger->info(Lang::get('last_commit_is', $project->getTitle(), $last_commit)); if ($project->getLastCommit() != $last_commit && $last_commit != "") { $this->logger->info(Lang::get('adding_new_build')); $build = new Build(); $build->setProjectId($project->getId()); $build->setCommitId($last_commit); $build->setStatus(Build::STATUS_NEW); $build->setBranch($project->getBranch()); $build->setCreated(new \DateTime()); $build->setCommitMessage($message); if (!empty($last_committer)) { $build->setCommitterEmail($last_committer); } $buildStore->save($build); $project->setLastCommit($last_commit); $projectStore->save($project); } } $this->logger->addInfo(Lang::get('finished_processing_builds')); }
/** * Creates an admin user in the existing PHPCI database */ protected function execute(InputInterface $input, OutputInterface $output) { $userStore = Factory::getStore('User'); $userService = new UserService($userStore); require PHPCI_DIR . 'bootstrap.php'; // Try to create a user account: $adminEmail = $this->ask('Admin email address: ', true, FILTER_VALIDATE_EMAIL); if (empty($adminEmail)) { return; } $adminPass = $this->ask('Admin password: '******'Admin name: '); try { $userService->createUser($adminName, $adminEmail, $adminPass, 1); print 'User account created!' . PHP_EOL; } catch (\Exception $ex) { print 'There was a problem creating your account. :(' . PHP_EOL; print $ex->getMessage(); print PHP_EOL; } }
/** * Creates an admin user in the existing PHPCI database */ protected function execute(InputInterface $input, OutputInterface $output) { $userStore = Factory::getStore('User'); $userService = new UserService($userStore); require PHPCI_DIR . 'bootstrap.php'; // Try to create a user account: $adminEmail = $this->ask(Lang::get('enter_email'), true, FILTER_VALIDATE_EMAIL); if (empty($adminEmail)) { return; } $adminPass = $this->ask(Lang::get('enter_pass')); $adminName = $this->ask(Lang::get('enter_name')); try { $userService->createUser($adminName, $adminEmail, $adminPass, 1); print Lang::get('user_created') . PHP_EOL; } catch (\Exception $ex) { print Lang::get('failed_to_create') . PHP_EOL; print $ex->getMessage(); print PHP_EOL; } }
/** * Pulls all pending builds from the database and runs them. */ protected function execute(InputInterface $input, OutputInterface $output) { $parser = new Parser(); $yaml = file_get_contents(APPLICATION_PATH . 'PHPCI/config.yml'); $this->settings = $parser->parse($yaml); $token = $this->settings['phpci']['github']['token']; if (!$token) { $this->logger->error("No github token found"); exit; } $buildStore = Factory::getStore('Build'); $this->logger->addInfo("Finding projects to poll"); $projectStore = Factory::getStore('Project'); $result = $projectStore->getWhere(); $this->logger->addInfo(sprintf("Found %d projects", count($result['items']))); foreach ($result['items'] as $project) { $http = new HttpClient('https://api.github.com'); $commits = $http->get('/repos/' . $project->getReference() . '/commits', array('access_token' => $token)); $last_commit = $commits['body'][0]['sha']; $last_committer = $commits['body'][0]['commit']['committer']['email']; $this->logger->info("Last commit to github for " . $project->getTitle() . " is " . $last_commit); if ($project->getLastCommit() != $last_commit && $last_commit != "") { $this->logger->info("Last commit is different from database, adding new build for " . $project->getTitle()); $build = new Build(); $build->setProjectId($project->getId()); $build->setCommitId($last_commit); $build->setStatus(Build::STATUS_NEW); $build->setBranch($project->getBranch()); $build->setCreated(new \DateTime()); if (!empty($last_committer)) { $build->setCommitterEmail($last_committer); } $buildStore->save($build); $project->setLastCommit($last_commit); $projectStore->save($project); } } $this->logger->addInfo("Finished processing builds"); }
/** * Pulls all pending builds from the database and runs them. */ protected function execute(InputInterface $input, OutputInterface $output) { $this->output = $output; // For verbose mode we want to output all informational and above // messages to the symphony output interface. if ($input->hasOption('verbose')) { $this->logger->pushHandler(new OutputLogHandler($this->output, Logger::INFO)); } $this->logger->pushProcessor(new LoggedBuildContextTidier()); $this->logger->addInfo("Finding builds to process"); $store = Factory::getStore('Build'); $result = $store->getByStatus(0, $this->maxBuilds); $this->logger->addInfo(sprintf("Found %d builds", count($result['items']))); $builds = 0; foreach ($result['items'] as $build) { $builds++; $build = BuildFactory::getBuild($build); try { // Logging relevant to this build should be stored // against the build itself. $buildDbLog = new BuildDBLogHandler($build, Logger::INFO); $this->logger->pushHandler($buildDbLog); $builder = new Builder($build, $this->logger); $builder->execute(); // After execution we no longer want to record the information // back to this specific build so the handler should be removed. $this->logger->popHandler($buildDbLog); } catch (\Exception $ex) { $build->setStatus(Build::STATUS_FAILED); $build->setLog($build->getLog() . PHP_EOL . PHP_EOL . $ex->getMessage()); $store->save($build); } } $this->logger->addInfo("Finished processing builds"); return $builds; }
public function init() { $request =& $this->request; $route = '/:controller/:action'; $opts = array('controller' => 'Home', 'action' => 'index'); // Inlined as a closure to fix "using $this when not in object context" on 5.3 $validateSession = function () { if (!empty($_SESSION['user_id'])) { $user = b8\Store\Factory::getStore('User')->getByPrimaryKey($_SESSION['user_id']); if ($user) { $_SESSION['user'] = $user; return true; } unset($_SESSION['user_id']); } return false; }; // Handler for the route we're about to register, checks for a valid session where necessary: $routeHandler = function (&$route, Response &$response) use(&$request, $validateSession) { $skipValidation = in_array($route['controller'], array('session', 'webhook', 'build-status')); if (!$skipValidation && !$validateSession()) { if ($request->isAjax()) { $response->setResponseCode(401); $response->setContent(''); } else { $_SESSION['login_redirect'] = substr($request->getPath(), 1); $response = new RedirectResponse($response); $response->setHeader('Location', PHPCI_URL . 'session/login'); } return false; } return true; }; $this->router->clearRoutes(); $this->router->register($route, $opts, $routeHandler); }
public function init() { $this->response->disableLayout(); $this->userStore = b8\Store\Factory::getStore('User'); }
/** * Get BuildMeta models by ProjectId for this Project. * * @uses \PHPCI\Store\BuildMetaStore::getByProjectId() * @uses \PHPCI\Model\BuildMeta * @return \PHPCI\Model\BuildMeta[] */ public function getProjectBuildMetas() { return Factory::getStore('BuildMeta', 'PHPCI')->getByProjectId($this->getId()); }
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(Lang::get('marked_as_failed', $build->getId())); $build->setStatus(Build::STATUS_FAILED); $build->setFinished(new \DateTime()); $store->save($build); $this->removeBuildDirectory($build); continue; } $rtn[$build->getProjectId()] = true; } return $rtn; }
/** * @param OutputInterface $output * @param DialogHelper $dialog */ protected function createAdminUser(OutputInterface $output, DialogHelper $dialog) { // Try to create a user account: $adminEmail = $dialog->askAndValidate($output, 'Your email address: ', function ($answer) { if (!filter_var($answer, FILTER_VALIDATE_EMAIL)) { throw new Exception('Must be a valid email address.'); } return $answer; }, false); $adminPass = $dialog->askHiddenResponse($output, 'Enter your desired admin password: '******'Enter your name: '); try { $user = new User(); $user->setEmail($adminEmail); $user->setName($adminName); $user->setIsAdmin(1); $user->setHash(password_hash($adminPass, PASSWORD_DEFAULT)); $this->reloadConfig(); $store = Factory::getStore('User'); $store->save($user); $output->writeln('<info>User account created!</info>'); } catch (\Exception $ex) { $output->writeln('<error>PHPCI failed to create your admin account.</error>'); $output->writeln('<error>' . $ex->getMessage() . '</error>'); die; } }
/** * Create add / edit project form. */ protected function projectForm($values, $type = 'add') { $form = new Form(); $form->setMethod('POST'); $form->setAction(PHPCI_URL . 'project/' . $type); $form->addField(new Form\Element\Csrf('csrf')); $form->addField(new Form\Element\Hidden('pubkey')); $options = array('choose' => Lang::get('select_repository_type'), 'github' => Lang::get('github'), 'bitbucket' => Lang::get('bitbucket'), 'gitlab' => Lang::get('gitlab'), 'remote' => Lang::get('remote'), 'local' => Lang::get('local'), 'hg' => Lang::get('hg'), 'svn' => Lang::get('svn')); $field = Form\Element\Select::create('type', Lang::get('where_hosted'), true); $field->setPattern('^(github|bitbucket|gitlab|remote|local|hg|svn)'); $field->setOptions($options); $field->setClass('form-control')->setContainerClass('form-group'); $form->addField($field); $container = new Form\ControlGroup('github-container'); $container->setClass('github-container'); $field = Form\Element\Select::create('github', Lang::get('choose_github'), false); $field->setClass('form-control')->setContainerClass('form-group'); $container->addField($field); $form->addField($container); $field = Form\Element\Text::create('reference', Lang::get('repo_name'), true); $field->setValidator($this->getReferenceValidator($values)); $field->setClass('form-control')->setContainerClass('form-group'); $form->addField($field); $field = Form\Element\Text::create('title', Lang::get('project_title'), true); $field->setClass('form-control')->setContainerClass('form-group'); $form->addField($field); $field = Form\Element\TextArea::create('key', Lang::get('project_private_key'), false); $field->setClass('form-control')->setContainerClass('form-group'); $field->setRows(6); $form->addField($field); $field = Form\Element\TextArea::create('build_config', Lang::get('build_config'), false); $field->setClass('form-control')->setContainerClass('form-group'); $field->setRows(6); $form->addField($field); $field = Form\Element\Text::create('branch', Lang::get('default_branch'), true); $field->setClass('form-control')->setContainerClass('form-group')->setValue('master'); $form->addField($field); $field = Form\Element\Select::create('group_id', 'Project Group', true); $field->setClass('form-control')->setContainerClass('form-group')->setValue(1); $groups = array(); $groupStore = b8\Store\Factory::getStore('ProjectGroup'); $groupList = $groupStore->getWhere(array(), 100, 0, array(), array('title' => 'ASC')); foreach ($groupList['items'] as $group) { $groups[$group->getId()] = $group->getTitle(); } $field->setOptions($groups); $form->addField($field); $field = Form\Element\Checkbox::create('allow_public_status', Lang::get('allow_public_status'), false); $field->setContainerClass('form-group'); $field->setCheckedValue(1); $field->setValue(0); $form->addField($field); $field = Form\Element\Checkbox::create('archived', Lang::get('archived'), false); $field->setContainerClass('form-group'); $field->setCheckedValue(1); $field->setValue(0); $form->addField($field); $field = new Form\Element\Submit(); $field->setValue(Lang::get('save_project')); $field->setContainerClass('form-group'); $field->setClass('btn-success'); $form->addField($field); $form->setValues($values); return $form; }
/** * Store build metadata */ public function storeMeta($key, $value) { $value = json_encode($value); Factory::getStore('Build')->setMeta($this->getProjectId(), $this->getId(), $key, $value); }
/** * Set up the builder. * @param \PHPCI\Model\Build $build * @param LoggerInterface $logger */ public function __construct(Build $build, LoggerInterface $logger = null) { $this->build = $build; $this->store = Factory::getStore('Build'); $this->buildLogger = new BuildLogger($logger, $build); $pluginFactory = $this->buildPluginFactory($build); $pluginFactory->addConfigFromFile(PHPCI_DIR . "/pluginconfig.php"); $this->pluginExecutor = new Plugin\Util\Executor($pluginFactory, $this->buildLogger); $executorClass = 'PHPCI\\Helper\\UnixCommandExecutor'; if (IS_WIN) { $executorClass = 'PHPCI\\Helper\\WindowsCommandExecutor'; } $this->commandExecutor = new $executorClass($this->buildLogger, PHPCI_DIR, $this->quiet, $this->verbose); $this->interpolator = new BuildInterpolator(); }
/** * Initialise the controller, set up stores and services. */ public function init() { $this->response->disableLayout(); $this->buildStore = Store\Factory::getStore('Build'); $this->projectStore = Store\Factory::getStore('Project'); }
/** * Initialise the controller, set up stores and services. */ public function init() { $this->buildStore = b8\Store\Factory::getStore('Build'); $this->projectStore = b8\Store\Factory::getStore('Project'); }
/** * @param Factory $pluginFactory * @param BuildLogger $logger */ public function __construct(Factory $pluginFactory, BuildLogger $logger, BuildStore $store = null) { $this->pluginFactory = $pluginFactory; $this->logger = $logger; $this->store = $store ?: StoreFactory::getStore('Build'); }
/** * Check whether we should skip auth (because it is disabled) * @return bool */ protected function shouldSkipAuth() { $config = b8\Config::getInstance(); $state = (bool) $config->get('phpci.authentication_settings.state', false); $userId = $config->get('phpci.authentication_settings.user_id', 0); if (false !== $state && 0 != (int) $userId) { $user = b8\Store\Factory::getStore('User')->getByPrimaryKey($userId); if ($user) { $_SESSION['phpci_user'] = $user; return true; } } return false; }