Skip to content

Commit

Permalink
Improve CI checks (#34)
Browse files Browse the repository at this point in the history
* Add phpstan lvl 8 to CI + fix code to pass

* Upgrade to phpunit 10.5

* Fixes after review
  • Loading branch information
maelanleborgne committed Feb 20, 2024
1 parent 2881cb5 commit a7bd265
Show file tree
Hide file tree
Showing 17 changed files with 157 additions and 89 deletions.
23 changes: 21 additions & 2 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
php: 8.2
deps: high
- symfony-version: 7.1
php: 8.2
php: 8.3
deps: high
steps:
- uses: actions/checkout@v3
Expand All @@ -53,7 +53,7 @@ jobs:

- name: Run tests
run: |
./vendor/bin/simple-phpunit
./vendor/bin/phpunit
php-cs-fixer:
name: PHP CS Fixer
Expand All @@ -71,3 +71,22 @@ jobs:
- name: Run PHP-CS-Fixer
run:
php-cs-fixer fix --dry-run --diff

phpstan:
name: PHPStan
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.2
tools: phpstan

- name: Install Composer dependencies
run: composer install --no-progress --prefer-dist --optimize-autoloader

- name: Run PHPStan
run: vendor/bin/phpstan analyse
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/vendor/
composer.lock
.php-cs-fixer.cache
.phpunit.result.cache
.phpunit.cache/
/tests/fixtures/var
5 changes: 3 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@
"require-dev": {
"symfony/filesystem": "^6.3|^7.0",
"symfony/framework-bundle": "^6.3|^7.0",
"symfony/phpunit-bridge": "^6.3|^7.0",
"phpstan/phpstan": "1.11.x-dev"
"phpstan/phpstan": "^1",
"phpstan/phpstan-symfony": "^1.3",
"phpunit/phpunit": "^10.5"
},
"autoload": {
"psr-4": {
Expand Down
7 changes: 7 additions & 0 deletions phpstan.dist.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
parameters:
level: 8
paths:
- src/
- tests/
includes:
- vendor/phpstan/phpstan-symfony/extension.neon
48 changes: 19 additions & 29 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -1,36 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>

<!-- https://phpunit.readthedocs.io/en/latest/configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd"
backupGlobals="false"
colors="true"
bootstrap="vendor/autoload.php"
convertDeprecationsToExceptions="false"
>
<php>
<ini name="display_errors" value="1" />
<ini name="error_reporting" value="-1" />
<server name="KERNEL_CLASS" value="Sensiolabs\TypeScriptBundle\Tests\fixtures\TypeScriptTestKernel"/>
<server name="APP_ENV" value="test" force="true" />
<server name="SHELL_VERBOSITY" value="-1" />
<server name="SYMFONY_PHPUNIT_REMOVE" value="" />
<server name="SYMFONY_PHPUNIT_VERSION" value="9.5" />
</php>

<testsuites>
<testsuite name="Bundle Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>

<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">src</directory>
</include>
</coverage>

<listeners>
<listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener" />
</listeners>
cacheDirectory=".phpunit.cache">
<php>
<ini name="display_errors" value="1"/>
<ini name="error_reporting" value="-1"/>
<server name="KERNEL_CLASS" value="Sensiolabs\TypeScriptBundle\Tests\fixtures\TypeScriptTestKernel"/>
<server name="APP_ENV" value="test" force="true"/>
<server name="SHELL_VERBOSITY" value="-1"/>
</php>
<testsuites>
<testsuite name="Bundle Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
<source>
<include>
<directory suffix=".php">src</directory>
</include>
</source>
</phpunit>
36 changes: 29 additions & 7 deletions src/AssetMapper/TypeScriptCompiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ class TypeScriptCompiler implements AssetCompilerInterface
{
private Filesystem $fileSystem;

/**
* @param list<string> $typeScriptFilesPaths
*/
public function __construct(
private readonly array $typeScriptFilesPaths,
private readonly string $jsPathDirectory,
Expand All @@ -21,34 +24,53 @@ public function __construct(

public function supports(MappedAsset $asset): bool
{
if (!str_ends_with($asset->sourcePath, '.ts')) {
$realSourcePath = realpath($asset->sourcePath);
if (false === $realSourcePath) {
return false;
}
if (!str_ends_with($realSourcePath, '.ts')) {
return false;
}
foreach ($this->typeScriptFilesPaths as $path) {
$realTypeScriptPath = realpath($path);
if (false === $realTypeScriptPath) {
throw new \Exception(sprintf('The TypeScript directory "%s" does not exist', $path));
}
// If the asset matches one of the TypeScript files source paths
if (realpath($asset->sourcePath) === realpath($path)) {
if ($realSourcePath === $realTypeScriptPath) {
return true;
}
// If the asset is in a directory (or subdirectory) of one of the TypeScript directory source paths
if (is_dir($path) && !str_starts_with($this->fileSystem->makePathRelative(realpath($asset->sourcePath), realpath($path)), '../')) {
if (is_dir($realTypeScriptPath) && !str_starts_with($this->fileSystem->makePathRelative($realSourcePath, $realTypeScriptPath), '../')) {
return true;
}
}

throw new \Exception(sprintf('The TypeScript file "%s" is not in the TypeScript files paths. Check the asset path or your "sensiolabs_typescript.source_dir" in your config', $asset->sourcePath));
throw new \Exception(sprintf('The TypeScript file "%s" is not in the TypeScript files paths. Check the asset path or your "sensiolabs_typescript.source_dir" in your config', $realSourcePath));
}

public function compile(string $content, MappedAsset $asset, AssetMapperInterface $assetMapper): string
{
$realSourcePath = realpath($asset->sourcePath);
if (false === $realSourcePath) {
throw new \Exception(sprintf('The TypeScript file "%s" does not exist', $asset->sourcePath));
}
foreach ($this->typeScriptFilesPaths as $typeScriptFilesPath) {
if (str_starts_with(realpath($asset->sourcePath), realpath($typeScriptFilesPath))) {
$fileName = basename($asset->sourcePath, '.ts');
$subPath = trim($this->fileSystem->makePathRelative(\dirname($asset->sourcePath), $this->projectRootDir), '/');
$realTypeScriptPath = realpath($typeScriptFilesPath);
if (false === $realTypeScriptPath) {
throw new \Exception(sprintf('The TypeScript directory "%s" does not exist', $typeScriptFilesPath));
}
if (str_starts_with($realSourcePath, $realTypeScriptPath)) {
$fileName = basename($realSourcePath, '.ts');
$subPath = trim($this->fileSystem->makePathRelative(\dirname($realSourcePath), $this->projectRootDir), '/');
$jsFile = $this->jsPathDirectory.'/'.$subPath.'/'.$fileName.'.js';
break;
}
}

if (!isset($jsFile)) {
throw new \Exception(sprintf('The TypeScript file "%s" is not in the TypeScript files paths. Check the asset path or your "sensiolabs_typescript.source_dir" in your config', $asset->sourcePath));
}
$asset->addFileDependency($jsFile);

if (($content = file_get_contents($jsFile)) === false) {
Expand Down
3 changes: 3 additions & 0 deletions src/AssetMapper/TypeScriptPublicPathAssetPathResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ public function resolvePublicPath(string $logicalPath): string

public function getPublicFilesystemPath(): string
{
if (!method_exists($this->decorator, 'getPublicFilesystemPath')) {
throw new \LogicException('The decorated resolver does not implement the "getPublicFilesystemPath" method.');
}
$path = $this->decorator->getPublicFilesystemPath();

if (str_ends_with($path, '.ts')) {
Expand Down
5 changes: 4 additions & 1 deletion src/DependencyInjection/SensiolabsTypeScriptExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ public function load(array $configs, ContainerBuilder $container): void
;
}

public function getConfiguration(array $config, ContainerBuilder $container): ?ConfigurationInterface
/**
* @param array<array<mixed>> $configs
*/
public function getConfiguration(array $configs, ContainerBuilder $container): ConfigurationInterface
{
return $this;
}
Expand Down
4 changes: 2 additions & 2 deletions src/SensiolabsTypeScriptBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

class SensiolabsTypeScriptBundle extends Bundle
{
public function getContainerExtension(): ?ExtensionInterface
public function getContainerExtension(): ExtensionInterface
{
return $this->extension ?? $this->extension = new SensiolabsTypeScriptExtension();
return $this->extension ?: new SensiolabsTypeScriptExtension();
}
}
37 changes: 20 additions & 17 deletions src/Tools/TypeScriptBinaryFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace Sensiolabs\TypeScriptBundle\Tools;

use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\HttpClient\HttpClient;
use Symfony\Contracts\HttpClient\HttpClientInterface;
Expand All @@ -11,21 +10,22 @@ class TypeScriptBinaryFactory
{
private const VERSION = 'v1.3.92';
private const SWC_RELEASE_URL_PATTERN = 'https://github.com/swc-project/swc/releases/download/%s/%s';
private HttpClientInterface $httpClient;
private SymfonyStyle $output;

public function __construct(
private readonly string $binaryDownloadDir,
private ?HttpClientInterface $httpClient = null,
private ?OutputInterface $output = null,
?HttpClientInterface $httpClient = null,
) {
$this->httpClient = $httpClient ?? HttpClient::create();
}

public function getBinaryFromPath($pathToExecutable): TypeScriptBinary
public function getBinaryFromPath(string $pathToExecutable): TypeScriptBinary
{
return new TypeScriptBinary($pathToExecutable);
}

public function getBinaryFromServerSpecs($os, $machine, $kernel): TypeScriptBinary
public function getBinaryFromServerSpecs(string $os, string $machine, string $kernel): TypeScriptBinary
{
$binaryName = self::getBinaryNameFromServerSpecs($os, $machine, $kernel);
if (!file_exists($this->binaryDownloadDir.'/'.$binaryName)) {
Expand All @@ -35,7 +35,7 @@ public function getBinaryFromServerSpecs($os, $machine, $kernel): TypeScriptBina
return $this->getBinaryFromPath($this->binaryDownloadDir.'/'.$binaryName);
}

public function setOutput(?SymfonyStyle $output): self
public function setOutput(SymfonyStyle $output): self
{
$this->output = $output;

Expand All @@ -50,10 +50,10 @@ public function setHttpClient(HttpClientInterface $client): self
}

public static function getBinaryNameFromServerSpecs(
$os,
$machine,
$kernel,
) {
string $os,
string $machine,
string $kernel,
): string {
list($os, $machine, $kernel) = [strtolower($os), strtolower($machine), strtolower($kernel)];
if (str_contains($os, 'darwin')) {
if ('arm64' === $machine) {
Expand Down Expand Up @@ -96,7 +96,7 @@ public static function getBinaryNameFromServerSpecs(
throw new \Exception(sprintf('Unknown platform or architecture (OS: %s, Machine: %s).', $os, $machine));
}

private function downloadAndExtract($binaryName): void
private function downloadAndExtract(string $binaryName): void
{
if (!is_dir($this->binaryDownloadDir)) {
mkdir($this->binaryDownloadDir, 0777, true);
Expand All @@ -107,10 +107,10 @@ private function downloadAndExtract($binaryName): void
}
$url = sprintf(self::SWC_RELEASE_URL_PATTERN, self::VERSION, $binaryName);

if ($this->output?->isVerbose()) {
$this->output?->note(sprintf('Downloading SWC binary from "%s" to "%s"...', $url, $targetPath));
if ($this->output->isVerbose()) {
$this->output->note(sprintf('Downloading SWC binary from "%s" to "%s"...', $url, $targetPath));
} else {
$this->output?->note('Downloading SWC binary ...');
$this->output->note('Downloading SWC binary ...');
}

$response = $this->httpClient->request('GET', $url, [
Expand All @@ -120,20 +120,23 @@ private function downloadAndExtract($binaryName): void
}

if (!$progressBar) {
$progressBar = $this->output?->createProgressBar($dlSize);
$progressBar = $this->output->createProgressBar($dlSize);
}

$progressBar?->setProgress($dlNow);
$progressBar->setProgress($dlNow);
},
]);
$fileHandler = fopen($targetPath, 'w');
if (false === $fileHandler) {
throw new \Exception(sprintf('Could not open file "%s" for writing.', $targetPath));
}
foreach ($this->httpClient->stream($response) as $chunk) {
fwrite($fileHandler, $chunk->getContent());
}

fclose($fileHandler);
$progressBar?->finish();
$this->output?->writeln('');
$this->output->writeln('');

chmod($this->binaryDownloadDir.'/'.$binaryName, 7770);
}
Expand Down
4 changes: 2 additions & 2 deletions src/Tools/WatcherBinaryFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

class WatcherBinaryFactory
{
public function getBinaryFromServerSpecs($os): WatcherBinary
public function getBinaryFromServerSpecs(string $os): WatcherBinary
{
$binaryName = self::getBinaryNameFromServerSpecs($os);
$binaryPath = __DIR__.'/watcher/'.$binaryName;
Expand All @@ -15,7 +15,7 @@ public function getBinaryFromServerSpecs($os): WatcherBinary
return new WatcherBinary($binaryPath);
}

public static function getBinaryNameFromServerSpecs($os)
public static function getBinaryNameFromServerSpecs(string $os): string
{
$os = strtolower($os);
if (str_contains($os, 'darwin')) {
Expand Down
9 changes: 6 additions & 3 deletions src/TypeScriptBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,13 @@

class TypeScriptBuilder
{
private ?SymfonyStyle $output = null;
private SymfonyStyle $output;
private ?TypeScriptBinary $buildBinary = null;
private ?WatcherBinary $watcherBinary = null;

/**
* @param list<string> $typeScriptFilesPaths
*/
public function __construct(
private readonly array $typeScriptFilesPaths,
private readonly string $compiledFilesPaths,
Expand Down Expand Up @@ -47,8 +50,8 @@ private function createBuildProcess(string $path, bool $watch = false): Process
$buildProcess = $this->getBuildBinary()->createProcess(array_merge(['compile', $relativePath], $args));
$buildProcess->setWorkingDirectory($this->projectRootDir);

$this->output?->note(sprintf('Executing SWC compile on %s.', $relativePath));
if ($this->output?->isVerbose()) {
$this->output->note(sprintf('Executing SWC compile on %s.', $relativePath));
if ($this->output->isVerbose()) {
$this->output->writeln([
' Command:',
' '.$buildProcess->getCommandLine(),
Expand Down
Loading

0 comments on commit a7bd265

Please sign in to comment.