Skip to content

Commit

Permalink
Replace badge logger with more advanced stryker logger (#1629)
Browse files Browse the repository at this point in the history
* Replace `badge` logger with more advanced `stryker` logger

Related to #1625

Now, Stryker logger allows to send badge information or the full mutation test elements report to display HTML report on Stryker Dashboard.

Example: https://dashboard.stryker-mutator.io/reports/github.com/infection/infection/master#mutant

Note, at the time of creating this PR, Stryker Dashboard has an old version of mutation-testing-elements lib which is too slow. Made a PR to update it: stryker-mutator/stryker-dashboard#211. The locally generated `html` report (see `logger.html` in `infection.json` already generates report with the latest lib)

This is a BC break.

Before:

`infection.json`

```json
{
    "logs": {
        "badge": {
            "branch": "master"
        }
    }
}
```

After:

`infection.json` - for badge information only

```json
{
    "logs": {
        "stryker": {
            "badge": "master"
        }
    }
}
```

or for badge *and* HTML report

```json
{
    "logs": {
        "badge": {
            "report": "master"
        }
    }
}
```

* Add more tests, remove todo
  • Loading branch information
maks-rafalko committed Jan 8, 2022
1 parent d96aa59 commit a749d72
Show file tree
Hide file tree
Showing 24 changed files with 365 additions and 187 deletions.
4 changes: 2 additions & 2 deletions infection.json
Expand Up @@ -7,8 +7,8 @@
]
},
"logs": {
"badge": {
"branch": "master"
"stryker": {
"badge": "master"
}
},
"mutators": {
Expand Down
52 changes: 33 additions & 19 deletions resources/schema.json
Expand Up @@ -70,26 +70,27 @@
"type": "string",
"description": "Markdown file which will give a break-down of the effectiveness of each mutator."
},
"badge": {
"type": "object",
"description": "Mutation score badge for your GitHub project. If provided, infection will report results for maching branches to an upstream reporting dashboard/collector.",
"additionalProperties": false,
"required": ["branch"],
"properties": {
"branch": {
"type": "string",
"description": "Mutation score badge for your GitHub project. If this value starts and ends with \"/\", it will be considered a regular expression.",
"exaples": [
"main",
"master",
"develop",
"latest",
"/1\\.\\d+/",
"/release-.*/",
"/feature\\/.*/"
]
"stryker": {

This comment has been minimized.

Copy link
@Ocramius

Ocramius Jan 10, 2022

Contributor

The fact that "badge" no longer exists at top-level is a bit of an annoying BC break: is this intentional?

This comment has been minimized.

Copy link
@maks-rafalko

maks-rafalko Jan 10, 2022

Author Member

This comment has been minimized.

Copy link
@Ocramius

Ocramius Jan 10, 2022

Contributor

Thanks for clarifying!

"oneOf": [

This comment has been minimized.

Copy link
@Ocramius

Ocramius Jan 10, 2022

Contributor

Is the oneOf intentional? It's not possible to set both "badge": ... and "report": ..., so perhaps missing something, although they seem to do the same thing?

This comment has been minimized.

Copy link
@maks-rafalko

maks-rafalko Jan 10, 2022

Author Member

stryker replaces badge because it's more advanced.

  • it can have only badge setting (uploaded to Stryker Dashboard)
  • or it can have only report setting, that uploads the whole HTML report and at the same time includes Badge

If you need only badge - use stryker.badge. If you need HTML report - user stryker.report and Badge will be "included" as well by Stryker Dashboard in additional to HTML report

This comment has been minimized.

Copy link
@maks-rafalko

maks-rafalko Jan 10, 2022

Author Member

perhaps missing something, although they seem to do the same thing?

mistake in the description, I will update it, thank you

This comment has been minimized.

Copy link
@Ocramius

Ocramius Jan 10, 2022

Contributor

Excellent, will then use logs.stryker.report on my projects 👍

{
"type": "object",
"required": ["badge"],
"description": "Mutation score badge for your GitHub project. If provided, Infection will report results for matching branches to an upstream reporting dashboard.",
"additionalProperties": false,
"properties": {
"badge": { "$ref": "#/definitions/stryker-branch" }
}
},
{
"type": "object",
"required": ["report"],
"description": "Mutation score badge for your GitHub project. If provided, Infection will report results for matching branches to an upstream reporting dashboard.",
"additionalProperties": false,
"properties": {
"report": { "$ref": "#/definitions/stryker-branch" }
}
}
}
]
},
"github": {
"type": "boolean",
Expand Down Expand Up @@ -603,6 +604,19 @@
}
}
]
},
"stryker-branch": {
"type": "string",
"description": "Mutation score badge for your GitHub project. If this value starts and ends with \"/\", it will be considered a regular expression.",
"examples": [
"main",
"master",
"develop",
"latest",
"/1\\.\\d+/",
"/release-.*/",
"/feature\\/.*/"
]
}
}
}
10 changes: 5 additions & 5 deletions src/Configuration/Entry/Logs.php
Expand Up @@ -48,7 +48,7 @@ class Logs
private ?string $debugLogFilePath;
private ?string $perMutatorFilePath;
private bool $useGitHubAnnotationsLogger;
private ?Badge $badge;
private ?StrykerConfig $strykerConfig;

public function __construct(
?string $textLogFilePath,
Expand All @@ -58,7 +58,7 @@ public function __construct(
?string $debugLogFilePath,
?string $perMutatorFilePath,
bool $useGitHubAnnotationsLogger,
?Badge $badge
?StrykerConfig $strykerConfig
) {
$this->textLogFilePath = $textLogFilePath;
$this->htmlLogFilePath = $htmlLogFilePath;
Expand All @@ -67,7 +67,7 @@ public function __construct(
$this->debugLogFilePath = $debugLogFilePath;
$this->perMutatorFilePath = $perMutatorFilePath;
$this->useGitHubAnnotationsLogger = $useGitHubAnnotationsLogger;
$this->badge = $badge;
$this->strykerConfig = $strykerConfig;
}

public static function createEmpty(): self
Expand Down Expand Up @@ -129,8 +129,8 @@ public function getUseGitHubAnnotationsLogger(): bool
return $this->useGitHubAnnotationsLogger;
}

public function getBadge(): ?Badge
public function getStrykerConfig(): ?StrykerConfig
{
return $this->badge;
return $this->strykerConfig;
}
}
Expand Up @@ -44,15 +44,22 @@
/**
* @internal
*/
final class Badge
final class StrykerConfig
{
private string $branchMatch;
private bool $isForFullReport;

/**
* Stryker has 2 ways for integration (https://stryker-mutator.io/docs/General/dashboard):
* - badge only
* - full report
*
* @throws InvalidArgumentException when the provided $branch looks like a regular expression, but is not a valid one
*/
public function __construct(string $branch)
private function __construct(string $branch, bool $isForFullReport)
{
$this->isForFullReport = $isForFullReport;

if (preg_match('#^/.+/$#', $branch) === 0) {
$this->branchMatch = '/^' . preg_quote($branch, '/') . '$/';

Expand All @@ -73,6 +80,21 @@ public function __construct(string $branch)
$this->branchMatch = $branch;
}

public static function forBadge(string $branch): self
{
return new self($branch, false);
}

public static function forFullReport(string $branch): self
{
return new self($branch, true);
}

public function isForFullReport(): bool
{
return $this->isForFullReport;
}

public function applicableForBranch(string $branchName): bool
{
return preg_match($this->branchMatch, $branchName) === 1;
Expand Down
25 changes: 17 additions & 8 deletions src/Configuration/Schema/SchemaConfigurationFactory.php
Expand Up @@ -38,10 +38,10 @@
use function array_filter;
use function array_map;
use function array_values;
use Infection\Configuration\Entry\Badge;
use Infection\Configuration\Entry\Logs;
use Infection\Configuration\Entry\PhpUnit;
use Infection\Configuration\Entry\Source;
use Infection\Configuration\Entry\StrykerConfig;
use stdClass;
use function trim;

Expand Down Expand Up @@ -88,18 +88,27 @@ private static function createLogs(stdClass $logs): Logs
self::normalizeString($logs->debug ?? null),
self::normalizeString($logs->perMutator ?? null),
$logs->github ?? false,
self::createBadge($logs->badge ?? null)
self::createStrykerConfig($logs->stryker ?? null)
);
}

private static function createBadge(?stdClass $badge): ?Badge
private static function createStrykerConfig(?stdClass $stryker): ?StrykerConfig
{
$branch = self::normalizeString($badge->branch ?? null);
if ($stryker === null) {
return null;
}

$branch = self::normalizeString($stryker->badge ?? $stryker->report ?? null);

if ($branch === null) {
return null;
}

if (($stryker->badge ?? null) !== null) {
return StrykerConfig::forBadge($branch);
}

return $branch === null
? null
: new Badge($branch)
;
return StrykerConfig::forFullReport($branch);
}

private static function createPhpUnit(stdClass $phpUnit): PhpUnit
Expand Down
13 changes: 7 additions & 6 deletions src/Container.php
Expand Up @@ -78,12 +78,12 @@
use Infection\FileSystem\SourceFileCollector;
use Infection\FileSystem\SourceFileFilter;
use Infection\FileSystem\TmpDirProvider;
use Infection\Logger\BadgeLoggerFactory;
use Infection\Logger\FederatedLogger;
use Infection\Logger\FileLoggerFactory;
use Infection\Logger\GitHub\GitDiffFileProvider;
use Infection\Logger\Html\StrykerHtmlReportBuilder;
use Infection\Logger\MutationTestingResultsLogger;
use Infection\Logger\StrykerLoggerFactory;
use Infection\Metrics\FilteringResultsCollectorFactory;
use Infection\Metrics\MetricsCalculator;
use Infection\Metrics\MinMsiChecker;
Expand Down Expand Up @@ -549,9 +549,10 @@ public static function create(): self
FilesDiffChangedLines::class => static function (self $container): FilesDiffChangedLines {
return new FilesDiffChangedLines($container->getDiffChangedLinesParser(), $container->getGitDiffFileProvider());
},
BadgeLoggerFactory::class => static function (self $container): BadgeLoggerFactory {
return new BadgeLoggerFactory(
StrykerLoggerFactory::class => static function (self $container): StrykerLoggerFactory {
return new StrykerLoggerFactory(
$container->getMetricsCalculator(),
$container->getStrykerHtmlReportBuilder(),
$container->getCiDetector(),
$container->getLogger()
);
Expand All @@ -575,7 +576,7 @@ public static function create(): self
$container->getFileLoggerFactory()->createFromLogEntries(
$container->getConfiguration()->getLogs()
),
$container->getBadgeLoggerFactory()->createFromLogEntries(
$container->getStrykerLoggerFactory()->createFromLogEntries(
$container->getConfiguration()->getLogs()
),
]));
Expand Down Expand Up @@ -1168,9 +1169,9 @@ public function getFileLoggerFactory(): FileLoggerFactory
return $this->get(FileLoggerFactory::class);
}

public function getBadgeLoggerFactory(): BadgeLoggerFactory
public function getStrykerLoggerFactory(): StrykerLoggerFactory
{
return $this->get(BadgeLoggerFactory::class);
return $this->get(StrykerLoggerFactory::class);
}

public function getMutationTestingResultsLogger(): MutationTestingResultsLogger
Expand Down
6 changes: 4 additions & 2 deletions src/Environment/StrykerApiKeyResolver.php
Expand Up @@ -36,6 +36,7 @@
namespace Infection\Environment;

use function array_key_exists;
use function array_slice;
use function is_string;

/**
Expand All @@ -53,7 +54,8 @@ final class StrykerApiKeyResolver
public function resolve(array $environment): string
{
$names = [
'INFECTION_BADGE_API_KEY',
'INFECTION_BADGE_API_KEY', // deprecated
'INFECTION_DASHBOARD_API_KEY',
'STRYKER_DASHBOARD_API_KEY',
];

Expand All @@ -65,6 +67,6 @@ public function resolve(array $environment): string
return $environment[$name];
}

throw CouldNotResolveStrykerApiKey::from(...$names);
throw CouldNotResolveStrykerApiKey::from(...array_slice($names, 1));
}
}
4 changes: 2 additions & 2 deletions src/Logger/Http/StrykerCurlClient.php
Expand Up @@ -55,8 +55,8 @@
* @internal
* @final
*
* @see https://github.com/stryker-mutator/stryker-handbook/blob/master/dashboard.md#send-a-report-via-curl
* @see https://github.com/stryker-mutator/mutation-testing-elements/tree/master/packages/mutation-testing-report-schema
* @see https://stryker-mutator.io/docs/General/dashboard
* @see https://github.com/stryker-mutator/mutation-testing-elements/blob/master/packages/report-schema/src/mutation-testing-report-schema.json
*/
class StrykerCurlClient
{
Expand Down
5 changes: 2 additions & 3 deletions src/Logger/Http/StrykerDashboardClient.php
Expand Up @@ -37,7 +37,6 @@

use function in_array;
use Psr\Log\LoggerInterface;
use function Safe\json_encode;
use function Safe\sprintf;

/**
Expand All @@ -58,13 +57,13 @@ public function sendReport(
string $repositorySlug,
string $branch,
string $apiKey,
float $mutationScore
string $reportJson
): void {
$response = $this->client->request(
$repositorySlug,
$branch,
$apiKey,
json_encode(['mutationScore' => $mutationScore])
$reportJson
);

$statusCode = $response->getStatusCode();
Expand Down

0 comments on commit a749d72

Please sign in to comment.