/** * Runs Pdepend with the given criteria as arguments */ public function execute() { if (!is_writable($this->location)) { throw new \Exception(sprintf('The location %s is not writable.', $this->location)); } $pdepend = $this->phpci->findBinary('pdepend'); if (!$pdepend) { $this->phpci->logFailure(Lang::get('could_not_find', 'pdepend')); return false; } $cmd = $pdepend . ' --summary-xml="%s" --jdepend-chart="%s" --overview-pyramid="%s" %s "%s"'; $this->removeBuildArtifacts(); // If we need to ignore directories if (count($this->phpci->ignore)) { $ignore = ' --ignore=' . implode(',', $this->phpci->ignore); } else { $ignore = ''; } $success = $this->phpci->executeCommand($cmd, $this->location . DIRECTORY_SEPARATOR . $this->summary, $this->location . DIRECTORY_SEPARATOR . $this->chart, $this->location . DIRECTORY_SEPARATOR . $this->pyramid, $ignore, $this->directory); $config = $this->phpci->getSystemConfig('phpci'); if ($success) { $this->phpci->logSuccess(sprintf("Pdepend successful. You can use %s\n, ![Chart](%s \"Pdepend Chart\")\n\n and ![Pyramid](%s \"Pdepend Pyramid\")\n\n for inclusion in the readme.md file", $config['url'] . '/build/pdepend/' . $this->summary, $config['url'] . '/build/pdepend/' . $this->chart, $config['url'] . '/build/pdepend/' . $this->pyramid)); } return $success; }
/** * * Moves the static analysis log files into doc root before the build is destroyed * * @return bool * @throws \Exception */ public function execute() { $srcDir = $this->build->getBuildPath() . '/build/logs/report'; $destDir = APPLICATION_PATH . 'public/reports'; $result = exec(sprintf(IS_WIN ? 'rmdir /S /Q "%s"' : 'rm -Rf "%s"', $destDir), $output, $exitStatus); // Non-zero status is an error scenario if ($exitStatus !== 0) { // Wipe failed - exception here throw new \Exception(Lang::get('failed_to_wipe', $destDir)); } $moveResult = false; if (!is_dir($destDir)) { $moveResult = rename($srcDir, $destDir); } switch ($moveResult) { case true: $logMessage = "Coverage reports deployed at "; $logMessage .= "{$this->reportUrl}"; $this->phpci->logSuccess($logMessage); break; default: $logMessage = "Oopsies"; $this->phpci->logFailure($logMessage); break; } return true; }
/** * Runs PHP Copy/Paste Detector in a specified directory. */ public function execute() { $ignore = ''; if (count($this->phpci->ignore)) { $map = function ($item) { return ' --exclude ' . (substr($item, -1) == '/' ? substr($item, 0, -1) : $item); }; $ignore = array_map($map, $this->phpci->ignore); $ignore = implode('', $ignore); } $phploc = $this->phpci->findBinary('phploc'); if (!$phploc) { $this->phpci->logFailure(PHPCI\Helper\Lang::get('could_not_find', 'phploc')); return false; } $success = $this->phpci->executeCommand($phploc . ' %s "%s"', $ignore, $this->directory); $output = $this->phpci->getLastOutput(); if (preg_match_all('/\\((LOC|CLOC|NCLOC|LLOC)\\)\\s+([0-9]+)/', $output, $matches)) { $data = array(); foreach ($matches[1] as $k => $v) { $data[$v] = (int) $matches[2][$k]; } $this->build->storeMeta('phploc', $data); } return $success; }
/** * @param Project $project * @param string|null $commitId * @param string|null $branch * @param string|null $committerEmail * @param string|null $commitMessage * @param string|null $extra * @return \PHPCI\Model\Build */ public function createBuild(Project $project, $commitId = null, $branch = null, $committerEmail = null, $commitMessage = null, $extra = null) { $build = new Build(); $build->setCreated(new \DateTime()); $build->setProject($project); $build->setStatus(0); if (!is_null($commitId)) { $build->setCommitId($commitId); } else { $build->setCommitId('Manual'); $build->setCommitMessage(Lang::get('manual_build')); } if (!is_null($branch)) { $build->setBranch($branch); } else { $build->setBranch($project->getBranch()); } if (!is_null($committerEmail)) { $build->setCommitterEmail($committerEmail); } if (!is_null($commitMessage)) { $build->setCommitMessage($commitMessage); } if (!is_null($extra)) { $build->setExtra(json_encode($extra)); } return $this->buildStore->save($build); }
/** * Set up the plugin, configure options, etc. * @param Builder $phpci * @param Build $build * @param array $options * @throws \Exception */ public function __construct(Builder $phpci, Build $build, array $options = array()) { $this->phpci = $phpci; $this->build = $build; $this->userAgent = "PHPCI/1.0 (+http://www.phptesting.org/)"; $this->cookie = "phpcicookie"; if (is_array($options) && isset($options['authToken']) && isset($options['room'])) { $this->authToken = $options['authToken']; $this->room = $options['room']; if (isset($options['message'])) { $this->message = $options['message']; } else { $this->message = Lang::get('x_built_at_x'); } if (isset($options['color'])) { $this->color = $options['color']; } else { $this->color = 'yellow'; } if (isset($options['notify'])) { $this->notify = $options['notify']; } else { $this->notify = false; } } else { throw new \Exception(Lang::get('hipchat_settings')); } }
/** * Connects to MySQL and runs a specified set of queries. */ public function execute() { $addresses = $this->getEmailAddresses(); // Without some email addresses in the yml file then we // can't do anything. if (count($addresses) == 0) { return false; } $subjectTemplate = "PHPCI - %s - %s"; $projectName = $this->phpci->getBuildProjectTitle(); $logText = $this->build->getLog(); if ($this->build->isSuccessful()) { $sendFailures = $this->sendSeparateEmails($addresses, sprintf($subjectTemplate, $projectName, Lang::get('passing_build')), sprintf(Lang::get('log_output') . "<br><pre>%s</pre>", $logText)); } else { $view = new View('Email/failed'); $view->build = $this->build; $view->project = $this->build->getProject(); $emailHtml = $view->render(); $sendFailures = $this->sendSeparateEmails($addresses, sprintf($subjectTemplate, $projectName, Lang::get('failing_build')), $emailHtml); } // This is a success if we've not failed to send anything. $this->phpci->log(Lang::get('n_emails_sent', count($addresses) - count($sendFailures))); $this->phpci->log(Lang::get('n_emails_failed', count($sendFailures))); return count($sendFailures) == 0; }
/** * Runs PHP Spec tests. */ public function execute() { $curdir = getcwd(); chdir($this->phpci->buildPath); $phpspec = $this->phpci->findBinary(array('phpspec', 'phpspec.php')); if (!$phpspec) { $this->phpci->logFailure(PHPCI\Helper\Lang::get('could_not_find', 'phpspec')); return false; } $success = $this->phpci->executeCommand($phpspec . ' --format=junit --no-code-generation run'); $output = $this->phpci->getLastOutput(); chdir($curdir); /* * process xml output * * <testsuites time=FLOAT tests=INT failures=INT errors=INT> * <testsuite name=STRING time=FLOAT tests=INT failures=INT errors=INT skipped=INT> * <testcase name=STRING time=FLOAT classname=STRING status=STRING/> * </testsuite> * </testsuites */ $xml = new \SimpleXMLElement($output); $attr = $xml->attributes(); $data = array('time' => (double) $attr['time'], 'tests' => (int) $attr['tests'], 'failures' => (int) $attr['failures'], 'errors' => (int) $attr['errors'], 'suites' => array()); /** * @var \SimpleXMLElement $group */ foreach ($xml->xpath('testsuite') as $group) { $attr = $group->attributes(); $suite = array('name' => (string) $attr['name'], 'time' => (double) $attr['time'], 'tests' => (int) $attr['tests'], 'failures' => (int) $attr['failures'], 'errors' => (int) $attr['errors'], 'skipped' => (int) $attr['skipped'], 'cases' => array()); /** * @var \SimpleXMLElement $child */ foreach ($group->xpath('testcase') as $child) { $attr = $child->attributes(); $case = array('name' => (string) $attr['name'], 'classname' => (string) $attr['classname'], 'time' => (double) $attr['time'], 'status' => (string) $attr['status']); if ($case['status'] == 'failed') { $error = array(); /* * ok, sad, we had an error * * there should be one - foreach makes this easier */ foreach ($child->xpath('failure') as $failure) { $attr = $failure->attributes(); $error['type'] = (string) $attr['type']; $error['message'] = (string) $attr['message']; } foreach ($child->xpath('system-err') as $system_err) { $error['raw'] = (string) $system_err; } $case['error'] = $error; } $suite['cases'][] = $case; } $data['suites'][] = $suite; } $this->build->storeMeta('phpspec', $data); return $success; }
/** * 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(Lang::get('tap_version')); } if (isset($lines[count($lines) - 1]) && preg_match(self::TEST_COVERAGE_PATTERN, $lines[count($lines) - 1])) { array_pop($lines); if ($lines[count($lines) - 1] == "") { array_pop($lines); } } $matches = array(); $totalTests = 0; if (preg_match(self::TEST_COUNTS_PATTERN, $lines[0], $matches)) { array_shift($lines); $totalTests = (int) $matches[2]; } if (isset($lines[count($lines) - 1]) && 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(Lang::get('tap_error')); } return $rtn; }
/** * Run the Atoum plugin. * @return bool */ public function execute() { $cmd = $this->executable; if ($this->args !== null) { $cmd .= " {$this->args}"; } if ($this->config !== null) { $cmd .= " -c '{$this->config}'"; } if ($this->directory !== null) { $dirPath = $this->phpci->buildPath . DIRECTORY_SEPARATOR . $this->directory; $cmd .= " -d '{$dirPath}'"; } chdir($this->phpci->buildPath); $output = ''; $status = true; exec($cmd, $output); if (count(preg_grep("/Success \\(/", $output)) == 0) { $status = false; $this->phpci->log($output); } if (count($output) == 0) { $status = false; $this->phpci->log(Lang::get('no_tests_performed')); } return $status; }
/** * Generates Model and Store classes by reading database meta data. */ protected function execute(InputInterface $input, OutputInterface $output) { if (!$this->verifyInstalled($output)) { return; } $output->write(Lang::get('updating_phpci')); shell_exec(PHPCI_DIR . 'vendor/bin/phinx migrate -c "' . PHPCI_DIR . 'phinx.php"'); $output->writeln('<info>' . Lang::get('ok') . '</info>'); }
/** * Wipe the destination directory if it already exists. * @throws \Exception */ protected function wipeExistingDirectory() { if ($this->wipe === true && $this->directory != '/' && is_dir($this->directory)) { $cmd = 'rm -Rf "%s*"'; $success = $this->phpci->executeCommand($cmd, $this->directory); if (!$success) { throw new \Exception(Lang::get('failed_to_wipe', $this->directory)); } } }
/** * Display PHPCI dashboard: */ public function index() { $this->layout->title = Lang::get('dashboard'); $builds = $this->buildStore->getLatestBuilds(null, 10); foreach ($builds as &$build) { $build = BuildFactory::getBuild($build); } $this->view->builds = $builds; $this->view->groups = $this->getGroupInfo(); return $this->view->render(); }
/** * List all enabled plugins, installed and recommend packages. * @return string */ public function index() { $this->requireAdmin(); $json = $this->getComposerJson(); $this->view->installedPackages = $json['require']; $pluginInfo = new PluginInformationCollection(); $pluginInfo->add(FilesPluginInformation::newFromDir(PHPCI_DIR . "PHPCI/Plugin/")); $pluginInfo->add(ComposerPluginInformation::buildFromYaml(PHPCI_DIR . "vendor/composer/installed.json")); $this->view->plugins = $pluginInfo->getInstalledPlugins(); $this->layout->title = Lang::get('plugins'); return $this->view->render(); }
/** * Display PHPCI dashboard: */ public function index() { $this->layout->title = Lang::get('dashboard'); $projects = $this->projectStore->getWhere(array('archived' => (int) isset($_GET['archived'])), 50, 0, array(), array('title' => 'ASC')); $builds = $this->buildStore->getLatestBuilds(null, 10); foreach ($builds as &$build) { $build = BuildFactory::getBuild($build); } $this->view->builds = $builds; $this->view->projects = $projects['items']; $this->view->summary = $this->getSummaryHtml($projects); return $this->view->render(); }
/** * Runs Behat tests. */ public function execute() { $curdir = getcwd(); chdir($this->phpci->buildPath); $behat = $this->executable; if (!$behat) { $this->phpci->logFailure(Lang::get('could_not_find', 'behat')); return false; } $success = $this->phpci->executeCommand($behat . ' %s', $this->features); chdir($curdir); return $success; }
protected function verifyInstalled(OutputInterface $output) { if (!file_exists(PHPCI_DIR . 'PHPCI/config.yml')) { $output->writeln('<error>' . Lang::get('not_installed') . '</error>'); $output->writeln('<error>' . Lang::get('install_instead') . '</error>'); die; } $content = file_get_contents(PHPCI_DIR . 'PHPCI/config.yml'); if (empty($content)) { $output->writeln('<error>' . Lang::get('not_installed') . '</error>'); $output->writeln('<error>' . Lang::get('install_instead') . '</error>'); die; } }
/** * Runs the shell command. */ public function execute() { if (!defined('ENABLE_SHELL_PLUGIN') || !ENABLE_SHELL_PLUGIN) { throw new \Exception(Lang::get('shell_not_enabled')); } $success = true; foreach ($this->commands as $command) { $command = $this->phpci->interpolate($command); if (!$this->phpci->executeCommand($command)) { $success = false; } } return $success; }
/** * Run PHP CS Fixer. * @return bool */ public function execute() { $curdir = getcwd(); chdir($this->workingdir); $phpcsfixer = $this->phpci->findBinary('php-cs-fixer'); if (!$phpcsfixer) { $this->phpci->logFailure(Lang::get('could_not_find', 'php-cs-fixer')); return false; } $cmd = $phpcsfixer . ' fix . %s %s %s'; $success = $this->phpci->executeCommand($cmd, $this->verbose, $this->diff, $this->level); chdir($curdir); return $success; }
/** * Runs Behat tests. */ public function execute() { $curdir = getcwd(); chdir($this->phpci->buildPath); $behat = $this->executable; if (!$behat) { $this->phpci->logFailure(Lang::get('could_not_find', 'behat')); return false; } $success = $this->phpci->executeCommand($behat . ' %s', $this->features); chdir($curdir); list($errorCount, $data) = $this->parseBehatOutput(); $this->build->storeMeta('behat-warnings', $errorCount); $this->build->storeMeta('behat-data', $data); return $success; }
/** * {@inheritDoc} */ public function execute(InputInterface $input, OutputInterface $output) { $projectId = $input->getArgument('projectId'); $commitId = $input->getOption('commit'); $branch = $input->getOption('branch'); $project = $this->projectStore->getById($projectId); if (empty($project)) { throw new \InvalidArgumentException('Project does not exist: ' . $projectId); } try { $this->buildService->createBuild($project, $commitId, $branch); $output->writeln(Lang::get('build_created')); } catch (\Exception $e) { $output->writeln(sprintf('<error>%s</error>', Lang::get('failed'))); $output->writeln(sprintf('<error>%s</error>', $e->getMessage())); } }
/** * Set up the plugin, configure options, etc. * @param Builder $phpci * @param Build $build * @param array $options * @throws \Exception */ public function __construct(Builder $phpci, Build $build, array $options = array()) { $this->phpci = $phpci; $this->build = $build; $this->message = $options['message']; $this->userAgent = "PHPCI/1.0 (+http://www.phptesting.org/)"; $this->cookie = "phpcicookie"; $buildSettings = $phpci->getConfig('build_settings'); if (isset($buildSettings['campfire'])) { $campfire = $buildSettings['campfire']; $this->url = $campfire['url']; $this->authToken = $campfire['authToken']; $this->roomId = $campfire['roomId']; } else { throw new \Exception(Lang::get('no_campfire_settings')); } }
/** * Executes parallel lint */ public function execute() { list($ignore) = $this->getFlags(); $phplint = $this->phpci->findBinary('parallel-lint'); if (!$phplint) { $this->phpci->logFailure(Lang::get('could_not_find', 'parallel-lint')); return false; } $cmd = $phplint . ' %s "%s"'; $success = $this->phpci->executeCommand($cmd, $ignore, $this->directory); $output = $this->phpci->getLastOutput(); $matches = array(); if (preg_match_all('/Parse error\\:/', $output, $matches)) { $this->build->storeMeta('phplint-errors', count($matches[0])); } return $success; }
/** * @covers PHPUnit::execute */ public function testExecute_CreateBasicBuild() { $project = new Project(); $project->setType('github'); $project->setId(101); $returnValue = $this->testedService->createBuild($project); $this->assertEquals(101, $returnValue->getProjectId()); $this->assertEquals(Build::STATUS_NEW, $returnValue->getStatus()); $this->assertNull($returnValue->getStarted()); $this->assertNull($returnValue->getFinished()); $this->assertNull($returnValue->getLog()); $this->assertEquals(\PHPCI\Helper\Lang::get('manual_build'), $returnValue->getCommitMessage()); $this->assertNull($returnValue->getCommitterEmail()); $this->assertNull($returnValue->getExtra()); $this->assertEquals('master', $returnValue->getBranch()); $this->assertInstanceOf('DateTime', $returnValue->getCreated()); $this->assertEquals('Manual', $returnValue->getCommitId()); }
/** * Run IRC plugin. * @return bool */ public function execute() { $msg = $this->phpci->interpolate($this->message); if (empty($this->server) || empty($this->room) || empty($this->nick)) { $this->phpci->logFailure(Lang::get('irc_settings')); } if (empty($this->port)) { $this->port = 6667; } $sock = fsockopen($this->server, $this->port); stream_set_timeout($sock, 1); $connectCommands = array('USER ' . $this->nick . ' 0 * :' . $this->nick, 'NICK ' . $this->nick); $this->executeIrcCommands($sock, $connectCommands); $this->executeIrcCommand($sock, 'JOIN ' . $this->room); $this->executeIrcCommand($sock, 'PRIVMSG ' . $this->room . ' :' . $msg); fclose($sock); return true; }
/** * Adds the specified environment variables to the builder environment */ public function execute() { $success = true; foreach ($this->env_vars as $key => $value) { if (is_numeric($key)) { // This allows the developer to specify env vars like " - FOO=bar" or " - FOO: bar" $env_var = is_array($value) ? key($value) . '=' . current($value) : $value; } else { // This allows the standard syntax: "FOO: bar" $env_var = "{$key}={$value}"; } if (!putenv($this->phpci->interpolate($env_var))) { $success = false; $this->phpci->logFailure(Lang::get('unable_to_set_env')); } } return $success; }
protected function processReport($output) { $data = json_decode(trim($output)); if (!is_array($data)) { $this->phpci->log($output); throw new \Exception(Lang::get('could_not_process_report')); } $errors = 0; $warnings = 0; foreach ($data as $file) { $fileName = str_replace($this->phpci->buildPath, '', $file->filePath); $errors += $file->errorCount; $warnings = $file->warningCount; foreach ($file->messages as $message) { $this->build->reportError($this->phpci, 'phplint_errors', 'ESLINT: ' . $message->message . "\n" . $message->source, $message->severity == 2 ? BuildError::SEVERITY_HIGH : BuildError::SEVERITY_LOW, $fileName, $message->line); } } return array($errors, $warnings); }
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); } }
/** * Run tests from a Codeception config file. * @param $configPath * @return bool|mixed */ protected function runConfigFile($configPath) { if (is_array($configPath)) { return $this->recurseArg($configPath, array($this, "runConfigFile")); } else { $codecept = $this->phpci->findBinary('codecept'); if (!$codecept) { $this->phpci->logFailure(Lang::get('could_not_find', 'codecept')); return false; } $cmd = 'cd "%s" && ' . $codecept . ' run -c "%s" ' . $this->args; if (IS_WIN) { $cmd = 'cd /d "%s" && ' . $codecept . ' run -c "%s" ' . $this->args; } $configPath = $this->phpci->buildPath . $configPath; $success = $this->phpci->executeCommand($cmd, $this->phpci->buildPath, $configPath); return $success; } }
/** * 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')); }
/** * Executes Composer and runs a specified command (e.g. install / update) */ public function execute() { $composerLocation = $this->phpci->findBinary(array('composer', 'composer.phar')); if (!$composerLocation) { $this->phpci->logFailure(Lang::get('could_not_find', 'composer')); return false; } $cmd = ''; if (IS_WIN) { $cmd = 'php '; } $cmd .= $composerLocation . ' --no-ansi --no-interaction '; if ($this->preferDist) { $this->phpci->log('Using --prefer-dist flag'); $cmd .= '--prefer-dist'; } else { $this->phpci->log('Using --prefer-source flag'); $cmd .= '--prefer-source'; } $cmd .= ' --working-dir="%s" %s'; return $this->phpci->executeCommand($cmd, $this->directory, $this->action); }