Skip to content

Commit

Permalink
SDK-5285: Add codesniffer executor (#172)
Browse files Browse the repository at this point in the history
  • Loading branch information
sergeyspryker committed Jan 2, 2024
1 parent 583f966 commit 17dbf52
Show file tree
Hide file tree
Showing 7 changed files with 260 additions and 143 deletions.
22 changes: 8 additions & 14 deletions src/Builder/FileNormalizer/CodeSniffStyleFileNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@

namespace SprykerSdk\Integrator\Builder\FileNormalizer;

use RuntimeException;
use SprykerSdk\Integrator\IntegratorConfig;
use SprykerSdk\Utils\Infrastructure\Service\ProcessRunnerServiceInterface;

class CodeSniffStyleFileNormalizer implements FileNormalizerInterface
{
Expand All @@ -31,18 +29,18 @@ class CodeSniffStyleFileNormalizer implements FileNormalizerInterface
protected $config;

/**
* @var \SprykerSdk\Utils\Infrastructure\Service\ProcessRunnerServiceInterface
* @var \SprykerSdk\Integrator\Builder\FileNormalizer\CodeSnifferCommandExecutor
*/
protected ProcessRunnerServiceInterface $processRunner;
protected CodeSnifferCommandExecutor $codeSnifferCommandExecutor;

/**
* @param \SprykerSdk\Integrator\IntegratorConfig $config
* @param \SprykerSdk\Utils\Infrastructure\Service\ProcessRunnerServiceInterface $processRunner
* @param \SprykerSdk\Integrator\Builder\FileNormalizer\CodeSnifferCommandExecutor $codeSnifferCommandExecutor
*/
public function __construct(IntegratorConfig $config, ProcessRunnerServiceInterface $processRunner)
public function __construct(IntegratorConfig $config, CodeSnifferCommandExecutor $codeSnifferCommandExecutor)
{
$this->config = $config;
$this->processRunner = $processRunner;
$this->codeSnifferCommandExecutor = $codeSnifferCommandExecutor;
}

/**
Expand All @@ -64,19 +62,15 @@ public function getErrorMessage(): ?string
/**
* @param array $filePaths
*
* @throws \RuntimeException
*
* @return void
*/
public function normalize(array $filePaths): void
{
$projectConsolePath = $this->getProjectConsolePath();
foreach ($this->getProjectRelativeFilePaths($filePaths) as $filePath) {
$process = $this->processRunner->run([$projectConsolePath, static::PHP_CS_FIX_COMMAND, $filePath]);

if ($process->getExitCode() > 0 && $process->getErrorOutput() !== '') {
throw new RuntimeException($process->getErrorOutput());
}
$this->codeSnifferCommandExecutor->executeCodeSnifferCommand(
[$projectConsolePath, static::PHP_CS_FIX_COMMAND, $filePath],
);
}
}

Expand Down
80 changes: 80 additions & 0 deletions src/Builder/FileNormalizer/CodeSnifferCommandExecutor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php

/**
* Copyright © 2016-present Spryker Systems GmbH. All rights reserved.
* Use of this software requires acceptance of the Evaluation License Agreement. See LICENSE file.
*/

declare(strict_types=1);

namespace SprykerSdk\Integrator\Builder\FileNormalizer;

use RuntimeException;
use SprykerSdk\Utils\Infrastructure\Service\ProcessRunnerServiceInterface;
use Symfony\Component\Process\Process;

class CodeSnifferCommandExecutor
{
/**
* @var int
*/
public const EXECUTION_ATTEMPTS = 3;

/**
* @var int
*/
protected const SUCCESS_COMMAND_CODE = 0;

/**
* @var \SprykerSdk\Utils\Infrastructure\Service\ProcessRunnerServiceInterface
*/
protected ProcessRunnerServiceInterface $processRunner;

/**
* @param \SprykerSdk\Utils\Infrastructure\Service\ProcessRunnerServiceInterface $processRunner
*/
public function __construct(ProcessRunnerServiceInterface $processRunner)
{
$this->processRunner = $processRunner;
}

/**
* @param array<string> $command
*
* @return void
*/
public function executeCodeSnifferCommand(array $command): void
{
$leftAttempts = static::EXECUTION_ATTEMPTS;

while ($leftAttempts > 0) {
$process = $this->processRunner->run($command);

--$leftAttempts;

if ($process->getExitCode() === static::SUCCESS_COMMAND_CODE) {
break;
}

if ($leftAttempts === 0 && $process->getExitCode() !== static::SUCCESS_COMMAND_CODE) {
$this->throwFailedExecutionException($process);
}
}
}

/**
* @param \Symfony\Component\Process\Process $process
*
* @throws \RuntimeException
*
* @return void
*/
protected function throwFailedExecutionException(Process $process): void
{
$errorOutput = $process->getErrorOutput();

if ($errorOutput !== '') {
throw new RuntimeException($errorOutput);
}
}
}
31 changes: 8 additions & 23 deletions src/Builder/FileNormalizer/PhpCSFixerFileNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@

namespace SprykerSdk\Integrator\Builder\FileNormalizer;

use RuntimeException;
use SprykerSdk\Integrator\IntegratorConfig;
use SprykerSdk\Utils\Infrastructure\Service\ProcessRunnerServiceInterface;

class PhpCSFixerFileNormalizer implements FileNormalizerInterface
{
Expand All @@ -26,18 +24,18 @@ class PhpCSFixerFileNormalizer implements FileNormalizerInterface
protected $config;

/**
* @var \SprykerSdk\Utils\Infrastructure\Service\ProcessRunnerServiceInterface
* @var \SprykerSdk\Integrator\Builder\FileNormalizer\CodeSnifferCommandExecutor
*/
protected ProcessRunnerServiceInterface $processRunner;
protected CodeSnifferCommandExecutor $codeSnifferCommandExecutor;

/**
* @param \SprykerSdk\Integrator\IntegratorConfig $config
* @param \SprykerSdk\Utils\Infrastructure\Service\ProcessRunnerServiceInterface $processRunner
* @param \SprykerSdk\Integrator\Builder\FileNormalizer\CodeSnifferCommandExecutor $codeSnifferCommandExecutor
*/
public function __construct(IntegratorConfig $config, ProcessRunnerServiceInterface $processRunner)
public function __construct(IntegratorConfig $config, CodeSnifferCommandExecutor $codeSnifferCommandExecutor)
{
$this->config = $config;
$this->processRunner = $processRunner;
$this->codeSnifferCommandExecutor = $codeSnifferCommandExecutor;
}

/**
Expand All @@ -59,26 +57,13 @@ public function getErrorMessage(): ?string
/**
* @param array $filePaths
*
* @throws \RuntimeException
*
* @return void
*/
public function normalize(array $filePaths): void
{
$command = [$this->getCSFixPath(), ...$this->getAbsoluteFilePaths($filePaths)];
$process = $this->processRunner->run($command);

// TODO remove when phpcbf will be able to fix all issues in file during the one iteration
if (defined('TEST_INTEGRATOR_MODE') && TEST_INTEGRATOR_MODE === 'true' && $process->getExitCode() !== 0) {
$process = $this->processRunner->run($command);
if ($process->getExitCode() !== 0) {
$process = $this->processRunner->run($command);
}
}

if ($process->getExitCode() > 0 && $process->getErrorOutput() !== '') {
throw new RuntimeException($process->getErrorOutput());
}
$this->codeSnifferCommandExecutor->executeCodeSnifferCommand(
[$this->getCSFixPath(), ...$this->getAbsoluteFilePaths($filePaths)],
);
}

/**
Expand Down
13 changes: 11 additions & 2 deletions src/IntegratorFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
use SprykerSdk\Integrator\Builder\Extractor\ExpressionExtractorInterface;
use SprykerSdk\Integrator\Builder\Extractor\ValueExtractor\ValueExtractorStrategyCollection;
use SprykerSdk\Integrator\Builder\FileBuilderFacade;
use SprykerSdk\Integrator\Builder\FileNormalizer\CodeSnifferCommandExecutor;
use SprykerSdk\Integrator\Builder\FileNormalizer\CodeSnifferCompositeNormalizer;
use SprykerSdk\Integrator\Builder\FileNormalizer\CodeSniffStyleFileNormalizer;
use SprykerSdk\Integrator\Builder\FileNormalizer\FileNormalizerInterface;
Expand Down Expand Up @@ -597,15 +598,15 @@ public function createCodeSnifferCompositeNormalizer(): FileNormalizerInterface
*/
public function createCodeSniffStyleFileNormalizer(): FileNormalizerInterface
{
return new CodeSniffStyleFileNormalizer($this->getConfig(), $this->createProcessRunnerService());
return new CodeSniffStyleFileNormalizer($this->getConfig(), $this->createCodeSnifferCommandExecutor());
}

/**
* @return \SprykerSdk\Integrator\Builder\FileNormalizer\FileNormalizerInterface
*/
public function createPhpCSFixerNormalizer(): FileNormalizerInterface
{
return new PhpCSFixerFileNormalizer($this->getConfig(), $this->createProcessRunnerService());
return new PhpCSFixerFileNormalizer($this->getConfig(), $this->createCodeSnifferCommandExecutor());
}

/**
Expand All @@ -616,6 +617,14 @@ public function createProcessRunnerService(): ProcessRunnerServiceInterface
return new ProcessRunnerService();
}

/**
* @return \SprykerSdk\Integrator\Builder\FileNormalizer\CodeSnifferCommandExecutor
*/
public function createCodeSnifferCommandExecutor(): CodeSnifferCommandExecutor
{
return new CodeSnifferCommandExecutor($this->createProcessRunnerService());
}

/**
* @return \SprykerSdk\Integrator\Builder\Printer\ClassDiffPrinterInterface
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,10 @@
namespace SprykerSdkTest\Integrator\Builder\FileNormalizer;

use PHPUnit\Framework\TestCase;
use RuntimeException;
use SprykerSdk\Integrator\Builder\FileNormalizer\CodeSnifferCommandExecutor;
use SprykerSdk\Integrator\Builder\FileNormalizer\CodeSniffStyleFileNormalizer;
use SprykerSdk\Integrator\Builder\FileStorage\FileStorage;
use SprykerSdk\Integrator\IntegratorConfig;
use SprykerSdk\Utils\Infrastructure\Service\ProcessRunnerService;
use SprykerSdk\Utils\Infrastructure\Service\ProcessRunnerServiceInterface;
use Symfony\Component\Process\Process;

class CodeSniffStyleFileNormalizerTest extends TestCase
{
Expand All @@ -26,16 +23,9 @@ class CodeSniffStyleFileNormalizerTest extends TestCase
public function testExecuteSuccess(): void
{
// Arrange
$processExecutorMock = $this->createProcessExecutorMock(0, '');
$processExecutorMock->expects($this->once())->method('run')->with(
$this->callback(function ($command) {
return $command[1] === 'code:sniff:style -f';
}),
);

// Arrange
$codesnifferCommandExecutor = $this->createCodeSnifferCommandExecutorMock();
$configMock = $this->createMock(IntegratorConfig::class);
$normalizer = new CodeSniffStyleFileNormalizer($configMock, $processExecutorMock);
$normalizer = new CodeSniffStyleFileNormalizer($configMock, $codesnifferCommandExecutor);

$fileStorage = new FileStorage();
$fileStorage->addFile('someClass.php');
Expand All @@ -47,15 +37,13 @@ public function testExecuteSuccess(): void
/**
* @return void
*/
public function testExecuteFailed(): void
public function testExecuteSuccessWhenProjectDirIsSet(): void
{
// Assert
$this->expectException(RuntimeException::class);

// Arrange
$processExecutorMock = $this->createProcessExecutorMock(2, 'process error');
$codesnifferCommandExecutor = $this->createCodeSnifferCommandExecutorMock();
$configMock = $this->createMock(IntegratorConfig::class);
$normalizer = new CodeSniffStyleFileNormalizer($configMock, $processExecutorMock);
$configMock->method('getProjectRootDirectory')->willReturn('projectRoot');
$normalizer = new CodeSniffStyleFileNormalizer($configMock, $codesnifferCommandExecutor);

$fileStorage = new FileStorage();
$fileStorage->addFile('someClass.php');
Expand All @@ -67,47 +55,52 @@ public function testExecuteFailed(): void
/**
* @return void
*/
public function testGetErrorMessageShouldReturnErrorMessage(): void
public function testExecuteSuccessWhenProjectDirIsSetAndHasSubPath(): void
{
// Arrange
$processExecutorMock = $this->createProcessExecutorMock(2, 'process error');
$codesnifferCommandExecutor = $this->createCodeSnifferCommandExecutorMock();
$configMock = $this->createMock(IntegratorConfig::class);
$normalizer = new CodeSniffStyleFileNormalizer($configMock, $processExecutorMock);
$configMock->method('getProjectRootDirectory')->willReturn('projectDir');
$normalizer = new CodeSniffStyleFileNormalizer($configMock, $codesnifferCommandExecutor);

// Act
$errorMessage = $normalizer->getErrorMessage();
$fileStorage = new FileStorage();
$fileStorage->addFile('projectDir/someClass.php');

// Assert
$this->assertNull($errorMessage);
// Act
$normalizer->normalize($fileStorage->flush());
}

/**
* @param int $exitCode
* @param string $errorOutput
*
* @return \SprykerSdk\Utils\Infrastructure\Service\ProcessRunnerServiceInterface
* @return void
*/
protected function createProcessExecutorMock(int $exitCode, string $errorOutput = ''): ProcessRunnerServiceInterface
public function testGetErrorMessageShouldReturnErrorMessage(): void
{
$processMock = $this->createProcessMock($exitCode, $errorOutput);
$processExecutorMock = $this->createMock(ProcessRunnerService::class);
$processExecutorMock->method('run')->willReturn($processMock);
// Arrange
$codesnifferCommandExecutor = $this->createMock(CodeSnifferCommandExecutor::class);
$configMock = $this->createMock(IntegratorConfig::class);
$normalizer = new CodeSniffStyleFileNormalizer($configMock, $codesnifferCommandExecutor);

return $processExecutorMock;
// Act
$errorMessage = $normalizer->getErrorMessage();

// Assert
$this->assertNull($errorMessage);
}

/**
* @param int $exitCode
* @param string $errorOutput
*
* @return \Symfony\Component\Process\Process
* @return \SprykerSdk\Integrator\Builder\FileNormalizer\CodeSnifferCommandExecutor
*/
protected function createProcessMock(int $exitCode, string $errorOutput = ''): Process
protected function createCodeSnifferCommandExecutorMock(): CodeSnifferCommandExecutor
{
$processMock = $this->createMock(Process::class);
$processMock->method('getExitCode')->willReturn($exitCode);
$processMock->method('getErrorOutput')->willReturn($errorOutput);

return $processMock;
$codeSnifferCommandExecutor = $this->createMock(CodeSnifferCommandExecutor::class);
$codeSnifferCommandExecutor->expects($this->once())
->method('executeCodeSnifferCommand')
->with(
$this->callback(function ($command) {
return $command[1] === 'code:sniff:style -f';
}),
);

return $codeSnifferCommandExecutor;
}
}
Loading

0 comments on commit 17dbf52

Please sign in to comment.