Skip to content

Commit

Permalink
Merge pull request #14 from netgen/NGSTACK-938-new-hooks
Browse files Browse the repository at this point in the history
HGSTACK-938 new hooks
  • Loading branch information
emodric authored Dec 17, 2024
2 parents c116d7c + d15c095 commit 1c1f32c
Show file tree
Hide file tree
Showing 3 changed files with 208 additions and 0 deletions.
52 changes: 52 additions & 0 deletions src/Action/CheckForTypescriptErrors.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

declare(strict_types=1);

namespace Netgen\GitHooks\Action;

use CaptainHook\App\Config;
use CaptainHook\App\Config\Action as ActionConfig;
use CaptainHook\App\Console\IO;
use SebastianFeldmann\Cli\Processor\ProcOpen as Processor;
use SebastianFeldmann\Git\Repository;

use function escapeshellarg;
use function sprintf;

final class CheckForTypescriptErrors extends Action
{
protected const ERROR_MESSAGE = 'Committed code has typescript errors. Please check the output for suggested diff.';

protected function doExecute(Config $config, IO $io, Repository $repository, ActionConfig $action): void
{
$configDirs = $action->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<string, mixed>
*/
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(),
];
}
}
56 changes: 56 additions & 0 deletions src/Action/CheckLinter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

declare(strict_types=1);

namespace Netgen\GitHooks\Action;

use CaptainHook\App\Config;
use CaptainHook\App\Config\Action as ActionConfig;
use CaptainHook\App\Console\IO;
use SebastianFeldmann\Cli\Processor\ProcOpen as Processor;
use SebastianFeldmann\Git\Repository;

use function escapeshellarg;
use function sprintf;

final class CheckLinter extends Action
{
protected const ERROR_MESSAGE = 'Committed JS code did not pass linter. Please check the output for suggested diff.';

protected function doExecute(Config $config, IO $io, Repository $repository, ActionConfig $action): void
{
$directories = $action->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);
}
}

/**
* @param string[] $directories
*
* @return array<string, mixed>
*/
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(),
];
}
}
100 changes: 100 additions & 0 deletions src/Action/CheckPrettier.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<?php

declare(strict_types=1);

namespace Netgen\GitHooks\Action;

use CaptainHook\App\Config;
use CaptainHook\App\Config\Action as ActionConfig;
use CaptainHook\App\Console\IO;
use SebastianFeldmann\Cli\Processor\ProcOpen as Processor;
use SebastianFeldmann\Git\Repository;
use Symfony\Component\Finder\Finder;

use function escapeshellarg;
use function preg_filter;
use function preg_match;
use function sprintf;

final class CheckPrettier extends Action
{
protected const ERROR_MESSAGE = 'Committed code was not formatted correctly. Please check the output for suggested diff.';

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']);
$prettierCommand = $action->getOptions()->get('prettier_command', 'pnpm prettier');
$formatOptions = $action->getOptions()->get('prettier_options', '--check');

$finder = new Finder();
preg_filter('/^/', '*.', $extensions);
$finder->in($directories)->files()->name($extensions);

if ($finder->hasResults()) {
$io->write(sprintf('Running %s on files:', $prettierCommand));

foreach ($finder as $file) {
if ($this->shouldSkipFileCheck($file->getPath(), $excludedFiles)) {
continue;
}

$result = $this->checkPrettier($file->getPath(), $prettierCommand, $formatOptions);

$io->write(sprintf('<info>%s: </info>', $file->getPath()));

/** @var bool $isResultSuccess */
$isResultSuccess = $result['success'];

if ($isResultSuccess) {
$io->write($result['output']);
} else {
$io->writeError(sprintf('<error>%s</error>', $result['error']));
}

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<string, mixed>
*/
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(),
'error' => $result->getStdErr(),
];
}
}

0 comments on commit 1c1f32c

Please sign in to comment.