/** * 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; }
/** * 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; }
/** * Runs PHP Mess Detector in a specified directory. */ public function execute() { $jshintBinaryPath = $this->phpci->findBinary('jshint'); $this->executeJsHint($jshintBinaryPath); list($errorCount, $data) = $this->processReport(trim($this->phpci->getLastOutput())); $this->build->storeMeta('jshint-warnings', $errorCount); $this->build->storeMeta('jshint-data', $data); return $this->wasLastExecSuccessful($errorCount); }
/** * Executes parallel lint */ public function execute() { list($ignore) = $this->getFlags(); $phplint = $this->phpci->findBinary('parallel-lint'); $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; }
/** * Runs PHP Code Sniffer in a specified directory, to a specified standard. */ public function execute() { list($ignore, $standard, $suffixes) = $this->getFlags(); $phpcs = $this->phpci->findBinary('phpcs'); if (!$phpcs) { $this->phpci->logFailure('Could not find phpcs.'); return false; } $this->phpci->logExecOutput(false); $cmd = $phpcs . ' --report=json %s %s %s %s %s "%s"'; $this->phpci->executeCommand($cmd, $standard, $suffixes, $ignore, $this->tab_width, $this->encoding, $this->phpci->buildPath . $this->path); $output = $this->phpci->getLastOutput(); list($errors, $warnings, $data) = $this->processReport($output); $this->phpci->logExecOutput(true); $success = true; $this->build->storeMeta('phpcs-warnings', $warnings); $this->build->storeMeta('phpcs-errors', $errors); $this->build->storeMeta('phpcs-data', $data); if ($this->allowed_warnings != -1 && $warnings > $this->allowed_warnings) { $success = false; } if ($this->allowed_errors != -1 && $errors > $this->allowed_errors) { $success = false; } return $success; }
/** * Run phptal lint against a specific file. * @param $path * @return bool */ protected function lintFile($path) { $success = true; list($suffixes, $tales) = $this->getFlags(); $lint = dirname(__FILE__) . '/../../vendor/phptal/phptal/tools/phptal_lint.php'; $cmd = '/usr/bin/env php ' . $lint . ' %s %s "%s"'; $this->phpci->executeCommand($cmd, $suffixes, $tales, $this->phpci->buildPath . $path); $output = $this->phpci->getLastOutput(); if (preg_match('/Found (.+?) (error|warning)/i', $output, $matches)) { $rows = explode(PHP_EOL, $output); unset($rows[0]); unset($rows[1]); unset($rows[2]); unset($rows[3]); foreach ($rows as $row) { $name = basename($path); $row = str_replace('(use -i to include your custom modifier functions)', '', $row); $message = str_replace($name . ': ', '', $row); $parts = explode(' (line ', $message); $message = trim($parts[0]); $line = str_replace(')', '', $parts[1]); $this->failedPaths[] = array('file' => $path, 'line' => $line, 'type' => $matches[2], 'message' => $message); } $success = false; } return $success; }
/** * Runs PHP Mess Detector in a specified directory. */ public function execute() { if (!$this->tryAndProcessRules()) { return false; } $phpmdBinaryPath = $this->phpci->findBinary('phpmd'); $this->executePhpMd($phpmdBinaryPath); $errorCount = $this->processReport(trim($this->phpci->getLastOutput())); $this->build->storeMeta('phpmd-warnings', $errorCount); return $this->wasLastExecSuccessful($errorCount); }
/** * Runs PHP Copy/Paste Detector in a specified directory. */ public function execute() { $ignore = ''; if (count($this->phpci->ignore)) { $map = function ($item) { return ' --exclude ' . rtrim($item, DIRECTORY_SEPARATOR); }; $ignore = array_map($map, $this->phpci->ignore); $ignore = implode('', $ignore); } $phploc = $this->phpci->findBinary('phploc'); $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; }
/** * {@inheritdoc} */ public function execute() { $curdir = getcwd(); chdir($this->phpci->buildPath); if (!is_file($this->configFile)) { $this->phpci->logFailure(sprintf('The Atoum config file "%s" is missing.', $this->configFile)); chdir($curdir); return false; } $this->phpci->logExecOutput(false); $status = $this->phpci->executeCommand('php %s -c %s -ft -utr', $this->executable, $this->configFile); $this->phpci->logExecOutput(true); try { $parser = new TapParser(mb_convert_encoding('TAP version 13' . PHP_EOL . $this->phpci->getLastOutput(), 'UTF-8', 'ISO-8859-1')); $data = $parser->parse(); $this->reportErrors($data); } catch (\Exception $exception) { $status = false; $this->phpci->logFailure('Impossible to parse the Atoum output.', $exception); } chdir($curdir); return $status; }
/** * Runs PHP Mess Detector in a specified directory. */ public function execute() { if (!$this->tryAndProcessRules()) { return false; } $phpmdBinaryPath = $this->phpci->findBinary('phpmd'); if (!$phpmdBinaryPath) { $this->phpci->logFailure(PHPCI\Helper\Lang::get('could_not_find', 'phpmd')); return false; } $this->executePhpMd($phpmdBinaryPath); list($errorCount, $data) = $this->processReport(trim($this->phpci->getLastOutput())); $this->build->storeMeta('phpmd-warnings', $errorCount); $this->build->storeMeta('phpmd-data', $data); return $this->wasLastExecSuccessful($errorCount); }
/** * Runs PHP Mess Detector in a specified directory. */ public function execute() { // Check that the binary exists: $checker = $this->phpci->findBinary('phpdoccheck'); if (!$checker) { $this->phpci->logFailure(PHPCI\Helper\Lang::get('could_not_find', 'phpdoccheck')); return false; } // Build ignore string: $ignore = ''; if (count($this->ignore)) { $ignore = ' --exclude="' . implode(',', $this->ignore) . '"'; } // Are we skipping any checks? $add = ''; if ($this->skipClasses) { $add .= ' --skip-classes'; } if ($this->skipMethods) { $add .= ' --skip-methods'; } // Build command string: $path = $this->phpci->buildPath . $this->path; $cmd = $checker . ' --json --directory="%s"%s%s'; // Disable exec output logging, as we don't want the XML report in the log: $this->phpci->logExecOutput(false); // Run checker: $this->phpci->executeCommand($cmd, $path, $ignore, $add); // Re-enable exec output logging: $this->phpci->logExecOutput(true); $output = json_decode($this->phpci->getLastOutput(), true); $errors = count($output); $success = true; $this->build->storeMeta('phpdoccheck-warnings', $errors); $this->build->storeMeta('phpdoccheck-data', $output); $this->reportErrors($output); if ($this->allowed_warnings != -1 && $errors > $this->allowed_warnings) { $success = false; } return $success; }
/** * Uses git diff to figure out what the diff line position is, based on the error line number. * @param Builder $builder * @param $file * @param $line * @return int|null */ protected function getDiffLineNumber(Builder $builder, $file, $line) { $builder->logExecOutput(false); $prNumber = $this->getExtra('pull_request_number'); $path = $builder->buildPath; if (!empty($prNumber)) { $builder->executeCommand('cd %s && git diff origin/%s "%s"', $path, $this->getBranch(), $file); } else { $builder->executeCommand('cd %s && git diff %s^! "%s"', $path, $this->getCommitId(), $file); } $builder->logExecOutput(true); $diff = $builder->getLastOutput(); $helper = new Diff(); $lines = $helper->getLinePositions($diff); return $lines[$line]; }
/** * Uses git diff to figure out what the diff line position is, based on the error line number. * @param Builder $builder * @param $file * @param $line * @return int|null */ protected function getDiffLineNumber(Builder $builder, $file, $line) { $line = (int) $line; $builder->logExecOutput(false); $prNumber = $this->getExtra('pull_request_number'); $path = $builder->buildPath; if (!empty($prNumber)) { $builder->executeCommand('cd %s && git diff origin/%s "%s"', $path, $this->getBranch(), $file); } else { $commitId = $this->getCommitId(); $compare = $commitId == 'Manual' ? 'HEAD' : $commitId; $builder->executeCommand('cd %s && git diff %s^^ "%s"', $path, $compare, $file); } $builder->logExecOutput(true); $diff = $builder->getLastOutput(); $helper = new Diff(); $lines = $helper->getLinePositions($diff); return isset($lines[$line]) ? $lines[$line] : null; }
/** * Handle any post-clone tasks, like switching branches. * @param Builder $builder * @param $cloneTo * @return bool */ protected function postCloneSetup(Builder $builder, $cloneTo) { $success = true; $commit = $this->getCommitId(); $chdir = IS_WIN ? 'cd /d "%s"' : 'cd "%s"'; if (!empty($commit) && $commit != 'Manual') { $cmd = $chdir . ' && git checkout %s --quiet'; $success = $builder->executeCommand($cmd, $cloneTo, $commit); } // Always update the commit hash with the actual HEAD hash if ($builder->executeCommand($chdir . ' && git rev-parse HEAD', $cloneTo)) { $this->setCommitId(trim($builder->getLastOutput())); } return $success; }