Skip to content

Commit 2ff9490

Browse files
authored
Merge pull request #149 from laminas/1.12.x-merge-up-into-1.13.x_8ivEmNRk
Merge release 1.12.2 into 1.13.x
2 parents da94ae9 + 8e1a296 commit 2ff9490

10 files changed

+416
-7
lines changed

CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
All notable changes to this project will be documented in this file, in reverse chronological order by release.
44

5+
56
## 1.13.0 - TBD
67

78
### Added
@@ -24,6 +25,24 @@ All notable changes to this project will be documented in this file, in reverse
2425

2526
- Nothing.
2627

28+
## 1.12.2 - 2021-06-04
29+
30+
31+
-----
32+
33+
### Release Notes for [1.12.2](https://github.com/laminas/automatic-releases/milestone/34)
34+
35+
1.12.x bugfix release (patch)
36+
37+
### 1.12.2
38+
39+
- Total issues resolved: **0**
40+
- Total pull requests resolved: **1**
41+
- Total contributors: **1**
42+
43+
#### Bug
44+
45+
- [148: Hardening scenarios around failed Github API and GraphQL calls](https://github.com/laminas/automatic-releases/pull/148) thanks to @Ocramius
2746

2847
## 1.12.1 - 2021-05-23
2948

src/Github/Api/GraphQL/RunGraphQLQuery.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@
44

55
namespace Laminas\AutomaticReleases\Github\Api\GraphQL;
66

7+
use Psl;
78
use Psl\Json;
89
use Psl\Type;
910
use Psr\Http\Client\ClientInterface;
1011
use Psr\Http\Message\RequestFactoryInterface;
1112

13+
use function array_key_exists;
14+
1215
final class RunGraphQLQuery implements RunQuery
1316
{
1417
private const ENDPOINT = 'https://api.github.com/graphql';
@@ -56,8 +59,13 @@ public function __invoke(
5659

5760
Type\literal_scalar(200)->assert($response->getStatusCode());
5861

59-
return Json\typed($responseBody, Type\shape([
60-
'data' => Type\dict(Type\string(), Type\mixed()),
61-
]))['data'];
62+
$response = Json\typed($responseBody, Type\shape([
63+
'data' => Type\dict(Type\string(), Type\mixed()),
64+
'errors' => Type\optional(Type\mixed()),
65+
]));
66+
67+
Psl\invariant(! array_key_exists('errors', $response), 'GraphQL query execution failed');
68+
69+
return $response['data'];
6270
}
6371
}

src/Github/Api/V3/CreatePullRequestThroughApiCall.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public function __invoke(
6262

6363
$response = $this->client->sendRequest($request);
6464

65-
Psl\invariant($response->getStatusCode() >= 200 || $response->getStatusCode() <= 299, 'Failed to create pull request through GitHub API.');
65+
Psl\invariant($response->getStatusCode() >= 200 && $response->getStatusCode() <= 299, 'Failed to create pull request through GitHub API.');
6666

6767
$responseBody = $response
6868
->getBody()

src/Github/Api/V3/SetDefaultBranchThroughApiCall.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public function __invoke(
5252

5353
$response = $this->client->sendRequest($request);
5454

55-
Psl\invariant($response->getStatusCode() >= 200 || $response->getStatusCode() <= 299, 'Failed to set default branch through GitHub API.');
55+
Psl\invariant($response->getStatusCode() >= 200 && $response->getStatusCode() <= 299, 'Failed to set default branch through GitHub API.');
5656

5757
$responseBody = $response
5858
->getBody()

test/unit/Github/Api/GraphQL/RunGraphQLQueryTest.php

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@
99
use Laminas\Diactoros\Response;
1010
use PHPUnit\Framework\MockObject\MockObject;
1111
use PHPUnit\Framework\TestCase;
12+
use Psl\Exception\InvariantViolationException;
1213
use Psl\SecureRandom;
14+
use Psl\Type\Exception\AssertException;
1315
use Psr\Http\Client\ClientInterface;
1416
use Psr\Http\Message\RequestFactoryInterface;
1517
use Psr\Http\Message\RequestInterface;
1618

19+
/** @covers \Laminas\AutomaticReleases\Github\Api\GraphQL\RunGraphQLQuery */
1720
final class RunGraphQLQueryTest extends TestCase
1821
{
1922
/** @var ClientInterface&MockObject */
@@ -84,4 +87,109 @@ public function testSuccessfulRequest(): void
8487
$this->runQuery->__invoke('the-query', ['a' => 'b'])
8588
);
8689
}
90+
91+
/**
92+
* @psalm-param positive-int $responseCode
93+
*
94+
* @dataProvider exampleFailureResponseCodes
95+
*/
96+
public function testWillThrowIfGraphQLResponseIsNotSuccessful(int $responseCode): void
97+
{
98+
$validResponse = (new Response())
99+
->withStatus($responseCode);
100+
101+
$validResponse->getBody()->write(<<<'JSON'
102+
{
103+
"data": {"foo": "bar"}
104+
}
105+
JSON
106+
);
107+
108+
$this
109+
->httpClient
110+
->expects(self::once())
111+
->method('sendRequest')
112+
->with(self::callback(function (RequestInterface $request): bool {
113+
self::assertSame(
114+
[
115+
'Host' => ['the-domain.com'],
116+
'Content-Type' => ['application/json'],
117+
'User-Agent' => ['Ocramius\'s minimal GraphQL client - stolen from Dunglas'],
118+
'Authorization' => ['bearer ' . $this->apiToken],
119+
],
120+
$request->getHeaders()
121+
);
122+
123+
self::assertSame(
124+
'{"query":"the-query","variables":{"a":"b"}}',
125+
$request->getBody()->__toString()
126+
);
127+
128+
return true;
129+
}))
130+
->willReturn($validResponse);
131+
132+
$this->expectException(AssertException::class);
133+
134+
self::assertSame(
135+
['foo' => 'bar'],
136+
$this->runQuery->__invoke('the-query', ['a' => 'b'])
137+
);
138+
}
139+
140+
/** @psalm-return non-empty-list<array{positive-int}> */
141+
public function exampleFailureResponseCodes(): array
142+
{
143+
return [
144+
[199],
145+
[201],
146+
[400],
147+
[500],
148+
];
149+
}
150+
151+
public function testWillThrowIfGraphQLResponseIncludesErrorsInResponse(): void
152+
{
153+
$validResponse = new Response();
154+
155+
$validResponse->getBody()->write(<<<'JSON'
156+
{
157+
"errors": ["nope"],
158+
"data": {"foo": "bar"}
159+
}
160+
JSON
161+
);
162+
163+
$this
164+
->httpClient
165+
->expects(self::once())
166+
->method('sendRequest')
167+
->with(self::callback(function (RequestInterface $request): bool {
168+
self::assertSame(
169+
[
170+
'Host' => ['the-domain.com'],
171+
'Content-Type' => ['application/json'],
172+
'User-Agent' => ['Ocramius\'s minimal GraphQL client - stolen from Dunglas'],
173+
'Authorization' => ['bearer ' . $this->apiToken],
174+
],
175+
$request->getHeaders()
176+
);
177+
178+
self::assertSame(
179+
'{"query":"the-query","variables":{"a":"b"}}',
180+
$request->getBody()->__toString()
181+
);
182+
183+
return true;
184+
}))
185+
->willReturn($validResponse);
186+
187+
$this->expectException(InvariantViolationException::class);
188+
$this->expectExceptionMessage('GraphQL query execution failed');
189+
190+
self::assertSame(
191+
['foo' => 'bar'],
192+
$this->runQuery->__invoke('the-query', ['a' => 'b'])
193+
);
194+
}
87195
}

test/unit/Github/Api/V3/CreateMilestoneTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use Psr\Http\Message\RequestInterface;
1919
use Psr\Log\LoggerInterface;
2020

21+
/** @covers \Laminas\AutomaticReleases\Github\Api\V3\CreateMilestoneThroughApiCall */
2122
class CreateMilestoneTest extends TestCase
2223
{
2324
/** @var ClientInterface&MockObject */

test/unit/Github/Api/V3/CreatePullRequestTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Psr\Http\Message\RequestFactoryInterface;
1717
use Psr\Http\Message\RequestInterface;
1818

19+
/** @covers \Laminas\AutomaticReleases\Github\Api\V3\CreatePullRequestThroughApiCall */
1920
final class CreatePullRequestTest extends TestCase
2021
{
2122
/** @var ClientInterface&MockObject */

0 commit comments

Comments
 (0)