Skip to content

Commit 730f70e

Browse files
authored
Merge pull request #283 from andrew-demb/ci
[#282] Fix compatibility with GraphQLite 8.2. Improve CI - prefer lowest, run static analysis for the highest PHP version, PHP 8.5
2 parents aa87948 + ebf769f commit 730f70e

7 files changed

Lines changed: 149 additions & 54 deletions

File tree

.github/workflows/test.yaml

Lines changed: 57 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,30 @@ concurrency:
1212
jobs:
1313
test:
1414
runs-on: ubuntu-latest
15-
name: test
15+
name: test (${{ matrix.name }})
1616
strategy:
1717
matrix:
18-
install-args: ['']
19-
php-version: ['8.2', '8.3', '8.4']
18+
include:
19+
- name: php-8.2
20+
php-version: '8.2'
21+
install-args: ''
22+
composer-cache-suffix: default
23+
- name: php-8.3
24+
php-version: '8.3'
25+
install-args: ''
26+
composer-cache-suffix: default
27+
- name: php-8.4
28+
php-version: '8.4'
29+
install-args: ''
30+
composer-cache-suffix: default
31+
- name: php-8.5
32+
php-version: '8.5'
33+
install-args: ''
34+
composer-cache-suffix: default
35+
- name: php-8.5-prefer-lowest
36+
php-version: '8.5'
37+
install-args: '--prefer-lowest'
38+
composer-cache-suffix: prefer-lowest
2039
fail-fast: false
2140
steps:
2241
- name: checkout
@@ -37,9 +56,9 @@ jobs:
3756
uses: actions/cache@v5.0.5
3857
with:
3958
path: ${{ steps.composercache.outputs.dir }}
40-
key: composer-${{ hashFiles('**/composer.json') }}-${{ matrix.install-args }}
59+
key: composer-${{ hashFiles('**/composer.json') }}-${{ matrix.composer-cache-suffix }}
4160
restore-keys: |
42-
composer-${{ hashFiles('**/composer.json') }}-${{ matrix.install-args }}
61+
composer-${{ hashFiles('**/composer.json') }}-${{ matrix.composer-cache-suffix }}
4362
composer-${{ hashFiles('**/composer.json') }}-
4463
composer-
4564
@@ -51,15 +70,44 @@ jobs:
5170
run: |
5271
vendor/bin/simple-phpunit --no-coverage
5372
73+
static-analysis:
74+
runs-on: ubuntu-latest
75+
name: static-analysis
76+
steps:
77+
- name: checkout
78+
uses: actions/checkout@v6
79+
80+
- name: php
81+
uses: shivammathur/setup-php@2.36.0
82+
with:
83+
php-version: '8.5'
84+
ini-values: zend.assertions=1
85+
86+
- name: composer-cache-dir
87+
id: composercache
88+
run: |
89+
echo "::set-output name=dir::$(composer config cache-files-dir)"
90+
91+
- name: composer-cache
92+
uses: actions/cache@v5.0.5
93+
with:
94+
path: ${{ steps.composercache.outputs.dir }}
95+
key: composer-${{ hashFiles('**/composer.json') }}
96+
restore-keys: |
97+
composer-${{ hashFiles('**/composer.json') }}
98+
composer-
99+
100+
- name: composer
101+
run: |
102+
composer update --no-interaction --no-progress --prefer-dist
103+
54104
- name: phpstan-cache
55105
uses: actions/cache@v5.0.5
56106
with:
57-
key: phpstan-${{ matrix.php-version }}-${{ matrix.install-args }}-${{ github.ref }}-${{ github.sha }}
107+
key: phpstan-${{ github.ref }}-${{ github.sha }}
58108
path: .phpstan-cache
59109
restore-keys: |
60-
phpstan-${{ matrix.php-version }}-${{ matrix.install-args }}-${{ github.ref }}-
61-
phpstan-${{ matrix.php-version }}-${{ matrix.install-args }}-
62-
phpstan-${{ matrix.php-version }}-
110+
phpstan-${{ github.ref }}-
63111
phpstan-
64112
65113
- name: phpstan

composer.json

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"require" : {
1919
"php" : ">=8.1",
2020
"ext-json": "*",
21-
"thecodingmachine/graphqlite" : "^8",
21+
"thecodingmachine/graphqlite" : "^8.1",
2222
"thecodingmachine/graphqlite-symfony-validator-bridge": "^7.1.1",
2323
"symfony/config": "^6.4 || ^7.0 || ^8.0",
2424
"symfony/console": "^6.4 || ^7.0 || ^8.0",
@@ -34,18 +34,15 @@
3434
"symfony/security-bundle": "^6.4 || ^7.0 || ^8.0",
3535
"symfony/yaml": "^6.4 || ^7.0 || ^8.0",
3636
"beberlei/porpaginas": "^1.2 || ^2.0",
37-
"symfony/phpunit-bridge": "^6.4 || ^7 || ^8.0",
37+
"symfony/phpunit-bridge": "^6.4.35 || ^7 || ^8.0",
3838
"phpstan/phpstan": "^2",
3939
"phpstan/phpstan-symfony": "^2.0",
4040
"composer/package-versions-deprecated": "^1.8",
4141
"composer/semver": "^3.4",
4242
"overblog/graphiql-bundle": "^0.2 || ^0.3 || ^1"
4343
},
4444
"conflict": {
45-
"symfony/event-dispatcher": "<4.3",
46-
"symfony/security-core": "<4.3",
47-
"symfony/routing": "<4.3",
48-
"phpdocumentor/type-resolver": "<1.4"
45+
"symfony/password-hasher": "<6.4"
4946
},
5047
"scripts": {
5148
"phpstan": "phpstan analyse -c phpstan.neon --no-progress"

phpstan.neon

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ parameters:
99
- src
1010
excludePaths:
1111
- vendor
12-
- cache
13-
- .phpstan-cache
12+
- cache (?)
13+
- .phpstan-cache (?)
1414
- tests
1515

1616
polluteScopeWithLoopInitialAssignments: false

src/DependencyInjection/GraphQLiteCompilerPass.php

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -337,13 +337,16 @@ private function makePublicInjectedServices(ReflectionClass $refClass, Annotatio
337337
$services = $this->getCodeCache()->get($refClass, function() use ($refClass, $reader, $container, $isController): array {
338338
$services = [];
339339
foreach ($refClass->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
340-
$field = $reader->getRequestAnnotation($method, Field::class) ?? $reader->getRequestAnnotation($method, Query::class) ?? $reader->getRequestAnnotation($method, Mutation::class);
341-
if ($field !== null) {
340+
$resolveResult = $this->resolveFieldGraphqlElement($reader, $method);
341+
if ($resolveResult['exists']) {
342342
if ($isController) {
343343
$services[$refClass->getName()] = $refClass->getName();
344344
}
345+
345346
$services += $this->getListOfInjectedServices($method, $container);
346-
if ($field instanceof Field && $field->getPrefetchMethod() !== null) {
347+
348+
$field = $resolveResult['field'];
349+
if (null !== $field && $field->getPrefetchMethod() !== null) {
347350
$services += $this->getListOfInjectedServices($refClass->getMethod($field->getPrefetchMethod()), $container);
348351
}
349352
}
@@ -467,4 +470,29 @@ private function getClassList(string $namespace): Generator
467470
}
468471
}
469472

473+
/**
474+
* @return array{exists: bool, field: Field|null}
475+
*/
476+
private function resolveFieldGraphqlElement(AnnotationReader $reader, ReflectionMethod $method): array
477+
{
478+
// backward compatibility with graphqlite v8.1
479+
// @phpstan-ignore function.alreadyNarrowedType
480+
if (false === \method_exists($reader, 'getGraphQLElementAnnotation')) {
481+
// graphqlite versions in this BC branch expose getRequestAnnotation instead.
482+
// @phpstan-ignore method.notFound
483+
$element = $reader->getRequestAnnotation($method, Field::class)
484+
// @phpstan-ignore method.notFound
485+
?? $reader->getRequestAnnotation($method, Query::class)
486+
// @phpstan-ignore method.notFound
487+
?? $reader->getRequestAnnotation($method, Mutation::class);
488+
489+
return ['exists' => null !== $element, 'field' => ($element instanceof Field ? $element : null)];
490+
}
491+
492+
$element = $reader->getGraphQLElementAnnotation($method, Field::class)
493+
?? $reader->getGraphQLElementAnnotation($method, Query::class)
494+
?? $reader->getGraphQLElementAnnotation($method, Mutation::class);
495+
496+
return ['exists' => null !== $element, 'field' => ($element instanceof Field ? $element : null)];
497+
}
470498
}

tests/Command/DumpSchemaCommandTest.php

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,20 @@ public function testExecute(): void
1818
$commandTester = new CommandTester($command);
1919
$commandTester->execute([]);
2020

21+
preg_match('/type Product \{(?P<body>[\s\S]*?)}/', $commandTester->getDisplay(), $matches);
22+
self::assertArrayHasKey('body', $matches);
23+
24+
self::assertMatchesRegularExpression(
25+
'/name: String!/',
26+
$matches['body']
27+
);
28+
self::assertMatchesRegularExpression(
29+
'/price: Float!/',
30+
$matches['body']
31+
);
2132
self::assertMatchesRegularExpression(
22-
'/type Product {[\s"]*name: String!\s*price: Float!\s*seller: Contact\s*}/',
23-
$commandTester->getDisplay()
33+
'/seller: Contact/',
34+
$matches['body']
2435
);
2536
}
2637
}

tests/FunctionalTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,10 @@ public function testValidation(): void
481481

482482
$response = $kernel->handle($request);
483483

484+
$this->assertSame(400, $response->getStatusCode());
484485
$result = json_decode($response->getContent(), true);
486+
$this->assertIsArray($result);
487+
$this->assertArrayHasKey('errors', $result);
485488
$errors = $result['errors'];
486489

487490
$this->assertSame('This value is not a valid email address.', $errors[0]['message']);

tests/GraphQLiteTestingKernel.php

Lines changed: 40 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,11 @@ public function registerBundles(): iterable
100100
public function configureContainer(ContainerBuilder $c, LoaderInterface $loader)
101101
{
102102
$loader->load(function(ContainerBuilder $container) {
103-
$frameworkConf = array(
104-
'secret' => 'S0ME_SECRET'
105-
);
103+
$frameworkConf = [
104+
'secret' => 'S0ME_SECRET',
105+
// forward compatibility with symfony/validator v7
106+
'validation' => ['email_validation_mode' => 'html5'],
107+
];
106108

107109
$frameworkConf['cache'] =[
108110
'app' => 'cache.adapter.array',
@@ -126,46 +128,52 @@ public function configureContainer(ContainerBuilder $c, LoaderInterface $loader)
126128
$extraConfig['enable_authenticator_manager'] = true;
127129
}
128130

129-
$container->loadFromExtension('security', array_merge(array(
130-
'providers' => [
131-
'in_memory' => [
132-
'memory' => [
133-
'users' => [
134-
'foo' => [
135-
'password' => 'bar',
136-
'roles' => 'ROLE_USER',
131+
$container->loadFromExtension(
132+
'security',
133+
array_merge(
134+
[
135+
'providers' => [
136+
'in_memory' => [
137+
'memory' => [
138+
'users' => [
139+
'foo' => [
140+
'password' => 'bar',
141+
'roles' => 'ROLE_USER',
142+
],
143+
],
137144
],
138-
],
139-
],
140-
],
141-
'in_memory_other' => [
142-
'memory' => [
143-
'users' => [
144-
'foo' => [
145-
'password' => 'bar',
146-
'roles' => 'ROLE_USER',
145+
],
146+
'in_memory_other' => [
147+
'memory' => [
148+
'users' => [
149+
'foo' => [
150+
'password' => 'bar',
151+
'roles' => 'ROLE_USER',
152+
],
153+
],
147154
],
148155
],
149156
],
157+
'firewalls' => [
158+
'main' => [
159+
'provider' => 'in_memory',
160+
],
161+
],
162+
'password_hashers' => [
163+
InMemoryUser::class => 'plaintext',
164+
],
150165
],
151-
],
152-
'firewalls' => [
153-
'main' => [
154-
'provider' => 'in_memory'
155-
]
156-
],
157-
'password_hashers' => [
158-
InMemoryUser::class => 'plaintext',
159-
],
160-
), $extraConfig));
166+
$extraConfig,
167+
),
168+
);
161169
}
162170

163-
$graphqliteConf = array(
171+
$graphqliteConf = [
164172
'namespace' => [
165173
'controllers' => $this->controllersNamespace,
166174
'types' => $this->typesNamespace
167175
],
168-
);
176+
];
169177

170178
if ($this->enableLogin) {
171179
$graphqliteConf['security']['enable_login'] = $this->enableLogin;

0 commit comments

Comments
 (0)