Skip to content
Open
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
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,53 @@
# PHPCS GitLab Report

[![Build Status](https://travis-ci.org/sateshpersaud/phpcs-gitlab-report.svg?branch=master)](https://travis-ci.org/sateshpersaud/phpcs-gitlab-report)

## Usage

### Code Quality

```yaml
# .gitlab-ci.yml

code_quality:
image: lorisleiva/laravel-docker:7.2
stage: test
script:
- php ./vendor/bin/phpcs \
--report=\\Satesh\\Phpcs\\CodeQualityReport \
--standard=PSR2 \
--basepath=./ \
--report-file=gl-code-quality-report.json \
src
artifacts:
reports:
codequality: gl-code-quality-report.json
paths:
- ./gl-code-quality-report.json
allow_failure: true
```


### SAST

*Note: use with [pheromone/phpcs-security-audit](https://github.com/FloeDesignTechnologies/phpcs-security-audit)*

```yaml
# .gitlab-ci.yml

phpcs-security-audit-sast:
stage: test
script:
- php ./vendor/bin/phpcs \
--report=\\Satesh\\Phpcs\\SecurityReport \
--standard=./vendor/pheromone/phpcs-security-audit/example_base_ruleset.xml \
--basepath=./ \
--report-file=gl-sast-report.json \
src
artifacts:
reports:
sast: gl-sast-report.json
paths:
- ./gl-sast-report.json
allow_failure: true
```
3 changes: 3 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,8 @@
"psr-4": {
"Satesh\\Phpcs\\": "src"
}
},
"scripts": {
"test": "./vendor/bin/phpunit"
}
}
2 changes: 1 addition & 1 deletion src/GitLabReport.php → src/CodeQualityReport.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Reports\Report;

class GitLabReport implements Report
class CodeQualityReport implements Report
{
/**
* {@inheritDoc}
Expand Down
87 changes: 87 additions & 0 deletions src/SecurityReport.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php declare(strict_types = 1);

namespace Satesh\Phpcs;

use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Reports\Report;

class SecurityReport implements Report
{
const SEVERITY = [
0 => 'Undefined',
1 => 'Info',
2 => 'Unknown',
3 => 'Low',
4 => 'Medium',
5 => 'High',
6 => 'Critical',
];

/**
* {@inheritDoc}
*/
public function generateFileReport($report, File $phpcsFile = null, $showSources = false, $width = 80): bool
{
foreach ($report['messages'] as $line => $lineErrors) {
foreach ($lineErrors as $column => $columnErrors) {
foreach ($columnErrors as $error) {
$gitLabError = [
'category' => 'sast',
'name' => rtrim($error['message'], '.'),
'message' => rtrim($error['message'], '.'),
'severity' => $this->getSeverity($error),
'scanner' => [
'id' => 'phpcs_security_audit',
'name' => 'phpcs-security-audit native',
],
'location' => [
'file' => $report['filename'],
'start_line' => $line,
],
'identifiers' => [
"type" => "phpcs_security_audit_source",
'name' => $error['source'],
'value' => $error['source'],
]
];

echo json_encode($gitLabError) . ',';
}
}
}

return true;
}

protected function getSeverity($error) {
switch ($error['type']) {
case "ERROR":
return "High";
case "WARNING":
return "Low";
default:
return "Undefined";
}
}

/**
* {@inheritDoc}
*/
public function generate(
$cachedData,
$totalFiles,
$totalErrors,
$totalWarnings,
$totalFixable,
$showSources = false,
$width = 80,
$interactive = false,
$toScreen = true
): void {
echo '{';
echo '"version": "2.0", ';
echo '"vulnerabilities": [' . rtrim($cachedData, ',') . '], ';
echo '"remediations": []';
echo '}';
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
<?php declare(strict_types = 1);

use PHPUnit\Framework\TestCase;
use Satesh\Phpcs\GitLabReport;
use Satesh\Phpcs\CodeQualityReport;

class GitLabReportTest extends TestCase
class CodeQualityReportTest extends TestCase
{
public function testGenerateFileReport(): string
{
$reportOutput = $this->getGitLabReport();

$this->expectOutputString($reportOutput);

$gitLabReport = new GitLabReport();
$gitLabReport = new CodeQualityReport();

$returnValue = $gitLabReport->generateFileReport($this->getPhpcsReport());

Expand All @@ -27,7 +27,7 @@ public function testGenerate(string $fileReport): void
{
$this->expectOutputString('[' . rtrim($fileReport, ',') . ']');

$gitLabReport = new GitLabReport();
$gitLabReport = new CodeQualityReport();

$gitLabReport->generate($fileReport, 1, 1, 1, 1);
}
Expand Down
68 changes: 68 additions & 0 deletions tests/SecurityReportTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php declare(strict_types = 1);

use PHPUnit\Framework\TestCase;
use Satesh\Phpcs\CodeQualityReport;
use Satesh\Phpcs\SecurityReport;

class SecurityReportTest extends TestCase
{
public function testGenerateFileReport(): string
{
$reportOutput = $this->getGitLabReport();

$this->expectOutputString($reportOutput);

$gitLabReport = new SecurityReport();

$returnValue = $gitLabReport->generateFileReport($this->getPhpcsReport());

static::assertTrue($returnValue);

return $reportOutput;
}

/**
* @depends testGenerateFileReport
*/
public function testGenerate(string $fileReport): void
{
$this->expectOutputString($this->getGitLabCompleteReport());

$gitLabReport = new SecurityReport();

$gitLabReport->generate($fileReport, 1, 1, 1, 1);
}

private function getGitLabReport(): string
{
return '{"category":"sast","name":"PHP files must only contain PHP code","message":"PHP files must only contain PHP code","severity":"High","scanner":{"id":"phpcs_security_audit","name":"phpcs-security-audit native"},"location":{"file":"files\/TestClass.php","start_line":3},"identifiers":{"type":"phpcs_security_audit_source","name":"Generic.Files.InlineHTML.Found","value":"Generic.Files.InlineHTML.Found"}},';
}

private function getGitLabCompleteReport(): string
{
return '{"version": "2.0", "vulnerabilities": [' . rtrim($this->getGitLabReport(), ',') . '], "remediations": []}';
}

private function getPhpcsReport(): array
{
return [
'filename' => 'files/TestClass.php',
'errors' => 1,
'warnings' => 0,
'fixable' => 0,
'messages' => [
3 => [
1 => [
[
'message' => 'PHP files must only contain PHP code.',
'source' => 'Generic.Files.InlineHTML.Found',
'severity' => 5,
'fixable' => false,
'type' => 'ERROR',
],
],
],
],
];
}
}