Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/CLI/Command/Check.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ protected function configure(): void
self::FORMAT_PARAM,
'f',
InputOption::VALUE_OPTIONAL,
'Output format: json or text (default)',
'Output format: text (default), json, gitlab',
'text'
);
}
Expand All @@ -112,7 +112,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$skipBaseline = (bool) $input->getOption(self::SKIP_BASELINE_PARAM);
$ignoreBaselineLinenumbers = (bool) $input->getOption(self::IGNORE_BASELINE_LINENUMBERS_PARAM);
$format = $input->getOption(self::FORMAT_PARAM);
$onlyErrors = Printer::FORMAT_JSON === $format;
$onlyErrors = Printer::FORMAT_JSON === $format || Printer::FORMAT_GITLAB === $format;

if (true !== $skipBaseline && !$useBaseline && file_exists(self::DEFAULT_BASELINE_FILENAME)) {
$useBaseline = self::DEFAULT_BASELINE_FILENAME;
Expand Down Expand Up @@ -285,7 +285,7 @@ private function printNoViolationsDetectedMessage(OutputInterface $output, bool
{
if (!$onlyErrors) {
$output->writeln('<info>NO VIOLATIONS DETECTED!</info>');
} elseif (Printer::FORMAT_JSON === $format) {
} elseif (Printer::FORMAT_JSON === $format || Printer::FORMAT_GITLAB === $format) {
$output->writeln('<info>[]</info>');
}
}
Expand Down
51 changes: 51 additions & 0 deletions src/CLI/Printer/GitlabPrinter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php
declare(strict_types=1);

namespace Arkitect\CLI\Printer;

use Arkitect\Rules\Violation;

class GitlabPrinter implements Printer
{
public function print(array $violationsCollection): string
{
$allErrors = [];

/**
* @var string $key
* @var Violation[] $violationsByFqcn
*/
foreach ($violationsCollection as $class => $violationsByFqcn) {
foreach ($violationsByFqcn as $violation) {
$checkName = $class.'.'.$this->toKebabCase($violation->getError());

$error = [
'description' => $violation->getError(),
'check_name' => $checkName,
'fingerprint' => hash('sha256', $checkName),
'severity' => 'major',
'location' => [
'path' => $violation->getFilePath(),
'lines' => [
'begin' => $violation->getLine() ?? 1,
],
],
];

$allErrors[] = $error;
}
}

return json_encode($allErrors);
}

private function toKebabCase(string $string): string
{
$string = preg_replace('/[^a-zA-Z0-9]+/', ' ', $string);
$string = preg_replace('/\s+/', ' ', $string);
$string = strtolower(trim($string));
$string = str_replace(' ', '-', $string);

return $string;
}
}
2 changes: 2 additions & 0 deletions src/CLI/Printer/Printer.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@ interface Printer

public const FORMAT_JSON = 'json';

public const FORMAT_GITLAB = 'gitlab';

public function print(array $violationsCollection): string;
}
4 changes: 3 additions & 1 deletion src/CLI/Printer/PrinterFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ final class PrinterFactory
public function create(string $format): Printer
{
switch ($format) {
case 'json':
case Printer::FORMAT_GITLAB:
return new GitlabPrinter();
case Printer::FORMAT_JSON:
return new JsonPrinter();
default:
return new TextPrinter();
Expand Down
34 changes: 34 additions & 0 deletions tests/E2E/Cli/CheckCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,40 @@ public function test_json_format_output_no_errors(): void
$this->assertCount(0, $json);
}

public function test_gitlab_format_output(): void
{
$configFilePath = __DIR__.'/../_fixtures/configMvcForYieldBug.php';

$cmdTester = $this->runCheck($configFilePath, null, null, false, false, false, 'gitlab');

$this->assertCheckHasErrors($cmdTester);

$display = $cmdTester->getDisplay();

$this->assertJson($display);

self::assertSame(<<<JSON
[{"description":"should have a name that matches *Controller because all controllers should be end name with Controller","check_name":"App\\\\Controller\\\\Foo.should-have-a-name-that-matches-controller-because-all-controllers-should-be-end-name-with-controller","fingerprint":"1e960c3f49b5ec63ece40321072ef2bd0bc33ad11b7be326f304255d277dc860","severity":"major","location":{"path":"Controller\/Foo.php","lines":{"begin":1}}}]

JSON, $display);
}

public function test_gitlab_format_output_no_errors(): void
{
$configFilePath = __DIR__.'/../_fixtures/configMvcWithoutErrors.php';

$cmdTester = $this->runCheck($configFilePath, null, null, false, false, false, 'gitlab');

$this->assertCheckHasSuccess($cmdTester);

$display = $cmdTester->getDisplay();

$this->assertJson($display);

$json = json_decode($display, true);
$this->assertCount(0, $json);
}

protected function runCheck(
$configFilePath = null,
?bool $stopOnFailure = null,
Expand Down
53 changes: 53 additions & 0 deletions tests/Unit/CLI/Printer/GitlabPrinterTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php
declare(strict_types=1);

namespace Arkitect\Tests\Unit\CLI\Printer;

use Arkitect\CLI\Printer\GitlabPrinter;
use Arkitect\Rules\Violation;
use PHPUnit\Framework\TestCase;

class GitlabPrinterTest extends TestCase
{
/**
* Test the `print` method returns a valid JSON string
* with violations details when violations exist.
*/
public function test_print_with_violations(): void
{
$violation1 = new Violation('App\\ExampleClass', 'Some error message', 42, 'tests/Unit/CLI/Printer/GitlabPrinterTest.php');
$violation2 = new Violation('App\\AnotherExampleClass', 'Another error message', null, 'tests/Unit/CLI/Printer/GitlabPrinterTest.php');

$violationsCollection = [
'RuleA' => [$violation1],
'RuleB' => [$violation2],
];

$printer = new GitlabPrinter();

$result = $printer->print($violationsCollection);

self::assertSame(<<<JSON
[{"description":"Some error message","check_name":"RuleA.some-error-message","fingerprint":"7ddcfd42f5f2af3d00864ef959a0327f508cb5227aedca96d919d681a5dcde4a","severity":"major","location":{"path":"tests\/Unit\/CLI\/Printer\/GitlabPrinterTest.php","lines":{"begin":42}}},{"description":"Another error message","check_name":"RuleB.another-error-message","fingerprint":"800c2ceafbf4023e401200186ecabdfe59891c5d6670e86571e3c50339df07dc","severity":"major","location":{"path":"tests\/Unit\/CLI\/Printer\/GitlabPrinterTest.php","lines":{"begin":1}}}]
JSON, $result);
}

/**
* Test the `print` method returns an empty JSON array
* when no violations are provided.
*/
public function test_print_with_no_violations(): void
{
$violationsCollection = [];

$printer = new GitlabPrinter();

$result = $printer->print($violationsCollection);

$this->assertIsString($result, 'Result should be a string');
$this->assertJson($result, 'Result should be a valid JSON string');

$decodedResult = json_decode($result, true);
$this->assertEmpty($decodedResult, 'Result should be an empty array');
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php
declare(strict_types=1);

namespace Arkitect\Tests\Unit\Printer;
namespace Arkitect\Tests\Unit\CLI\Printer;

use Arkitect\CLI\Printer\JsonPrinter;
use Arkitect\Rules\Violation;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php
declare(strict_types=1);

namespace Arkitect\Tests\Unit\Printer;
namespace Arkitect\Tests\Unit\CLI\Printer;

use Arkitect\CLI\Printer\JsonPrinter;
use Arkitect\CLI\Printer\PrinterFactory;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php
declare(strict_types=1);

namespace Arkitect\Tests\Unit\Printer;
namespace Arkitect\Tests\Unit\CLI\Printer;

use Arkitect\CLI\Printer\TextPrinter;
use Arkitect\Rules\Violation;
Expand Down