From 5a28d30905cd7a4bef708a349361e70cee303ba9 Mon Sep 17 00:00:00 2001 From: Jakov Knezovic Date: Thu, 12 Dec 2024 17:43:37 +0100 Subject: [PATCH] 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(), + ]; + } +}