From c4d71ee95579b917372b1e55a7beefdda1879f9a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Sep 2025 10:11:05 -0400 Subject: [PATCH 1/8] Bump actions/setup-node from 4 to 5 (#759) Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4 to 5. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-node dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/doc_generation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/doc_generation.yml b/.github/workflows/doc_generation.yml index 97caa41546..d6e29165f7 100644 --- a/.github/workflows/doc_generation.yml +++ b/.github/workflows/doc_generation.yml @@ -22,7 +22,7 @@ jobs: uses: "actions/checkout@v5" - name: "Setup NodeJS" - uses: actions/setup-node@v4 + uses: actions/setup-node@v5 with: node-version: '20.x' From 5ed662c18a63ef7b5eed30bea27b82bd31477cab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Sep 2025 10:11:19 -0400 Subject: [PATCH 2/8] Bump codecov/codecov-action from 5.5.0 to 5.5.1 (#758) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.5.0 to 5.5.1. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v5.5.0...v5.5.1) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-version: 5.5.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/continuous_integration.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/continuous_integration.yml b/.github/workflows/continuous_integration.yml index 375e7b9daa..07b6da2a08 100644 --- a/.github/workflows/continuous_integration.yml +++ b/.github/workflows/continuous_integration.yml @@ -85,7 +85,7 @@ jobs: path: "build" overwrite: true - - uses: codecov/codecov-action@v5.5.0 # upload the coverage to codecov + - uses: codecov/codecov-action@v5.5.1 # upload the coverage to codecov with: fail_ci_if_error: false # optional (default = false) - Need CODECOV_TOKEN # Do not upload in forks, and only on php8.4, latest deps From cb7c195b54ffafca493eb7ce6c31e1d7ceca28a4 Mon Sep 17 00:00:00 2001 From: Andrii Dembitskyi Date: Fri, 10 Oct 2025 21:58:35 +0300 Subject: [PATCH 3/8] :sparkles: Improve exception message for unexpected null value - mention expected type (#762) --- src/ResolveUtils.php | 4 ++-- src/TypeMismatchRuntimeException.php | 12 ++++++++++-- tests/ResolveUtilsTest.php | 2 ++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/ResolveUtils.php b/src/ResolveUtils.php index b3aa657668..2f95d35f32 100644 --- a/src/ResolveUtils.php +++ b/src/ResolveUtils.php @@ -24,7 +24,7 @@ final class ResolveUtils public static function assertInnerReturnType(mixed $result, Type $type): void { if ($type instanceof NonNull && $result === null) { - throw TypeMismatchRuntimeException::unexpectedNullValue(); + throw TypeMismatchRuntimeException::unexpectedNullValue($type); } if ($result === null) { return; @@ -56,7 +56,7 @@ public static function assertInnerReturnType(mixed $result, Type $type): void public static function assertInnerInputType(mixed $input, Type $type): void { if ($type instanceof NonNull && $input === null) { - throw TypeMismatchRuntimeException::unexpectedNullValue(); + throw TypeMismatchRuntimeException::unexpectedNullValue($type); } if ($input === null) { return; diff --git a/src/TypeMismatchRuntimeException.php b/src/TypeMismatchRuntimeException.php index c73e323dac..d121bb4809 100644 --- a/src/TypeMismatchRuntimeException.php +++ b/src/TypeMismatchRuntimeException.php @@ -4,6 +4,8 @@ namespace TheCodingMachine\GraphQLite; +use GraphQL\Type\Definition\Type; + use function gettype; /** @@ -11,9 +13,15 @@ */ class TypeMismatchRuntimeException extends GraphQLRuntimeException { - public static function unexpectedNullValue(): self + public static function unexpectedNullValue(Type|null $expectedType = null): self { - return new self('Unexpected null value for non nullable field.'); + $expectedMessageTail = ''; + if ($expectedType !== null) { + $expectedMessageTail = ' Expected: "' . $expectedType->toString() . '"'; + // ToDo: support for NULL $expectedType should be dropped in the next major + } + + return new self('Unexpected null value for non nullable field.' . $expectedMessageTail); } public static function expectedIterable(mixed $result): self diff --git a/tests/ResolveUtilsTest.php b/tests/ResolveUtilsTest.php index ca5a1e634c..041f42d4e7 100644 --- a/tests/ResolveUtilsTest.php +++ b/tests/ResolveUtilsTest.php @@ -12,6 +12,7 @@ class ResolveUtilsTest extends TestCase public function testAssertNull(): void { $this->expectException(TypeMismatchRuntimeException::class); + $this->expectExceptionMessage('Unexpected null value for non nullable field. Expected: "String!"'); ResolveUtils::assertInnerReturnType(null, Type::nonNull(Type::string())); } @@ -30,6 +31,7 @@ public function testAssertObjectOk(): void public function testAssertInputNull(): void { $this->expectException(TypeMismatchRuntimeException::class); + $this->expectExceptionMessage('Unexpected null value for non nullable field. Expected: "String!"'); ResolveUtils::assertInnerInputType(null, Type::nonNull(Type::string())); } From 62552cba72fa68aa8289133734ad6a5b001895ca Mon Sep 17 00:00:00 2001 From: Jorg Adam Sowa Date: Thu, 11 Dec 2025 04:10:03 +0100 Subject: [PATCH 4/8] chore: symfony 8 dependencies (#770) * chore: symfony 8 dependencies * fix ExceptionLogger --- composer.json | 6 +++--- src/Utils/PropertyAccessor.php | 1 + tests/Loggers/ExceptionLogger.php | 13 +++++++------ 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/composer.json b/composer.json index 520f02bbc5..00ccdb862c 100644 --- a/composer.json +++ b/composer.json @@ -21,8 +21,8 @@ "psr/http-server-handler": "^1", "psr/http-server-middleware": "^1", "psr/simple-cache": "^1.0.1 || ^2 || ^3", - "symfony/cache": "^4.3 || ^5 || ^6 || ^7", - "symfony/expression-language": "^4 || ^5 || ^6 || ^7", + "symfony/cache": "^4.3 || ^5 || ^6 || ^7 || ^8", + "symfony/expression-language": "^4 || ^5 || ^6 || ^7 || ^8", "webonyx/graphql-php": "^v15.0", "kcs/class-finder": "^0.6.0" }, @@ -35,7 +35,7 @@ "php-coveralls/php-coveralls": "^2.7", "phpstan/extension-installer": "^1.4", "phpstan/phpstan": "^2.0", - "phpunit/phpunit": "^10.5 || ^11.0", + "phpunit/phpunit": "^10.5 || ^11.0 || ^12.0", "symfony/var-dumper": "^6.4" }, "suggest": { diff --git a/src/Utils/PropertyAccessor.php b/src/Utils/PropertyAccessor.php index 1347d1151c..2d0b4bd76d 100644 --- a/src/Utils/PropertyAccessor.php +++ b/src/Utils/PropertyAccessor.php @@ -94,6 +94,7 @@ public static function setValue(object $instance, string $propertyName, mixed $v throw AccessPropertyException::createForUnwritableProperty($class, $propertyName); } + /** @param class-string $class */ private static function isPublicProperty(string $class, string $propertyName): bool { if (! property_exists($class, $propertyName)) { diff --git a/tests/Loggers/ExceptionLogger.php b/tests/Loggers/ExceptionLogger.php index 612d0226ce..3a0a65861a 100644 --- a/tests/Loggers/ExceptionLogger.php +++ b/tests/Loggers/ExceptionLogger.php @@ -1,12 +1,15 @@ Date: Mon, 15 Dec 2025 15:31:08 -0500 Subject: [PATCH 5/8] Bump actions/upload-artifact from 4 to 6 (#775) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 6. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v4...v6) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/continuous_integration.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/continuous_integration.yml b/.github/workflows/continuous_integration.yml index 07b6da2a08..b6f83ab849 100644 --- a/.github/workflows/continuous_integration.yml +++ b/.github/workflows/continuous_integration.yml @@ -79,7 +79,7 @@ jobs: run: composer cs-check - name: "Archive code coverage results" - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: codeCoverage-${{ matrix.php-version }}-${{ github.run_id }} path: "build" From b01944a09281f3c15ad9d8d1cbb4aa65f1c6c629 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Dec 2025 15:35:13 -0500 Subject: [PATCH 6/8] Bump actions/cache from 4 to 5 (#774) Bumps [actions/cache](https://github.com/actions/cache) from 4 to 5. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/cache dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/continuous_integration.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/continuous_integration.yml b/.github/workflows/continuous_integration.yml index b6f83ab849..cd0653d998 100644 --- a/.github/workflows/continuous_integration.yml +++ b/.github/workflows/continuous_integration.yml @@ -44,7 +44,7 @@ jobs: echo "::set-output name=dir::$(composer config cache-files-dir)" - name: composer-cache - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: ${{ steps.composercache.outputs.dir }} key: composer-${{ hashFiles('**/composer.json') }}-${{ matrix.install-args }} @@ -61,7 +61,7 @@ jobs: run: "vendor/bin/phpunit" - name: phpstan-cache - uses: actions/cache@v4 + uses: actions/cache@v5 with: key: phpstan-${{ matrix.php-version }}-${{ matrix.install-args }}-${{ github.ref }}-${{ github.sha }} path: .phpstan-cache From 0ef3465e3a8502338c00213b044012f3900c3590 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Dec 2025 15:35:42 -0500 Subject: [PATCH 7/8] Bump JamesIves/github-pages-deploy-action from 4.7.3 to 4.7.6 (#773) Bumps [JamesIves/github-pages-deploy-action](https://github.com/jamesives/github-pages-deploy-action) from 4.7.3 to 4.7.6. - [Release notes](https://github.com/jamesives/github-pages-deploy-action/releases) - [Commits](https://github.com/jamesives/github-pages-deploy-action/compare/v4.7.3...v4.7.6) --- updated-dependencies: - dependency-name: JamesIves/github-pages-deploy-action dependency-version: 4.7.6 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/doc_generation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/doc_generation.yml b/.github/workflows/doc_generation.yml index d6e29165f7..f96e79e728 100644 --- a/.github/workflows/doc_generation.yml +++ b/.github/workflows/doc_generation.yml @@ -36,7 +36,7 @@ jobs: - name: "Deploy website" if: "${{ github.event_name == 'push' || github.event_name == 'release' }}" - uses: JamesIves/github-pages-deploy-action@v4.7.3 + uses: JamesIves/github-pages-deploy-action@v4.7.6 with: token: ${{ secrets.GITHUB_TOKEN }} branch: gh-pages # The branch the action should deploy to. From 76c0ef939f3aa030992a96b8e2e7930de4d3e400 Mon Sep 17 00:00:00 2001 From: Faizan Akram Dar Date: Wed, 17 Dec 2025 17:58:34 +0100 Subject: [PATCH 8/8] fix: validate files in FilesSnapshot before processing (#772) Add check to ensure each file is valid before processing. Without this change filemtime throws an error if the file doesn't exist but is part of cache, which is very common in dev environment. For production it won't matter since is_file is cached, for some reason is_file is also faster than file_exists. Symfony codebase also prefers is_file over file_exists when checking existence of php file. --- src/Cache/FilesSnapshot.php | 5 +++++ tests/Cache/FilesSnapshotTest.php | 30 +++++++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/Cache/FilesSnapshot.php b/src/Cache/FilesSnapshot.php index 7ac70861ac..afed10f0c3 100644 --- a/src/Cache/FilesSnapshot.php +++ b/src/Cache/FilesSnapshot.php @@ -7,6 +7,7 @@ use ReflectionClass; use function array_unique; +use function is_file; use function Safe\filemtime; class FilesSnapshot @@ -24,6 +25,10 @@ public static function for(array $files): self $dependencies = []; foreach (array_unique($files) as $file) { + if (! is_file($file)) { + continue; + } + $dependencies[$file] = filemtime($file); } diff --git a/tests/Cache/FilesSnapshotTest.php b/tests/Cache/FilesSnapshotTest.php index f45aa2c75e..a82baeb95a 100644 --- a/tests/Cache/FilesSnapshotTest.php +++ b/tests/Cache/FilesSnapshotTest.php @@ -69,9 +69,37 @@ public function testTracksChangesInFile(): void self::assertTrue($snapshot->changed()); } + public function testIgnoresNonExistentFiles(): void + { + $nonExistentFile = '/path/to/non/existent/file.php'; + + $snapshot = FilesSnapshot::for([$nonExistentFile]); + + self::assertFalse($snapshot->changed()); + } + + public function testIgnoresNonExistentFilesInMixedList(): void + { + $existingFile = (new \ReflectionClass(FooType::class))->getFileName(); + $nonExistentFile1 = '/path/to/non/existent/file1.php'; + $nonExistentFile2 = '/path/to/non/existent/file2.php'; + + $snapshot = FilesSnapshot::for([ + $nonExistentFile1, + $existingFile, + $nonExistentFile2, + ]); + + self::assertFalse($snapshot->changed()); + + $this->touch($existingFile); + + self::assertTrue($snapshot->changed()); + } + private function touch(string $fileName): void { touch($fileName, filemtime($fileName) + 1); clearstatcache(); } -} \ No newline at end of file +}