diff --git a/.github/workflows/mt-annotations.yaml b/.github/workflows/mt-annotations.yaml
index 9958b3609..96fd35d64 100644
--- a/.github/workflows/mt-annotations.yaml
+++ b/.github/workflows/mt-annotations.yaml
@@ -49,4 +49,4 @@ jobs:
- name: Run Infection for added files only
run: |
git fetch origin $GITHUB_BASE_REF
- php bin/infection -j2 --git-diff-lines --git-diff-base=origin/$GITHUB_BASE_REF --logger-github --ignore-msi-with-no-mutations --only-covered
+ php bin/infection -j2 --git-diff-lines --git-diff-base=origin/$GITHUB_BASE_REF --ignore-msi-with-no-mutations --only-covered
diff --git a/.github/workflows/mt.yaml b/.github/workflows/mt.yaml
index cd235fd2d..a3c1726ff 100644
--- a/.github/workflows/mt.yaml
+++ b/.github/workflows/mt.yaml
@@ -11,7 +11,7 @@ on:
- master
env:
- MIN_MSI: 71.05
+ MIN_MSI: 71.39
MIN_COVERED_MSI: 86.78
jobs:
diff --git a/src/Command/RunCommand.php b/src/Command/RunCommand.php
index 3f2ec9481..260130b32 100644
--- a/src/Command/RunCommand.php
+++ b/src/Command/RunCommand.php
@@ -37,6 +37,7 @@
use function extension_loaded;
use function file_exists;
+use function getenv;
use function implode;
use Infection\Configuration\Configuration;
use Infection\Configuration\Schema\SchemaConfigurationLoader;
@@ -61,8 +62,9 @@
use InvalidArgumentException;
use const PHP_SAPI;
use Psr\Log\LoggerInterface;
-use function Safe\sprintf;
+use function sprintf;
use Symfony\Component\Console\Input\ArrayInput;
+use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use function trim;
@@ -264,8 +266,9 @@ protected function configure(): void
->addOption(
self::OPTION_LOGGER_GITHUB,
null,
- InputOption::VALUE_NONE,
- 'Log escaped Mutants as GitHub Annotations.',
+ InputOption::VALUE_OPTIONAL,
+ 'Log escaped Mutants as GitHub Annotations (automatically detected on Github Actions itself, use true to force-enable or false to force-disable it).',
+ false
)
->addOption(
self::OPTION_LOGGER_HTML,
@@ -482,7 +485,7 @@ private function createContainer(IO $io, LoggerInterface $logger): Container
$gitDiffFilter,
$isForGitDiffLines,
$gitDiffBase,
- (bool) $input->getOption(self::OPTION_LOGGER_GITHUB),
+ $this->getUseGitHubLogger($input),
$htmlFileLogPath === '' ? Container::DEFAULT_HTML_LOGGER_PATH : $htmlFileLogPath,
(bool) $input->getOption(self::OPTION_USE_NOOP_MUTATORS),
(bool) $input->getOption(self::OPTION_EXECUTE_ONLY_COVERING_TEST_CASES)
@@ -606,4 +609,38 @@ private function logRunningWithDebugger(ConsoleOutput $consoleOutput): void
$consoleOutput->logRunningWithDebugger('PCOV');
}
}
+
+ private function getUseGitHubLogger(InputInterface $input): ?bool
+ {
+ // on e2e environment, we don't need github logger
+ if (getenv('INFECTION_E2E_TESTS_ENV') !== false) {
+ return false;
+ }
+
+ $useGitHubLogger = $input->getOption(self::OPTION_LOGGER_GITHUB);
+ // `false` means the option was not provided at all -> user does not care and it will be auto-detected
+ // `null` means the option was provided without any argument -> user wants to enable it
+ // any string: the argument provided, but only `'true'` and `'false` are supported
+ if ($useGitHubLogger === false) {
+ return null;
+ }
+
+ if ($useGitHubLogger === null) {
+ return true;
+ }
+
+ if ($useGitHubLogger === 'true') {
+ return true;
+ }
+
+ if ($useGitHubLogger === 'false') {
+ return false;
+ }
+
+ throw new InvalidArgumentException(sprintf(
+ 'Cannot pass "%s" to "--%s": only "true", "false" or no argument is supported',
+ $useGitHubLogger,
+ self::OPTION_LOGGER_GITHUB
+ ));
+ }
}
diff --git a/src/Configuration/ConfigurationFactory.php b/src/Configuration/ConfigurationFactory.php
index a6909d71d..c5ce31b28 100644
--- a/src/Configuration/ConfigurationFactory.php
+++ b/src/Configuration/ConfigurationFactory.php
@@ -52,7 +52,9 @@
use Infection\Mutator\MutatorParser;
use Infection\Mutator\MutatorResolver;
use Infection\TestFramework\TestFrameworkTypes;
+use OndraM\CiDetector\CiDetector;
use OndraM\CiDetector\CiDetectorInterface;
+use OndraM\CiDetector\Exception\CiNotDetectedException;
use function Safe\sprintf;
use function sys_get_temp_dir;
use Webmozart\Assert\Assert;
@@ -118,7 +120,7 @@ public function create(
?string $gitDiffFilter,
bool $isForGitDiffLines,
?string $gitDiffBase,
- bool $useGitHubLogger,
+ ?bool $useGitHubLogger,
?string $htmlLogFilePath,
bool $useNoopMutators,
bool $executeOnlyCoveringTestCases
@@ -316,8 +318,12 @@ private function retrieveFilter(string $filter, ?string $gitDiffFilter, bool $is
return $this->gitDiffFileProvider->provide($gitDiffFilter, $baseBranch);
}
- private function retrieveLogs(Logs $logs, bool $useGitHubLogger, ?string $htmlLogFilePath): Logs
+ private function retrieveLogs(Logs $logs, ?bool $useGitHubLogger, ?string $htmlLogFilePath): Logs
{
+ if ($useGitHubLogger === null) {
+ $useGitHubLogger = $this->detectCiGithubActions();
+ }
+
if ($useGitHubLogger) {
$logs->setUseGitHubAnnotationsLogger($useGitHubLogger);
}
@@ -328,4 +334,15 @@ private function retrieveLogs(Logs $logs, bool $useGitHubLogger, ?string $htmlLo
return $logs;
}
+
+ private function detectCiGithubActions(): bool
+ {
+ try {
+ $ci = $this->ciDetector->detect();
+ } catch (CiNotDetectedException $e) {
+ return false;
+ }
+
+ return $ci->getCiName() === CiDetector::CI_GITHUB_ACTIONS;
+ }
}
diff --git a/src/Container.php b/src/Container.php
index f4d4ab69c..541a9a0cd 100644
--- a/src/Container.php
+++ b/src/Container.php
@@ -169,7 +169,7 @@ final class Container
public const DEFAULT_GIT_DIFF_FILTER = null;
public const DEFAULT_GIT_DIFF_LINES = false;
public const DEFAULT_GIT_DIFF_BASE = null;
- public const DEFAULT_USE_GITHUB_LOGGER = false;
+ public const DEFAULT_USE_GITHUB_LOGGER = null;
public const DEFAULT_HTML_LOGGER_PATH = null;
public const DEFAULT_USE_NOOP_MUTATORS = false;
public const DEFAULT_EXECUTE_ONLY_COVERING_TEST_CASES = false;
@@ -610,7 +610,7 @@ public function withValues(
?string $gitDiffFilter,
bool $isForGitDiffLines,
?string $gitDiffBase,
- bool $useGitHubLogger,
+ ?bool $useGitHubLogger,
?string $htmlLogFilePath,
bool $useNoopMutators,
bool $executeOnlyCoveringTestCases
diff --git a/tests/e2e_tests b/tests/e2e_tests
index a92a13178..f30ec3c9e 100755
--- a/tests/e2e_tests
+++ b/tests/e2e_tests
@@ -23,9 +23,9 @@ do
if [ -f "run_tests.bash" ]
then
- output="$(bash run_tests.bash)"
+ output="$(INFECTION_E2E_TESTS_ENV=1 bash run_tests.bash)"
else
- output="$(bash ../standard_script.bash ${1:-bin/infection})"
+ output="$(INFECTION_E2E_TESTS_ENV=1 bash ../standard_script.bash ${1:-bin/infection})"
fi
if [ $? != 0 ]
diff --git a/tests/phpunit/Configuration/ConfigurationFactoryTest.php b/tests/phpunit/Configuration/ConfigurationFactoryTest.php
index a5810cf38..44869725d 100644
--- a/tests/phpunit/Configuration/ConfigurationFactoryTest.php
+++ b/tests/phpunit/Configuration/ConfigurationFactoryTest.php
@@ -91,6 +91,7 @@ public static function tearDownAfterClass(): void
*/
public function test_it_can_create_a_configuration(
bool $ciDetected,
+ bool $githubActionsDetected,
SchemaConfiguration $schema,
?string $inputExistingCoveragePath,
?string $inputInitialTestsPhpOptions,
@@ -112,7 +113,7 @@ public function test_it_can_create_a_configuration(
?string $inputGitDiffFilter,
bool $inputIsForGitDiffLines,
string $inputGitDiffBase,
- bool $inputUseGitHubAnnotationsLogger,
+ ?bool $inputUseGitHubAnnotationsLogger,
?string $inputHtmlLogFilePath,
bool $inputUseNoopMutators,
int $inputMsiPrecision,
@@ -144,7 +145,7 @@ public function test_it_can_create_a_configuration(
bool $inputExecuteOnlyCoveringTestCases
): void {
$config = $this
- ->createConfigurationFactory($ciDetected)
+ ->createConfigurationFactory($ciDetected, $githubActionsDetected)
->create(
$schema,
$inputExistingCoveragePath,
@@ -217,6 +218,7 @@ public function valueProvider(): iterable
$expectedLogs->setUseGitHubAnnotationsLogger(true);
yield 'minimal' => [
+ false,
false,
new SchemaConfiguration(
'/path/to/infection.json',
@@ -397,12 +399,42 @@ public function valueProvider(): iterable
true
);
- yield 'ignoreMsiWithNoMutations not specified in schema and not specified in input' => self::createValueForIgnoreMsiWithNoMutations(
- null,
+ yield 'Github Actions annotation disabled, not logged in non-Github Actions environment' => self::createValueForGithubActionsDetected(
+ false,
+ false,
+ false
+ );
+
+ yield 'Github Actions annotation disabled, not logged in Github Actions environment' => self::createValueForGithubActionsDetected(
+ false,
+ true,
+ false
+ );
+
+ yield 'Github Actions annotation not provided, not logged in non-Github Actions environment' => self::createValueForGithubActionsDetected(
null,
+ false,
false
);
+ yield 'Github Actions annotation not provided, logged in Github Actions environment' => self::createValueForGithubActionsDetected(
+ null,
+ true,
+ true
+ );
+
+ yield 'Github Actions annotation enabled, logged in non-Github Actions environment' => self::createValueForGithubActionsDetected(
+ true,
+ false,
+ true
+ );
+
+ yield 'Github Actions annotation enabled, logged in Github Actions environment' => self::createValueForGithubActionsDetected(
+ true,
+ true,
+ true
+ );
+
yield 'ignoreMsiWithNoMutations not specified in schema and true in input' => self::createValueForIgnoreMsiWithNoMutations(
null,
true,
@@ -686,6 +718,7 @@ public function valueProvider(): iterable
);
yield 'with source files' => [
+ false,
false,
new SchemaConfiguration(
'/path/to/infection.json',
@@ -759,6 +792,7 @@ public function valueProvider(): iterable
];
yield 'complete' => [
+ false,
false,
new SchemaConfiguration(
'/path/to/infection.json',
@@ -865,6 +899,7 @@ private static function createValueForTimeout(
int $expectedTimeOut
): array {
return [
+ false,
false,
new SchemaConfiguration(
'/path/to/infection.json',
@@ -940,6 +975,7 @@ private static function createValueForTmpDir(
?string $expectedTmpDir
): array {
return [
+ false,
false,
new SchemaConfiguration(
'/path/to/infection.json',
@@ -1016,6 +1052,7 @@ private static function createValueForCoveragePath(
string $expectedCoveragePath
): array {
return [
+ false,
false,
new SchemaConfiguration(
'/path/to/infection.json',
@@ -1091,6 +1128,7 @@ private static function createValueForPhpUnitConfigDir(
?string $expectedPhpUnitConfigDir
): array {
return [
+ false,
false,
new SchemaConfiguration(
'/path/to/infection.json',
@@ -1168,6 +1206,7 @@ private static function createValueForNoProgress(
): array {
return [
$ciDetected,
+ false,
new SchemaConfiguration(
'/path/to/infection.json',
null,
@@ -1237,12 +1276,101 @@ private static function createValueForNoProgress(
];
}
+ private static function createValueForGithubActionsDetected(
+ ?bool $inputUseGitHubAnnotationsLogger,
+ bool $githubActionsDetected,
+ bool $useGitHubAnnotationsLogger
+ ): array {
+ $expectedLogs = new Logs(
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ $useGitHubAnnotationsLogger,
+ null,
+ );
+
+ return [
+ false,
+ $githubActionsDetected,
+ new SchemaConfiguration(
+ '/path/to/infection.json',
+ null,
+ new Source([], []),
+ Logs::createEmpty(),
+ '',
+ new PhpUnit(null, null),
+ null,
+ null,
+ null,
+ [],
+ null,
+ null,
+ null,
+ null
+ ),
+ null,
+ null,
+ false,
+ 'none',
+ false,
+ false,
+ false,
+ false,
+ null,
+ false,
+ null,
+ '',
+ null,
+ null,
+ '',
+ 0,
+ false,
+ null,
+ false,
+ 'master',
+ $inputUseGitHubAnnotationsLogger,
+ null,
+ false,
+ 2,
+ 10,
+ [],
+ [],
+ '',
+ [],
+ $expectedLogs,
+ 'none',
+ sys_get_temp_dir() . '/infection',
+ new PhpUnit('/path/to', null),
+ self::getDefaultMutators(),
+ 'phpunit',
+ null,
+ null,
+ false,
+ '',
+ sys_get_temp_dir() . '/infection',
+ false,
+ false,
+ false,
+ false,
+ false,
+ null,
+ false,
+ null,
+ [],
+ false,
+ ];
+ }
+
private static function createValueForIgnoreMsiWithNoMutations(
?bool $ignoreMsiWithNoMutationsFromSchemaConfiguration,
?bool $ignoreMsiWithNoMutationsFromInput,
?bool $expectedIgnoreMsiWithNoMutations
): array {
return [
+ false,
false,
new SchemaConfiguration(
'/path/to/infection.json',
@@ -1319,6 +1447,7 @@ private static function createValueForMinMsi(
?float $expectedMinMsi
): array {
return [
+ false,
false,
new SchemaConfiguration(
'/path/to/infection.json',
@@ -1395,6 +1524,7 @@ private static function createValueForMinCoveredMsi(
?float $expectedMinCoveredMsi
): array {
return [
+ false,
false,
new SchemaConfiguration(
'/path/to/infection.json',
@@ -1472,6 +1602,7 @@ private static function createValueForTestFramework(
string $expectedTestFrameworkExtraOptions
): array {
return [
+ false,
false,
new SchemaConfiguration(
'/path/to/infection.json',
@@ -1548,6 +1679,7 @@ private static function createValueForInitialTestsPhpOptions(
?string $expectedInitialTestPhpOptions
): array {
return [
+ false,
false,
new SchemaConfiguration(
'/path/to/infection.json',
@@ -1625,6 +1757,7 @@ private static function createValueForTestFrameworkExtraOptions(
string $expectedTestFrameworkExtraOptions
): array {
return [
+ false,
false,
new SchemaConfiguration(
'/path/to/infection.json',
@@ -1701,6 +1834,7 @@ private static function createValueForTestFrameworkKey(
string $expectedTestFrameworkExtraOptions
): array {
return [
+ false,
false,
new SchemaConfiguration(
'/path/to/infection.json',
@@ -1781,6 +1915,7 @@ private static function createValueForMutators(
array $expectedMutators
): array {
return [
+ false,
false,
new SchemaConfiguration(
'/path/to/infection.json',
@@ -1860,6 +1995,7 @@ private static function createValueForIgnoreSourceCodeByRegex(
array $expectedIgnoreSourceCodeMutatorsMap
): array {
return [
+ false,
false,
new SchemaConfiguration(
'/path/to/infection.json',
@@ -1946,6 +2082,7 @@ private static function createValueForHtmlLogFilePath(?string $htmlFileLogPathIn
);
return [
+ false,
false,
new SchemaConfiguration(
'/path/to/infection.json',
@@ -2045,7 +2182,7 @@ private static function getDefaultMutators(): array
return self::$mutators;
}
- private function createConfigurationFactory(bool $ciDetected): ConfigurationFactory
+ private function createConfigurationFactory(bool $ciDetected, bool $githubActionsDetected): ConfigurationFactory
{
/** @var SourceFileCollector&ObjectProphecy $sourceFilesCollectorProphecy */
$sourceFilesCollectorProphecy = $this->prophesize(SourceFileCollector::class);
@@ -2071,7 +2208,7 @@ private function createConfigurationFactory(bool $ciDetected): ConfigurationFact
SingletonContainer::getContainer()->getMutatorFactory(),
new MutatorParser(),
$sourceFilesCollectorProphecy->reveal(),
- new DummyCiDetector($ciDetected),
+ new DummyCiDetector($ciDetected, $githubActionsDetected),
$gitDiffFilesProviderMock
);
}
diff --git a/tests/phpunit/Configuration/Entry/LogsAssertions.php b/tests/phpunit/Configuration/Entry/LogsAssertions.php
index c4ccd7b70..549cfe05b 100644
--- a/tests/phpunit/Configuration/Entry/LogsAssertions.php
+++ b/tests/phpunit/Configuration/Entry/LogsAssertions.php
@@ -57,7 +57,7 @@ private function assertLogsStateIs(
$this->assertSame($expectedJsonLogFilePath, $logs->getJsonLogFilePath());
$this->assertSame($expectedDebugLogFilePath, $logs->getDebugLogFilePath());
$this->assertSame($expectedPerMutatorFilePath, $logs->getPerMutatorFilePath());
- $this->assertSame($expectedUseGitHubAnnotationsLogger, $logs->getUseGitHubAnnotationsLogger());
+ $this->assertSame($expectedUseGitHubAnnotationsLogger, $logs->getUseGitHubAnnotationsLogger(), 'Use GithubAnnotationLogger is incorrect');
$strykerConfig = $logs->getStrykerConfig();
diff --git a/tests/phpunit/Console/E2ETest.php b/tests/phpunit/Console/E2ETest.php
index 1a5b1e2bf..8ecdd681d 100644
--- a/tests/phpunit/Console/E2ETest.php
+++ b/tests/phpunit/Console/E2ETest.php
@@ -349,6 +349,7 @@ private function runInfection(int $expectedExitCode, array $argvExtra = []): str
'run',
'--verbose',
'--no-interaction',
+ '--logger-github=false',
], $argvExtra));
$output = new BufferedOutput();
diff --git a/tests/phpunit/Fixtures/DummyCiDetector.php b/tests/phpunit/Fixtures/DummyCiDetector.php
index 6f21edcab..603d29219 100644
--- a/tests/phpunit/Fixtures/DummyCiDetector.php
+++ b/tests/phpunit/Fixtures/DummyCiDetector.php
@@ -6,20 +6,23 @@
use Infection\Tests\UnsupportedMethod;
use OndraM\CiDetector\Ci\CiInterface;
-use OndraM\CiDetector\CiDetector;
+use OndraM\CiDetector\Ci\GitHubActions;
use OndraM\CiDetector\CiDetectorInterface;
use OndraM\CiDetector\Env;
+use OndraM\CiDetector\Exception\CiNotDetectedException;
final class DummyCiDetector implements CiDetectorInterface
{
private bool $ciDetected;
+ private bool $githubActionsDetected;
- public function __construct(bool $ciDetected)
+ public function __construct(bool $ciDetected, bool $githubActionsDetected = false)
{
$this->ciDetected = $ciDetected;
+ $this->githubActionsDetected = $githubActionsDetected;
}
- public static function fromEnvironment(Env $environment): CiDetector
+ public static function fromEnvironment(Env $environment): CiDetectorInterface
{
throw UnsupportedMethod::method(__CLASS__, __FUNCTION__);
}
@@ -31,6 +34,10 @@ public function isCiDetected(): bool
public function detect(): CiInterface
{
- throw UnsupportedMethod::method(__CLASS__, __FUNCTION__);
+ if ($this->githubActionsDetected) {
+ return new GitHubActions(new Env());
+ }
+
+ throw new CiNotDetectedException('No CI server detected in current environment');
}
}