diff --git a/.codeclimate.yml b/.codeclimate.yml new file mode 100644 index 0000000..a986135 --- /dev/null +++ b/.codeclimate.yml @@ -0,0 +1,27 @@ +--- +engines: + duplication: + enabled: true + config: + languages: + - php + phpcodesniffer: + enabled: true + phpmd: + enabled: true + checks: + CleanCode/ElseExpression: + enabled: false + Controversial/Superglobals: + enabled: false + exclude_fingerprints: + # High complexity in CiInfo#toArray() + - 8f1ff5077ea52a5fee818bde73a0dbb7 + - efc665f3aa41cbbd0bbd0ec9c945a453 +ratings: + paths: + - "**.inc" + - "**.module" + - "**.php" +exclude_paths: +- tests/ diff --git a/.gitignore b/.gitignore index b6ba778..2fe8804 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ +.idea/ +.vagrant/ +Vagrantfile build/ vendor/ -box.phar -codeclimate-test-reporter.phar composer.lock composer.phar diff --git a/.travis.yml b/.travis.yml index 8251f0d..f36196c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,10 +9,6 @@ cache: directories: - $HOME/.composer/cache -env: - global: - secure: Yc+Xohkr/iEUU7FCQuSLXAE9ywNW9g6CfrM1Ki0Hl+fS15F3AXT7dFY8EyCJ4dP1/oI0dBmwrGWrltXV0XWIjGV1Ms3tefCgQpBBAqwT+hImzVP3RbpZW8Iyo2d0VgiDemQF1LWYD/pKu6d8WljTnv5D77NIMdEJjQ0uzeTLWdw= - before_install: - composer self-update diff --git a/composer.json b/composer.json index 7192486..9d7381e 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,10 @@ { "name": "codeclimate/php-test-reporter", "description": "PHP client for reporting test coverage to Code Climate", - "keywords": ["codeclimate", "coverage"], + "keywords": [ + "codeclimate", + "coverage" + ], "homepage": "https://github.com/codeclimate/php-test-reporter", "type": "library", "license": "MIT", @@ -15,23 +18,40 @@ "require": { "php": ">=5.3", "ext-curl": "*", - "satooshi/php-coveralls": "1.0.*", - "symfony/console": ">=2.0" + "satooshi/php-coveralls": "^1.0", + "symfony/console": "^2.0" }, "require-dev": { "phpunit/phpunit": "3.7.*@stable", - "ext-xdebug": "*" + "ext-xdebug": "*", + "tm/tooly-composer-script": "^1.0" }, "autoload": { - "psr-0": { - "CodeClimate\\Component": "src/", - "CodeClimate\\Bundle": "src/" + "psr-4": { + "CodeClimate\\PhpTestReporter\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "CodeClimate\\PhpTestReporter\\Tests\\": "tests/" } }, - "bin": ["composer/bin/test-reporter"], + "bin": [ + "composer/bin/test-reporter" + ], + "scripts": { + "post-install-cmd": "Tooly\\ScriptHandler::installPharTools", + "post-update-cmd": "Tooly\\ScriptHandler::installPharTools" + }, "extra": { "branch-alias": { "dev-master": "0.3.x-dev" - } + }, + "tools": { + "box": { + "url": "https://github.com/box-project/box2/releases/download/2.7.2/box-2.7.2.phar", + "only-dev": true + } + } } } diff --git a/composer/bin/test-reporter b/composer/bin/test-reporter index 877de15..3a1e766 100755 --- a/composer/bin/test-reporter +++ b/composer/bin/test-reporter @@ -1,10 +1,14 @@ #!/usr/bin/env php */ class Application extends BaseApplication { /** * Path to project root directory. - * * @var string */ private $rootDir; @@ -37,7 +35,6 @@ public function __construct($rootDir, $name = 'UNKNOWN', $version = 'UNKNOWN') /** * {@inheritdoc} - * * @see \Symfony\Component\Console\Application::getCommandName() */ protected function getCommandName(InputInterface $input) @@ -47,14 +44,13 @@ protected function getCommandName(InputInterface $input) /** * {@inheritdoc} - * * @see \Symfony\Component\Console\Application::getDefaultCommands() */ protected function getDefaultCommands() { // Keep the core default commands to have the HelpCommand // which is used when using the --help option - $defaultCommands = parent::getDefaultCommands(); + $defaultCommands = parent::getDefaultCommands(); $defaultCommands[] = $this->createTestReporterCommand(); return $defaultCommands; @@ -62,8 +58,7 @@ protected function getDefaultCommands() /** * Create TestReporterCommand. - * - * @return \CodeClimate\Bundle\TestReporterBundle\Command\TestReporterCommand + * @return TestReporterCommand */ protected function createTestReporterCommand() { @@ -77,7 +72,6 @@ protected function createTestReporterCommand() /** * {@inheritdoc} - * * @see \Symfony\Component\Console\Application::getDefinition() */ public function getDefinition() diff --git a/src/CodeClimate/Bundle/TestReporterBundle/Command/TestReporterCommand.php b/src/ConsoleCommands/TestReporterCommand.php similarity index 62% rename from src/CodeClimate/Bundle/TestReporterBundle/Command/TestReporterCommand.php rename to src/ConsoleCommands/TestReporterCommand.php index 4fd439d..0db923a 100644 --- a/src/CodeClimate/Bundle/TestReporterBundle/Command/TestReporterCommand.php +++ b/src/ConsoleCommands/TestReporterCommand.php @@ -1,8 +1,9 @@ setName('test-reporter') - ->setDescription('Code Climate PHP Test Reporter') - ->addOption( - 'stdout', - null, - InputOption::VALUE_NONE, - 'Do not upload, print JSON payload to stdout' - ) - ->addOption( - 'coverage-report', - null, - InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, - 'Location of clover style CodeCoverage report, as produced by PHPUnit\'s --coverage-clover option.', - array('build/logs/clover.xml') - ); + ->setName('test-reporter') + ->setDescription('Code Climate PHP Test Reporter') + ->addOption( + 'stdout', + null, + InputOption::VALUE_NONE, + 'Do not upload, print JSON payload to stdout' + ) + ->addOption( + 'coverage-report', + null, + InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, + 'Location of clover style CodeCoverage report, as produced by PHPUnit\'s --coverage-clover option.', + [ 'build/logs/clover.xml' ] + ); } /** * {@inheritdoc} - * * @see \Symfony\Component\Console\Command\Command::execute() */ protected function execute(InputInterface $input, OutputInterface $output) { - $ret = 0; + $ret = 0; $collector = new CoverageCollector($input->getOption('coverage-report')); - $json = $collector->collectAsJson(); + $json = $collector->collectAsJson(); if ($input->getOption('stdout')) { $output->writeln((string)$json); } else { - $client = new ApiClient(); + $client = new ApiClient(); $response = $client->send($json); switch ($response->code) { case 200: @@ -72,7 +70,7 @@ protected function execute(InputInterface $input, OutputInterface $output) break; default: - $output->writeln("Unexpected response: ".$response->code." ".$response->message); + $output->writeln("Unexpected response: " . $response->code . " " . $response->message); $output->writeln($response->body); $ret = 1; break; diff --git a/src/CodeClimate/Bundle/TestReporterBundle/Version.php b/src/Constants/Version.php similarity index 77% rename from src/CodeClimate/Bundle/TestReporterBundle/Version.php rename to src/Constants/Version.php index 103e7d8..b079856 100644 --- a/src/CodeClimate/Bundle/TestReporterBundle/Version.php +++ b/src/Constants/Version.php @@ -1,5 +1,6 @@ apiHost = $_SERVER["CODECLIMATE_API_HOST"]; } - } /** * Send the given JSON as a request to the CodeClimate Server * * @param object $json JSON data + * * @return \stdClass Response object with (code, message, headers & body properties) */ public function send($json) { $response = new \stdClass; - $payload = (string)$json; - $options = array( - 'http' => array( - 'method' => 'POST', - 'header' => array( + $payload = (string)$json; + $options = [ + 'http' => [ + 'method' => 'POST', + 'header' => [ 'Host: codeclimate.com', 'Content-Type: application/json', - 'User-Agent: Code Climate (PHP Test Reporter v'.Version::VERSION.')', - 'Content-Length: '.strlen($payload) - ), + 'User-Agent: Code Climate (PHP Test Reporter v' . Version::VERSION . ')', + 'Content-Length: ' . strlen($payload), + ], 'content' => $payload, - "timeout" => 10 - ) - ); - $context = stream_context_create($options); - $url = $this->apiHost.'/test_reports'; + "timeout" => 10, + ], + ]; + $context = stream_context_create($options); + $url = $this->apiHost . '/test_reports'; if ($stream = @fopen($url, 'r', false, $context)) { - $meta = stream_get_meta_data($stream); - $raw_response = implode("\r\n", $meta['wrapper_data'])."\r\n\r\n".stream_get_contents($stream); + $meta = stream_get_meta_data($stream); + $rawResponse = implode("\r\n", $meta['wrapper_data']) . "\r\n\r\n" . stream_get_contents($stream); fclose($stream); - if (!empty($raw_response)) { - $response = $this->buildResponse($response, $raw_response); + if (!empty($rawResponse)) { + $response = $this->buildResponse($response, $rawResponse); } } else { $response = $this->sendWithCurl($url, $payload); @@ -63,43 +65,44 @@ public function send($json) * Send the given JSON as a request to the CodeClimate Server using cURL. * Added as a backup if PHP Streams method fails (e.g. if allow_url_fopen is disabled). * - * @param string $url The API end-point URL + * @param string $url The API end-point URL * @param string $payload The request payload as a JSON-encoded string + * * @return \stdClass Response object with (code, message, headers & body properties) */ private function sendWithCurl($url, $payload) { $response = new \stdClass; - $curl = curl_init($url); + $curl = curl_init($url); curl_setopt($curl, CURLOPT_HEADER, true); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 10); curl_setopt( $curl, CURLOPT_HTTPHEADER, - array( + [ 'Host: codeclimate.com', 'Content-Type: application/json', - 'User-Agent: Code Climate (PHP Test Reporter v'.Version::VERSION.')', - 'Content-Length: '.strlen($payload) - ) + 'User-Agent: Code Climate (PHP Test Reporter v' . Version::VERSION . ')', + 'Content-Length: ' . strlen($payload), + ] ); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($curl, CURLOPT_POSTFIELDS, $payload); - $raw_response = curl_exec($curl); + $rawResponse = curl_exec($curl); $status = curl_getinfo($curl, CURLINFO_HTTP_CODE); - if (!empty($raw_response)) { - $response = $this->buildResponse($response, $raw_response); + if (!empty($rawResponse)) { + $response = $this->buildResponse($response, $rawResponse); } else { $error = error_get_last(); preg_match('/([0-9]{3})/', $error['message'], $match); $errorCode = (isset($match[1])) ? $match[1] : ($status ? $status : 500); - $response->code = $errorCode; + $response->code = $errorCode; $response->message = $error['message']; - $response->headers = array(); - $response->body = NULL; + $response->headers = [ ]; + $response->body = null; } return $response; @@ -109,7 +112,8 @@ private function sendWithCurl($url, $payload) * Build the response object from the HTTP results * * @param \stdClass $response Standard object - * @param string $body HTTP response contents + * @param string $body HTTP response contents + * * @return \stdClass Populated class object */ private function buildResponse($response, $body) diff --git a/src/CodeClimate/Bundle/TestReporterBundle/CoverageCollector.php b/src/TestReporter/CoverageCollector.php similarity index 86% rename from src/CodeClimate/Bundle/TestReporterBundle/CoverageCollector.php rename to src/TestReporter/CoverageCollector.php index e35326e..6d15dd2 100644 --- a/src/CodeClimate/Bundle/TestReporterBundle/CoverageCollector.php +++ b/src/TestReporter/CoverageCollector.php @@ -1,8 +1,7 @@ setRootDir($rootDir); $this->setCloverPaths($paths); foreach ($this->getCloverPaths() as $path) { @@ -35,6 +34,7 @@ public function __construct($paths) /** * Set a list of Clover XML paths + * * @param array $paths Array of relative paths to Clovers XML files */ public function setCloverPaths($paths) @@ -50,6 +50,7 @@ public function getCloverPaths() { return $this->cloverPaths; } + public function collectAsJson() { $cloverJsonFile = $this->api->collectCloverXml()->getJsonFile(); diff --git a/src/CodeClimate/Bundle/TestReporterBundle/Entity/CiInfo.php b/src/TestReporter/Entity/CiInfo.php similarity index 84% rename from src/CodeClimate/Bundle/TestReporterBundle/Entity/CiInfo.php rename to src/TestReporter/Entity/CiInfo.php index f44431d..12243c3 100644 --- a/src/CodeClimate/Bundle/TestReporterBundle/Entity/CiInfo.php +++ b/src/TestReporter/Entity/CiInfo.php @@ -1,5 +1,5 @@ werckerProperties(); } - return array(); + return [ ]; } protected function travisProperties() { - return array( + return [ "name" => "travis-ci", "branch" => $_SERVER["TRAVIS_BRANCH"], "build_identifier" => $_SERVER["TRAVIS_JOB_ID"], - "pull_request" => $_SERVER["TRAVIS_PULL_REQUEST"] - ); + "pull_request" => $_SERVER["TRAVIS_PULL_REQUEST"], + ]; } protected function circleProperties() { - return array( + return [ "name" => "circleci", "build_identifier" => $_SERVER["CIRCLE_BUILD_NUM"], "branch" => $_SERVER["CIRCLE_BRANCH"], - "commit_sha" => $_SERVER["CIRCLE_SHA1"] - ); + "commit_sha" => $_SERVER["CIRCLE_SHA1"], + ]; } protected function semaphoreProperties() { - return array( + return [ "name" => "semaphore", "branch" => $_SERVER["BRANCH_NAME"], - "build_identifier" => $_SERVER["SEMAPHORE_BUILD_NUMBER"] - ); + "build_identifier" => $_SERVER["SEMAPHORE_BUILD_NUMBER"], + ]; } protected function jenkinsProperties() { - return array( + return [ "name" => "jenkins", "build_identifier" => $_SERVER["BUILD_NUMBER"], "build_url" => $_SERVER["BUILD_URL"], "branch" => $_SERVER["GIT_BRANCH"], - "commit_sha" => $_SERVER["GIT_COMMIT"] - ); + "commit_sha" => $_SERVER["GIT_COMMIT"], + ]; } protected function tddiumProperties() { - return array( + return [ "name" => "tddium", "build_identifier" => $_SERVER["TDDIUM_SESSION_ID"], - "worker_id" => $_SERVER["TDDIUM_TID"] - ); + "worker_id" => $_SERVER["TDDIUM_TID"], + ]; } protected function codeshipProperties() { - return array( + return [ "name" => "codeship", "build_identifier" => $_SERVER["CI_BUILD_NUMBER"], "build_url" => $_SERVER["CI_BUILD_URL"], "branch" => $_SERVER["CI_BRANCH"], - "commit_sha" => $_SERVER["CI_COMMIT_ID"] - ); + "commit_sha" => $_SERVER["CI_COMMIT_ID"], + ]; } protected function buildkiteProperties() { - return array( + return [ "name" => "buildkite", "build_identifier" => $_SERVER["BUILDKITE_BUILD_ID"], "build_url" => $_SERVER["BUILDKITE_BUILD_URL"], "branch" => $_SERVER["BUILDKITE_BRANCH"], "commit_sha" => $_SERVER["BUILDKITE_COMMIT"], - "pull_request" => $_SERVER["BUILDKITE_PULL_REQUEST"] - ); + "pull_request" => $_SERVER["BUILDKITE_PULL_REQUEST"], + ]; } protected function werckerProperties() { - return array( + return [ "name" => "wercker", "build_identifier" => $_SERVER["WERCKER_BUILD_ID"], "build_url" => $_SERVER["WERCKER_BUILD_URL"], "branch" => $_SERVER["WERCKER_GIT_BRANCH"], - "commit_sha" => $_SERVER["WERCKER_GIT_COMMIT"] - ); + "commit_sha" => $_SERVER["WERCKER_GIT_COMMIT"], + ]; } } diff --git a/src/CodeClimate/Bundle/TestReporterBundle/Entity/JsonFile.php b/src/TestReporter/Entity/JsonFile.php similarity index 57% rename from src/CodeClimate/Bundle/TestReporterBundle/Entity/JsonFile.php rename to src/TestReporter/Entity/JsonFile.php index c9ec0c8..8bd414a 100644 --- a/src/CodeClimate/Bundle/TestReporterBundle/Entity/JsonFile.php +++ b/src/TestReporter/Entity/JsonFile.php @@ -1,24 +1,24 @@ false, "run_at" => $this->getRunAt(), "repo_token" => $this->getRepoToken(), "environment" => $this->getEnvironment(), "git" => $this->collectGitInfo(), "ci_service" => $this->collectCiServiceInfo(), - "source_files" => $this->collectSourceFiles() - ); + "source_files" => $this->collectSourceFiles(), + ]; } public function getRunAt() @@ -33,21 +33,21 @@ public function getRepoToken() protected function getEnvironment() { - return array( + return [ "pwd" => getcwd(), - "package_version" => Version::VERSION - ); + "package_version" => Version::VERSION, + ]; } protected function collectGitInfo() { $command = new GitCommand(); - return array( + return [ "head" => $command->getHead(), "branch" => $command->getBranch(), - "committed_at" => $command->getCommittedAt() - ); + "committed_at" => $command->getCommittedAt(), + ]; } protected function collectCiServiceInfo() @@ -59,24 +59,27 @@ protected function collectCiServiceInfo() protected function collectSourceFiles() { - $sourceFiles = array(); + $sourceFiles = [ ]; foreach ($this->getSourceFiles() as $sourceFile) { - array_push($sourceFiles, array( - "name" => $sourceFile->getName(), - "coverage" => json_encode($sourceFile->getCoverage()), - "blob_id" => $this->calculateBlobId($sourceFile) - )); + array_push( + $sourceFiles, + [ + "name" => $sourceFile->getName(), + "coverage" => json_encode($sourceFile->getCoverage()), + "blob_id" => $this->calculateBlobId($sourceFile), + ] + ); } return $sourceFiles; } - protected function calculateBlobId($sourceFile) + protected function calculateBlobId(SourceFile $sourceFile) { $content = file_get_contents($sourceFile->getPath()); - $header = "blob ".strlen($content)."\0"; + $header = "blob " . strlen($content) . "\0"; - return sha1($header.$content); + return sha1($header . $content); } } diff --git a/tests/CodeClimate/Bundle/TestReporterBundle/Console/ApplicationTest.php b/tests/Unit/ApplicationTest.php similarity index 55% rename from tests/CodeClimate/Bundle/TestReporterBundle/Console/ApplicationTest.php rename to tests/Unit/ApplicationTest.php index b093f2c..b0cb847 100644 --- a/tests/CodeClimate/Bundle/TestReporterBundle/Console/ApplicationTest.php +++ b/tests/Unit/ApplicationTest.php @@ -1,6 +1,7 @@ srcDir = realpath(__DIR__ . '/../../../../..'); + $this->srcDir = realpath(__DIR__ . '/../../../../CodeClimateTestReporter'); $this->setupProject(); $this->setupEnvironment(); } @@ -25,18 +26,18 @@ public function shouldExecuteSuccessfully() $app->setAutoExit(false); $tester = new ApplicationTester($app); - $status = $tester->run(array('--stdout' => true)); + $status = $tester->run([ '--stdout' => true ]); $this->assertEquals(0, $status); } private function setupProject() { - shell_exec("rm -rf ".static::PROJECT_DIR); - mkdir(static::PROJECT_DIR."/build/logs", 0755, true); - copy("tests/files/test.php", static::PROJECT_DIR."/test.php"); - copy("tests/files/test.php", static::PROJECT_DIR."/test2.php"); - copy("tests/files/clover.xml", static::PROJECT_DIR."/build/logs/clover.xml"); + shell_exec("rm -rf " . static::PROJECT_DIR); + mkdir(static::PROJECT_DIR . "/build/logs", 0755, true); + copy("tests/files/test.php", static::PROJECT_DIR . "/test.php"); + copy("tests/files/test.php", static::PROJECT_DIR . "/test2.php"); + copy("tests/files/clover.xml", static::PROJECT_DIR . "/build/logs/clover.xml"); chdir(static::PROJECT_DIR); @@ -49,9 +50,9 @@ private function setupProject() private function setupEnvironment() { $_SERVER["CODECLIMATE_REPO_TOKEN"] = 'abc123'; - $_SERVER["TRAVIS"] = "1"; - $_SERVER["TRAVIS_BRANCH"] = "master"; - $_SERVER["TRAVIS_JOB_ID"] = "1"; - $_SERVER["TRAVIS_PULL_REQUEST"] = "fb-feature"; + $_SERVER["TRAVIS"] = "1"; + $_SERVER["TRAVIS_BRANCH"] = "master"; + $_SERVER["TRAVIS_JOB_ID"] = "1"; + $_SERVER["TRAVIS_PULL_REQUEST"] = "fb-feature"; } } diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 727467f..1b84a5c 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,4 +1,3 @@ add('CodeClimate', __DIR__); +require(__DIR__ . '/../vendor/autoload.php');