From 291c4298ccae1d9f7284b97701d05e24b0a32bbd Mon Sep 17 00:00:00 2001 From: Johannes Wachter Date: Tue, 19 May 2026 12:47:03 +0200 Subject: [PATCH 1/4] Update CI runner to ubuntu-22.04 The ubuntu-20.04 runner image is no longer available, causing jobs to hang waiting for a runner. See: https://github.blog/changelog/2025-01-15-github-actions-ubuntu-20-runner-image-brownout-dates-and-other-breaking-changes/ --- .github/workflows/test-application.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-application.yaml b/.github/workflows/test-application.yaml index aac0865..e01e484 100644 --- a/.github/workflows/test-application.yaml +++ b/.github/workflows/test-application.yaml @@ -12,7 +12,7 @@ on: jobs: test: name: '${{ matrix.php-version }} ${{ matrix.dependencies }}, Storage ${{ matrix.storage }}, Coverage ${{ matrix.coverage }}' - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 env: COVERAGE: ${{ matrix.coverage }} STORAGE: ${{ matrix.storage }} From c6372f25e3fbe57b42a309166636f9c174249761 Mon Sep 17 00:00:00 2001 From: Johannes Wachter Date: Tue, 19 May 2026 13:18:24 +0200 Subject: [PATCH 2/4] Fix CI pipeline and pre-existing test failures - Update CI runner from ubuntu-20.04 to ubuntu-22.04 - Replace 'doctrine:database:create' (unsupported on DBAL 3 SQLite platform) with a touch on the sqlite file before schema:create - Pin symfony/var-exporter to ^6.4 || ^7.0 so doctrine/orm 3.6 can find ProxyHelper::generateLazyGhost, which was removed in Symfony 8 - Widen TaskExecutionRepository::create to accept DateTimeInterface and normalize to DateTimeImmutable, so DateTime returned by CronExpression::getNextRunDate() in upstream TaskScheduler is accepted - Add ArrayTaskExecutionRepository subclass that performs the same normalization for array storage and initializes the result field so getResult() returns null instead of false (unserialize(null) === false) - Update tests to call findAllPaginated() instead of removed findAll() --- .github/workflows/test-application.yaml | 3 +- composer.json | 3 +- src/Entity/TaskExecution.php | 8 ++++ src/Entity/TaskExecutionRepository.php | 6 ++- src/Resources/config/storage/array.xml | 2 +- .../ArrayTaskExecutionRepository.php | 37 +++++++++++++++++++ .../Command/ScheduleTaskCommandTest.php | 14 +++---- .../Entity/TaskExecutionRepositoryTest.php | 2 +- 8 files changed, 63 insertions(+), 12 deletions(-) create mode 100644 src/Storage/ArrayStorage/ArrayTaskExecutionRepository.php diff --git a/.github/workflows/test-application.yaml b/.github/workflows/test-application.yaml index e01e484..8c87214 100644 --- a/.github/workflows/test-application.yaml +++ b/.github/workflows/test-application.yaml @@ -77,7 +77,8 @@ jobs: - name: Doctrine if: matrix.storage == 'doctrine' run: | - tests/app/console doctrine:database:create + mkdir -p tests/app/data + touch tests/app/data/database.sqlite tests/app/console doctrine:schema:create - name: Execute test diff --git a/composer.json b/composer.json index 3be6c20..81f6198 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,8 @@ "doctrine/data-fixtures": "^1.3.3", "phpunit/phpunit": "^9.6.5 || ^10", "phpspec/prophecy": "^1.14", - "phpspec/prophecy-phpunit": "^2.0" + "phpspec/prophecy-phpunit": "^2.0", + "symfony/var-exporter": "^6.4 || ^7.0" }, "autoload": { "psr-4": { diff --git a/src/Entity/TaskExecution.php b/src/Entity/TaskExecution.php index bc6e592..36914cd 100644 --- a/src/Entity/TaskExecution.php +++ b/src/Entity/TaskExecution.php @@ -18,4 +18,12 @@ */ class TaskExecution extends BaseTaskExecution { + public function getResult() + { + if (null === $this->result) { + return null; + } + + return parent::getResult(); + } } diff --git a/src/Entity/TaskExecutionRepository.php b/src/Entity/TaskExecutionRepository.php index 7236008..6ad1172 100644 --- a/src/Entity/TaskExecutionRepository.php +++ b/src/Entity/TaskExecutionRepository.php @@ -26,8 +26,12 @@ class TaskExecutionRepository extends EntityRepository implements TaskExecutionR /** * {@inheritdoc} */ - public function create(TaskInterface $task, \DateTimeImmutable $scheduleTime) + public function create(TaskInterface $task, \DateTimeInterface $scheduleTime) { + if (!$scheduleTime instanceof \DateTimeImmutable) { + $scheduleTime = \DateTimeImmutable::createFromInterface($scheduleTime); + } + return new TaskExecution($task, $task->getHandlerClass(), $scheduleTime, $task->getWorkload()); } diff --git a/src/Resources/config/storage/array.xml b/src/Resources/config/storage/array.xml index 2bd31a7..7e718d3 100644 --- a/src/Resources/config/storage/array.xml +++ b/src/Resources/config/storage/array.xml @@ -4,6 +4,6 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - + diff --git a/src/Storage/ArrayStorage/ArrayTaskExecutionRepository.php b/src/Storage/ArrayStorage/ArrayTaskExecutionRepository.php new file mode 100644 index 0000000..28fd8b7 --- /dev/null +++ b/src/Storage/ArrayStorage/ArrayTaskExecutionRepository.php @@ -0,0 +1,37 @@ +setResult(null); + + return $execution; + } +} diff --git a/tests/Functional/Command/ScheduleTaskCommandTest.php b/tests/Functional/Command/ScheduleTaskCommandTest.php index e6d0995..3ac55f4 100644 --- a/tests/Functional/Command/ScheduleTaskCommandTest.php +++ b/tests/Functional/Command/ScheduleTaskCommandTest.php @@ -28,12 +28,12 @@ public function testExecute() ] ); - $tasks = $this->taskRepository->findAll(); + $tasks = $this->taskRepository->findAllPaginated(1); $this->assertCount(1, $tasks); $this->assertEquals(TestHandler::class, $tasks[0]->getHandlerClass()); - $executions = $this->taskExecutionRepository->findAll(); + $executions = $this->taskExecutionRepository->findAllPaginated(1); $this->assertCount(1, $executions); $this->assertEquals(TestHandler::class, $executions[0]->getHandlerClass()); @@ -49,7 +49,7 @@ public function testExecuteWithWorkload() ] ); - $tasks = $this->taskRepository->findAll(); + $tasks = $this->taskRepository->findAllPaginated(1); $this->assertCount(1, $tasks); $this->assertEquals(TestHandler::class, $tasks[0]->getHandlerClass()); @@ -67,7 +67,7 @@ public function testExecuteWithWorkloadAndInterval() ] ); - $tasks = $this->taskRepository->findAll(); + $tasks = $this->taskRepository->findAllPaginated(1); $this->assertCount(1, $tasks); $this->assertEquals(TestHandler::class, $tasks[0]->getHandlerClass()); @@ -88,7 +88,7 @@ public function testExecuteWithWorkloadAndIntervalAndEndDate() ] ); - $tasks = $this->taskRepository->findAll(); + $tasks = $this->taskRepository->findAllPaginated(1); $this->assertCount(1, $tasks); $this->assertEquals(TestHandler::class, $tasks[0]->getHandlerClass()); @@ -109,13 +109,13 @@ public function testExecuteWithExecutionDate() ] ); - $tasks = $this->taskRepository->findAll(); + $tasks = $this->taskRepository->findAllPaginated(1); $this->assertCount(1, $tasks); $this->assertEquals(TestHandler::class, $tasks[0]->getHandlerClass()); $this->assertGreaterThanOrEqual($date, $tasks[0]->getFirstExecution()); - $executions = $this->taskExecutionRepository->findAll(); + $executions = $this->taskExecutionRepository->findAllPaginated(1); $this->assertCount(1, $executions); $this->assertEquals(TestHandler::class, $executions[0]->getHandlerClass()); diff --git a/tests/Functional/Entity/TaskExecutionRepositoryTest.php b/tests/Functional/Entity/TaskExecutionRepositoryTest.php index 0a94fa2..b4012e8 100644 --- a/tests/Functional/Entity/TaskExecutionRepositoryTest.php +++ b/tests/Functional/Entity/TaskExecutionRepositoryTest.php @@ -65,7 +65,7 @@ public function testFindAll() $executions[$execution->getUuid()] = $execution; } - $result = $this->taskExecutionRepository->findAll(); + $result = $this->taskExecutionRepository->findAllPaginated(1); $this->assertCount(3, $result); foreach ($result as $item) { From c69140c63d976b13e43c2c472119f8445cd1870e Mon Sep 17 00:00:00 2001 From: Johannes Wachter Date: Tue, 19 May 2026 13:20:56 +0200 Subject: [PATCH 3/4] Allow symfony/var-exporter ^5.4 for PHP 8.0 compatibility --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 81f6198..5495911 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,7 @@ "phpunit/phpunit": "^9.6.5 || ^10", "phpspec/prophecy": "^1.14", "phpspec/prophecy-phpunit": "^2.0", - "symfony/var-exporter": "^6.4 || ^7.0" + "symfony/var-exporter": "^5.4 || ^6.4 || ^7.0" }, "autoload": { "psr-4": { From 6a33385cd093e27b83b26e6575602f59948c266b Mon Sep 17 00:00:00 2001 From: Johannes Wachter Date: Tue, 19 May 2026 14:57:22 +0200 Subject: [PATCH 4/4] Revert BC-breaking workarounds per @alexander-schranz review Revert the changes that altered TaskExecutionRepository::create() to accept DateTimeInterface and that subclassed the upstream ArrayTaskExecutionRepository. The interface requires DateTimeImmutable and widening it breaks BC for consumers. The conversion belongs on the caller side (upstream TaskScheduler in php-task/php-task), not on every TaskExecutionRepository implementation. --- src/Entity/TaskExecution.php | 8 ---- src/Entity/TaskExecutionRepository.php | 6 +-- src/Resources/config/storage/array.xml | 2 +- .../ArrayTaskExecutionRepository.php | 37 ------------------- 4 files changed, 2 insertions(+), 51 deletions(-) delete mode 100644 src/Storage/ArrayStorage/ArrayTaskExecutionRepository.php diff --git a/src/Entity/TaskExecution.php b/src/Entity/TaskExecution.php index 36914cd..bc6e592 100644 --- a/src/Entity/TaskExecution.php +++ b/src/Entity/TaskExecution.php @@ -18,12 +18,4 @@ */ class TaskExecution extends BaseTaskExecution { - public function getResult() - { - if (null === $this->result) { - return null; - } - - return parent::getResult(); - } } diff --git a/src/Entity/TaskExecutionRepository.php b/src/Entity/TaskExecutionRepository.php index 6ad1172..7236008 100644 --- a/src/Entity/TaskExecutionRepository.php +++ b/src/Entity/TaskExecutionRepository.php @@ -26,12 +26,8 @@ class TaskExecutionRepository extends EntityRepository implements TaskExecutionR /** * {@inheritdoc} */ - public function create(TaskInterface $task, \DateTimeInterface $scheduleTime) + public function create(TaskInterface $task, \DateTimeImmutable $scheduleTime) { - if (!$scheduleTime instanceof \DateTimeImmutable) { - $scheduleTime = \DateTimeImmutable::createFromInterface($scheduleTime); - } - return new TaskExecution($task, $task->getHandlerClass(), $scheduleTime, $task->getWorkload()); } diff --git a/src/Resources/config/storage/array.xml b/src/Resources/config/storage/array.xml index 7e718d3..2bd31a7 100644 --- a/src/Resources/config/storage/array.xml +++ b/src/Resources/config/storage/array.xml @@ -4,6 +4,6 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - + diff --git a/src/Storage/ArrayStorage/ArrayTaskExecutionRepository.php b/src/Storage/ArrayStorage/ArrayTaskExecutionRepository.php deleted file mode 100644 index 28fd8b7..0000000 --- a/src/Storage/ArrayStorage/ArrayTaskExecutionRepository.php +++ /dev/null @@ -1,37 +0,0 @@ -setResult(null); - - return $execution; - } -}