/** * 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; }
/** * 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') && $input->getOption('verbose')) { $this->logger->pushHandler(new OutputLogHandler($this->output, Logger::INFO)); } $running = $this->validateRunningBuilds(); $this->logger->pushProcessor(new LoggedBuildContextTidier()); $this->logger->addInfo(Lang::get('finding_builds')); $store = Factory::getStore('Build'); $result = $store->getByStatus(0, $this->maxBuilds); $this->logger->addInfo(Lang::get('found_n_builds', count($result['items']))); $builds = 0; while (count($result['items'])) { $build = array_shift($result['items']); $build = BuildFactory::getBuild($build); // Skip build (for now) if there's already a build running in that project: if (!$this->isFromDaemon && in_array($build->getProjectId(), $running)) { $this->logger->addInfo(Lang::get('skipping_build', $build->getId())); $result['items'][] = $build; // Re-run build validator: $running = $this->validateRunningBuilds(); continue; } $builds++; 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->setFinished(new \DateTime()); $build->setLog($build->getLog() . PHP_EOL . PHP_EOL . $ex->getMessage()); $store->save($build); } } $this->logger->addInfo(Lang::get('finished_processing_builds')); return $builds; }
/** * 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); } }