From 5a28d30905cd7a4bef708a349361e70cee303ba9 Mon Sep 17 00:00:00 2001 From: Jakov Knezovic Date: Thu, 12 Dec 2024 17:43:37 +0100 Subject: [PATCH 1/2] NGSTACK-938 add new hooks for linter, prettier and ts compiler --- src/Action/CheckForTypescriptErrors.php | 52 +++++++++++++++ src/Action/CheckLinter.php | 54 +++++++++++++++ src/Action/CheckPrettier.php | 87 +++++++++++++++++++++++++ 3 files changed, 193 insertions(+) create mode 100644 src/Action/CheckForTypescriptErrors.php create mode 100644 src/Action/CheckLinter.php create mode 100644 src/Action/CheckPrettier.php diff --git a/src/Action/CheckForTypescriptErrors.php b/src/Action/CheckForTypescriptErrors.php new file mode 100644 index 0000000..e2c6b63 --- /dev/null +++ b/src/Action/CheckForTypescriptErrors.php @@ -0,0 +1,52 @@ +getOptions()->get('config_dirs', ['.']); + $typescriptCompilerCommand = $action->getOptions()->get('typescript_compiler_command', 'npx tsc'); + $typescriptCompilerOptions = $action->getOptions()->get('typescript_compiler_options', '--noEmit'); + + $io->write(sprintf('Running %s on files:', $typescriptCompilerCommand), true, IO::VERBOSE); + foreach ($configDirs as $dir) { + $io->write(sprintf(' - %s', $dir), true, IO::VERBOSE); + + $result = $this->checkTypescriptErrors($dir, $typescriptCompilerCommand, $typescriptCompilerOptions); + $io->write($result['output']); + + if ($result['success'] !== true) { + $this->throwError($action, $io); + } + } + } + + /** + * @return array + */ + protected function checkTypescriptErrors(string $dir, string $typescriptCompilerCommand, string $typescriptCompilerOptions): array + { + $process = new Processor(); + $result = $process->run($typescriptCompilerCommand . ' ' . $typescriptCompilerOptions . ' --project ' . escapeshellarg($dir)); + + return [ + 'success' => $result->isSuccessful(), + 'output' => $result->getStdOut(), + ]; + } +} diff --git a/src/Action/CheckLinter.php b/src/Action/CheckLinter.php new file mode 100644 index 0000000..b3097c4 --- /dev/null +++ b/src/Action/CheckLinter.php @@ -0,0 +1,54 @@ +getOptions()->get('directories', ['assets']); + $linterCommand = $action->getOptions()->get('linter_command', 'pnpm eslint'); + + $io->write(sprintf('Running %s on files:', $linterCommand), true, IO::VERBOSE); + + $result = $this->checkLinter($directories, $linterCommand); + $io->write($result['output']); + + if ($result['success'] !== true) { + $this->throwError($action, $io); + } + } + + /** + * @return array + */ + protected function checkLinter(array $directories, string $linterCommand): array + { + $process = new Processor(); + $cliString = $linterCommand; + + foreach ($directories as $directory) { + $cliString .= ' ' . escapeshellarg($directory); + } + + $result = $process->run($cliString); + + return [ + 'success' => $result->isSuccessful(), + 'output' => $result->getStdOut(), + ]; + } +} diff --git a/src/Action/CheckPrettier.php b/src/Action/CheckPrettier.php new file mode 100644 index 0000000..ed0becf --- /dev/null +++ b/src/Action/CheckPrettier.php @@ -0,0 +1,87 @@ +getOptions()->get('extensions', ['js', 'jsx', 'ts', 'tsx', 'css', 'scss']); + $excludedFiles = $action->getOptions()->get('excluded_files') ?? []; + $directories = $action->getOptions()->get('directories', ['assets']); + $prettierCommand = $action->getOptions()->get('prettier_command', 'pnpm prettier'); + $formatOptions = $action->getOptions()->get('prettier_options', '--check'); + + $finder = new Finder(); + $finder->in($directories)->files()->name(preg_filter('/^/', '*.', $extensions)); + + if ($finder->hasResults()) { + $io->write(sprintf('Running %s on files:', $prettierCommand), true, IO::VERBOSE); + + foreach ($finder as $file) { + if ($this->shouldSkipFileCheck($file, $excludedFiles)) { + continue; + } + + $result = $this->checkPrettier($file->getPath(), $prettierCommand, $formatOptions); + $io->write($result['output']); + + if ($result['success'] !== true) { + $this->throwError($action, $io); + } + } + } + } + + /** + * @param string[] $excludedFiles + */ + protected function shouldSkipFileCheck(string $file, array $excludedFiles): bool + { + foreach ($excludedFiles as $excludedFile) { + // File definition using regexp + if ($excludedFile[0] === '/') { + if (preg_match($excludedFile, $file) === 1) { + return true; + } + + continue; + } + if ($excludedFile === $file) { + return true; + } + } + + return false; + } + + /** + * @return array + */ + protected function checkPrettier(string $file, string $prettierCommand, string $prettierOptions): array + { + $process = new Processor(); + $result = $process->run($prettierCommand . ' ' . $prettierOptions . ' ' . escapeshellarg($file)); + + return [ + 'success' => $result->isSuccessful(), + 'output' => $result->getStdOut(), + ]; + } +} From d15c09555791fdae79f139fd8fac773f5a766afb Mon Sep 17 00:00:00 2001 From: Jakov Knezovic Date: Fri, 13 Dec 2024 15:17:05 +0100 Subject: [PATCH 2/2] NGSTACK-938 fix phpstan issues --- src/Action/CheckLinter.php | 2 ++ src/Action/CheckPrettier.php | 21 +++++++++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/Action/CheckLinter.php b/src/Action/CheckLinter.php index b3097c4..76bc681 100644 --- a/src/Action/CheckLinter.php +++ b/src/Action/CheckLinter.php @@ -33,6 +33,8 @@ protected function doExecute(Config $config, IO $io, Repository $repository, Act } /** + * @param string[] $directories + * * @return array */ protected function checkLinter(array $directories, string $linterCommand): array diff --git a/src/Action/CheckPrettier.php b/src/Action/CheckPrettier.php index ed0becf..5e10567 100644 --- a/src/Action/CheckPrettier.php +++ b/src/Action/CheckPrettier.php @@ -22,6 +22,7 @@ final class CheckPrettier extends Action protected function doExecute(Config $config, IO $io, Repository $repository, ActionConfig $action): void { + /** @var string|string[] $extensions */ $extensions = $action->getOptions()->get('extensions', ['js', 'jsx', 'ts', 'tsx', 'css', 'scss']); $excludedFiles = $action->getOptions()->get('excluded_files') ?? []; $directories = $action->getOptions()->get('directories', ['assets']); @@ -29,18 +30,29 @@ protected function doExecute(Config $config, IO $io, Repository $repository, Act $formatOptions = $action->getOptions()->get('prettier_options', '--check'); $finder = new Finder(); - $finder->in($directories)->files()->name(preg_filter('/^/', '*.', $extensions)); + preg_filter('/^/', '*.', $extensions); + $finder->in($directories)->files()->name($extensions); if ($finder->hasResults()) { - $io->write(sprintf('Running %s on files:', $prettierCommand), true, IO::VERBOSE); + $io->write(sprintf('Running %s on files:', $prettierCommand)); foreach ($finder as $file) { - if ($this->shouldSkipFileCheck($file, $excludedFiles)) { + if ($this->shouldSkipFileCheck($file->getPath(), $excludedFiles)) { continue; } $result = $this->checkPrettier($file->getPath(), $prettierCommand, $formatOptions); - $io->write($result['output']); + + $io->write(sprintf('%s: ', $file->getPath())); + + /** @var bool $isResultSuccess */ + $isResultSuccess = $result['success']; + + if ($isResultSuccess) { + $io->write($result['output']); + } else { + $io->writeError(sprintf('%s', $result['error'])); + } if ($result['success'] !== true) { $this->throwError($action, $io); @@ -82,6 +94,7 @@ protected function checkPrettier(string $file, string $prettierCommand, string $ return [ 'success' => $result->isSuccessful(), 'output' => $result->getStdOut(), + 'error' => $result->getStdErr(), ]; } }