From f8930fd807cc78baa93e999011d4f9fdc11813f2 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 21 Jul 2026 10:18:03 +0200 Subject: [PATCH] chore: Cleanup, fixes and quick tests. --- .github/workflows/php.yml | 39 +++++++++++++++ .gitignore | 2 + Command/GetDefinitionCommand.php | 17 ++++++- .../CleanupOldExecutionDefinition.php | 2 +- Etl/ChainDefinition/ExampleDefinition.php | 2 + .../EtlExecutionEventSubscriber.php | 4 +- Resources/config/parameters.yml | 2 - .../ChainDefinitionBuildTest.php | 50 +++++++++++++++++++ composer.json | 15 ++++-- phpunit.xml.dist | 25 ++++++++++ 10 files changed, 147 insertions(+), 11 deletions(-) create mode 100644 .github/workflows/php.yml create mode 100644 Tests/Etl/ChainDefinition/ChainDefinitionBuildTest.php create mode 100644 phpunit.xml.dist diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml new file mode 100644 index 0000000..a6ca316 --- /dev/null +++ b/.github/workflows/php.yml @@ -0,0 +1,39 @@ +name: PHP Tests + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +permissions: + contents: read + +jobs: + build: + + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + php-versions: ['8.3', '8.4', '8.5'] + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + coverage: none + + - name: Check PHP Version + run: php -v + + - name: Install dependencies + run: composer install --prefer-dist --no-progress + + - name: Run unit tests + run: ./vendor/bin/phpunit -c phpunit.xml.dist diff --git a/.gitignore b/.gitignore index 4fbb073..eae14ff 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ /vendor/ /composer.lock +/.phpunit.cache/ +.phpunit.result.cache diff --git a/Command/GetDefinitionCommand.php b/Command/GetDefinitionCommand.php index 61b1802..fe6d46d 100644 --- a/Command/GetDefinitionCommand.php +++ b/Command/GetDefinitionCommand.php @@ -4,6 +4,7 @@ namespace Oliverde8\PhpEtlBundle\Command; +use Oliverde8\PhpEtlBundle\Etl\ChainDefinitionInterface\ChainDefinitionInterface; use Oliverde8\PhpEtlBundle\Services\ChainProcessorsManager; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; @@ -36,7 +37,19 @@ protected function execute(InputInterface $input, OutputInterface $output): int $chainName = $input->getArgument("name"); $definition = $this->chainProcessorsManager->getRawDefinition($chainName); - echo Yaml::dump($definition, 4); - return 0; + if ($definition instanceof ChainDefinitionInterface) { + $output->writeln(sprintf( + 'V2 (PHP) chain definition: %s (key: %s)', + $definition::class, + $definition->getKey() + )); + + return Command::SUCCESS; + } + + // V1 (YAML) chains are stored as their raw YAML string; re-dump for consistent formatting. + $output->writeln(Yaml::dump(Yaml::parse($definition), 4)); + + return Command::SUCCESS; } } diff --git a/Etl/ChainDefinition/CleanupOldExecutionDefinition.php b/Etl/ChainDefinition/CleanupOldExecutionDefinition.php index 968dad0..0b0e6f6 100644 --- a/Etl/ChainDefinition/CleanupOldExecutionDefinition.php +++ b/Etl/ChainDefinition/CleanupOldExecutionDefinition.php @@ -19,7 +19,7 @@ public function getKey(): string public function build(): ChainConfig { - return new ChainConfig() + return (new ChainConfig()) ->addLink(new FindOldExecutionConfig((new \DateTime())->modify('-1 month'))) ->addLink(new DeleteEntityForOldExecutionConfig()) ->addLink(new DeleteFilesForOldExecutionConfig()); diff --git a/Etl/ChainDefinition/ExampleDefinition.php b/Etl/ChainDefinition/ExampleDefinition.php index e3057d5..f80a6d1 100644 --- a/Etl/ChainDefinition/ExampleDefinition.php +++ b/Etl/ChainDefinition/ExampleDefinition.php @@ -33,5 +33,7 @@ public function build(): ChainConfig singleElement: true )) ->addLink(new CsvFileWriterConfig('output.csv')); + + return $chainConfig; } } diff --git a/EventSubscriber/EtlExecutionEventSubscriber.php b/EventSubscriber/EtlExecutionEventSubscriber.php index 252856e..ff7d311 100644 --- a/EventSubscriber/EtlExecutionEventSubscriber.php +++ b/EventSubscriber/EtlExecutionEventSubscriber.php @@ -47,7 +47,9 @@ public function setChainDetails(BeforeEntityPersistedEvent $event): void } $definition = $this->chainProcessorManager->getRawDefinition($entity->getName()); - $entity->setDefinition($definition); + // Legacy YAML definitions are strings; V2 definitions are objects - store the + // definition class so the entity's (string) "definition" column stays valid. + $entity->setDefinition(\is_string($definition) ? $definition : $definition::class); $entity->setStatus(EtlExecution::STATUS_WAITING); } diff --git a/Resources/config/parameters.yml b/Resources/config/parameters.yml index ed19d06..f537a4d 100644 --- a/Resources/config/parameters.yml +++ b/Resources/config/parameters.yml @@ -1,5 +1,3 @@ parameters: - oliverde8-php-etl: - chains: [] oliverde8.php.etl.base_dir: "%kernel.project_dir%/var/etl" oliverde8.php.etl.min_keep: "1 month" \ No newline at end of file diff --git a/Tests/Etl/ChainDefinition/ChainDefinitionBuildTest.php b/Tests/Etl/ChainDefinition/ChainDefinitionBuildTest.php new file mode 100644 index 0000000..25afb1b --- /dev/null +++ b/Tests/Etl/ChainDefinition/ChainDefinitionBuildTest.php @@ -0,0 +1,50 @@ + + */ + public static function definitionProvider(): iterable + { + yield 'example' => [new ExampleDefinition()]; + yield 'cleanup-old-execution' => [new CleanupOldExecutionDefinition()]; + yield 'flysystem-example' => [new FlysystemExampleDefinition()]; + } + + /** + * @dataProvider definitionProvider + */ + public function testGetKeyIsNonEmptyString(ChainDefinitionInterface $definition): void + { + $this->assertNotEmpty($definition->getKey()); + } + + /** + * @dataProvider definitionProvider + */ + public function testBuildReturnsChainConfig(ChainDefinitionInterface $definition): void + { + $this->assertInstanceOf(ChainConfig::class, $definition->build()); + } +} diff --git a/composer.json b/composer.json index 9e5a555..9a20572 100644 --- a/composer.json +++ b/composer.json @@ -11,10 +11,10 @@ } ], "require": { - "php": ">=8.2", - "oliverde8/php-etl": "^v1.2.0-alpha5|^v2.0.0-alpha5", - "symfony/framework-bundle": "^7.0|^8.0", - "symfony/messenger": "^7.0|^8.0", + "php": ">=8.3", + "oliverde8/php-etl": "^2.0", + "symfony/framework-bundle": "^7.4|^8.0", + "symfony/messenger": "^7.4|^8.0", "ext-json": "*" }, "autoload": { @@ -22,8 +22,13 @@ "Oliverde8\\PhpEtlBundle\\": "." } }, + "suggest": { + "easycorp/easyadmin-bundle": "To manage and run ETL executions from an admin UI (see oliverde8/php-etl-easyadmin-bundle); enables the EtlExecution admin event subscriber", + "league/flysystem": "To find and process files from external/remote filesystems (ExternalFileFinder / FlysystemExternalFileFinderCompiler)" + }, "require-dev": { "symfony/monolog-bundle": "^3.7", - "symfony/console": "^7.0|^8.0" + "symfony/console": "^7.4|^8.0", + "phpunit/phpunit": "^11.0" } } diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..f85727c --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,25 @@ + + + + + + Tests + + + + + + . + + + Tests + vendor + Resources + + +