Skip to content

Commit

Permalink
Extend by the Code Climate output format
Browse files Browse the repository at this point in the history
The Code Climate format is used in the GitLab CI/CD to show errors in
the merge request page. The simple JSON format is not sufficient for
this.
  • Loading branch information
Lukas Hettwer authored and grogy committed May 8, 2021
1 parent 2c07745 commit a6090fc
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ It is strongly recommended for existing users of the (unmaintained)
- `--no-progress` Disable progress in console output.
- `--checkstyle` Output results as Checkstyle XML.
- `--json` Output results as JSON string (requires PHP 5.4).
- `--gitlab` Output results for the GitLab Code Quality widget (requires PHP 5.4), see more in [Code Quality](https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html) documentation.
- `--blame` Try to show git blame for row with error.
- `--git <git>` Path to Git executable to show blame message (default: 'git').
- `--stdin` Load files and folder to test from standard input.
Expand Down
1 change: 1 addition & 0 deletions src/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ private function showOptions()
--no-colors Disable colors in console output.
--no-progress Disable progress in console output.
--json Output results as JSON string.
--gitlab Output results for the GitLab Code Quality Widget.
--checkstyle Output results as Checkstyle XML.
--blame Try to show git blame for row with error.
--git <git> Path to Git executable to show blame message (default: 'git').
Expand Down
2 changes: 2 additions & 0 deletions src/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ protected function getDefaultOutput(Settings $settings)
switch ($settings->format) {
case Settings::FORMAT_JSON:
return new JsonOutput($writer);
case Settings::FORMAT_GITLAB:
return new GitLabOutput($writer);
case Settings::FORMAT_CHECKSTYLE:
return new CheckstyleOutput($writer);
}
Expand Down
75 changes: 75 additions & 0 deletions src/Output.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,81 @@ public function writeResult(Result $result, ErrorFormatter $errorFormatter, $ign
}
}

class GitLabOutput implements Output
{
/** @var IWriter */
protected $writer;

/**
* @param IWriter $writer
*/
public function __construct(IWriter $writer)
{
$this->writer = $writer;
}

public function ok()
{

}

public function skip()
{

}

public function error()
{

}

public function fail()
{

}

public function setTotalFileCount($count)
{

}

public function writeHeader($phpVersion, $parallelJobs, $hhvmVersion = null)
{

}

public function writeResult(Result $result, ErrorFormatter $errorFormatter, $ignoreFails)
{
$errors = array();
foreach ($result->getErrors() as $error) {
$message = $error->getMessage();
$line = 1;
if ($error instanceof SyntaxError) {
$line = $error->getLine();
}
$filePath = $error->getFilePath();
$result = array(
'type' => 'issue',
'check_name' => 'Parse error',
'description' => $message,
'categories' => 'Style',
'fingerprint' => md5($filePath . $message . $line),
'severity' => 'minor',
'location' => array(
'path' => $filePath,
'lines' => array(
'begin' => $line,
),
),
);
array_push($errors, $result);
}

$string = json_encode($errors) . PHP_EOL;
$this->writer->write($string);
}
}

class TextOutput implements Output
{
const TYPE_DEFAULT = 'default',
Expand Down
5 changes: 5 additions & 0 deletions src/Settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class Settings

const FORMAT_TEXT = 'text';
const FORMAT_JSON = 'json';
const FORMAT_GITLAB = 'gitlab';
const FORMAT_CHECKSTYLE = 'checkstyle';

/**
Expand Down Expand Up @@ -179,6 +180,10 @@ public static function parseArguments(array $arguments)
$settings->format = self::FORMAT_JSON;
break;

case '--gitlab':
$settings->format = self::FORMAT_GITLAB;
break;

case '--checkstyle':
$settings->format = self::FORMAT_CHECKSTYLE;
break;
Expand Down
95 changes: 95 additions & 0 deletions tests/Output.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?php

/**
* @testCase
*/

require __DIR__ . '/../vendor/autoload.php';

use JakubOnderka\PhpParallelLint\ErrorFormatter;
use JakubOnderka\PhpParallelLint\GitLabOutput;
use JakubOnderka\PhpParallelLint\IWriter;
use JakubOnderka\PhpParallelLint\Result;
use JakubOnderka\PhpParallelLint\SyntaxError;
use Tester\Assert;

class OutputTest extends Tester\TestCase
{
/**
* @dataProvider getGitLabOutputData
*/
public function testGitLabOutput($errors)
{
$result = new Result($errors, array(), array(), 0);
$writer = new TestWriter();
$output = new GitLabOutput($writer);

$output->writeResult($result, new ErrorFormatter(), true);

$result = (array) json_decode($writer->getLogs());

for ($i = 0; $i < count($result) && $i < count($errors); $i++) {
$message = $errors[$i]->getMessage();
$filePath = $errors[$i]->getFilePath();
$line = 1;
if ($errors[$i] instanceof SyntaxError) {
$line = $errors[$i]->getLine();
}
Assert::equal($result[$i]->type, 'issue');
Assert::equal($result[$i]->check_name, 'Parse error');
Assert::equal($result[$i]->categories, 'Style');
Assert::equal($result[$i]->severity, 'minor');
Assert::equal($result[$i]->description, $message);
Assert::equal($result[$i]->fingerprint, md5($filePath . $message . $line));
Assert::equal($result[$i]->location->path, $filePath);
Assert::equal($result[$i]->location->lines->begin, $line);
}
}

public function getGitLabOutputData()
{
return array(
array(
'errors' => array()
),
array(
'errors' => array(
new SyntaxError('foo/bar.php', "Parse error: syntax error, unexpected in foo/bar.php on line 52")
)
),
array(
'errors' => array(
new JakubOnderka\PhpParallelLint\Error('foo/bar.php', "PHP Parse error: syntax error, unexpected ';'")
)
),
array(
'errors' => array(
new SyntaxError('foo/bar.php', "Parse error: syntax error, unexpected in foo/bar.php on line 52"),
new JakubOnderka\PhpParallelLint\Error('foo/bar.php', "PHP Parse error: syntax error, unexpected ';'")
)
),
);
}
}

class TestWriter implements IWriter
{
/** @var string */
protected $logs = "";

/**
* @param string $string
*/
public function write($string)
{
$this->logs .= $string;
}

public function getLogs()
{
return $this->logs;
}
}

$testCase = new OutputTest;
$testCase->run();
8 changes: 8 additions & 0 deletions tests/Settings.parseArguments.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,14 @@ class SettingsParseArgumentsTest extends Tester\TestCase
Assert::equal(Settings::FORMAT_JSON, $settings->format);
}

public function testGitLabOutput()
{
$commandLine = './parallel-lint --gitlab .';
$argv = explode(" ", $commandLine);
$settings = Settings::parseArguments($argv);
Assert::equal(Settings::FORMAT_GITLAB, $settings->format);
}

public function testCheckstyleOutput()
{
$commandLine = './parallel-lint --checkstyle .';
Expand Down

0 comments on commit a6090fc

Please sign in to comment.