Skip to content

Commit dcdbcee

Browse files
committed
create specific exceptions for release process
1 parent b832e62 commit dcdbcee

File tree

5 files changed

+97
-22
lines changed

5 files changed

+97
-22
lines changed

bin/create_release

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
require __DIR__.'/../vendor/autoload.php';
55

66
use SymfonyDocsBuilder\Phar\Compiler;
7+
use SymfonyDocsBuilder\Release\Exception\ReleaseFailed;
78
use SymfonyDocsBuilder\Release\GithubApiHttpClientFactory;
89
use SymfonyDocsBuilder\Release\Releaser;
910

@@ -21,6 +22,11 @@ try {
2122

2223
$releaser->createRelease(...$argv);
2324
} catch (Exception $e) {
24-
echo 'Failed to create a new release: ['.get_class($e).'] '.$e->getMessage().' at '.$e->getFile().':'.$e->getLine()."\n";
25+
if ($e instanceof ReleaseFailed) {
26+
echo $e->toString();
27+
} else {
28+
echo 'Failed to create a new release: ['.get_class($e).'] '.$e->getMessage().' at '.$e->getFile().':'.$e->getLine()."\n";
29+
}
30+
2531
exit(1);
2632
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace SymfonyDocsBuilder\Release\Exception;
4+
5+
use Symfony\Contracts\HttpClient\Exception\HttpExceptionInterface;
6+
7+
class DeleteReleaseFailed extends ReleaseFailed
8+
{
9+
private $originException;
10+
11+
public function __construct(ReleaseFailed $originException, HttpExceptionInterface $previous)
12+
{
13+
$this->originException = $originException;
14+
15+
parent::__construct('Error while deleting release.', 0, $previous);
16+
}
17+
18+
public function toString(): string
19+
{
20+
return sprintf(
21+
"%s\n\nOriginal exception was: [%s]\n\t\"%s\"\n\tat %s:%s\n",
22+
parent::toString(),
23+
get_class($this->originException),
24+
$this->originException->getMessage(),
25+
$this->originException->getFile(),
26+
$this->originException->getLine()
27+
);
28+
}
29+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace SymfonyDocsBuilder\Release\Exception;
4+
5+
use Symfony\Contracts\HttpClient\Exception\HttpExceptionInterface;
6+
7+
class ReleaseFailed extends \RuntimeException
8+
{
9+
public static function whileCreatingDraft(HttpExceptionInterface $previous): self
10+
{
11+
if (401 === $previous->getCode()) {
12+
$message = 'Error while trying to create release: Invalid token.';
13+
} else {
14+
$message = 'Error while trying to create release.';
15+
}
16+
17+
return new self($message, 0, $previous);
18+
}
19+
20+
public static function whileAttachingAssetToRelease(HttpExceptionInterface $previous): self
21+
{
22+
return new self('Error while adding asset to release.', 0, $previous);
23+
}
24+
25+
public static function whilePublishingRelease(HttpExceptionInterface $previous): self
26+
{
27+
return new self('Error while publishing release. Maybe the tag name already exists?', 0, $previous);
28+
}
29+
30+
public function toString(): string
31+
{
32+
return sprintf(
33+
"Failed to create a new release: [%s]\n\t\"%s\"\n\tat %s:%s\n\nHttpException was: [%s]\n\t\"%s\"\n\tat %s:%s\n",
34+
self::class,
35+
$this->getMessage(),
36+
$this->getFile(),
37+
$this->getLine(),
38+
get_class($this->getPrevious()),
39+
$this->getPrevious()->getMessage(),
40+
$this->getPrevious()->getFile(),
41+
$this->getPrevious()->getLine()
42+
);
43+
}
44+
}

src/Release/Releaser.php

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
namespace SymfonyDocsBuilder\Release;
44

5+
use Symfony\Contracts\HttpClient\Exception\HttpExceptionInterface;
56
use Symfony\Contracts\HttpClient\HttpClientInterface;
67
use SymfonyDocsBuilder\Phar\Compiler;
8+
use SymfonyDocsBuilder\Release\Exception\ReleaseFailed;
79

810
class Releaser
911
{
@@ -21,7 +23,7 @@ public function __construct(HttpClientInterface $client, Compiler $compiler)
2123
$this->compiler = $compiler;
2224
}
2325

24-
public function createRelease(string $tag, string $name = 'Symfony docs builder %s', string $description = 'Symfony docs builder %s')
26+
public function createRelease(string $tag, string $name = 'Symfony docs builder %s', string $description = 'Symfony docs builder %s'): void
2527
{
2628
if (!preg_match('/^v\d+\.\d+\.\d+$/', $tag)) {
2729
throw new \RuntimeException(sprintf('"%s" is not a valid tag.', $tag));
@@ -53,15 +55,8 @@ private function createDraftRelease(string $tag, string $name, string $descripti
5355
);
5456

5557
return (int) $response->toArray()['id'];
56-
} catch (\RuntimeException $exception) {
57-
if (401 === $exception->getCode()) {
58-
$message = 'Error while trying to create release: Invalid token.';
59-
} else {
60-
$message = 'Error while trying to create release.';
61-
}
62-
63-
// todo: create new exception which can be exploited in ./bin/create_release
64-
throw new \RuntimeException($message, 0, $exception);
58+
} catch (HttpExceptionInterface $exception) {
59+
throw ReleaseFailed::whileCreatingDraft($exception);
6560
}
6661
}
6762

@@ -81,9 +76,8 @@ private function addAssetToRelease(int $releaseId): void
8176
'body' => file_get_contents(__DIR__.'/../../docs.phar'),
8277
]
8378
);
84-
} catch (\RuntimeException $exception) {
85-
$this->deleteRelease($releaseId);
86-
throw new \RuntimeException('Error while adding asset to release.', 0, $exception);
79+
} catch (HttpExceptionInterface $exception) {
80+
$this->deleteRelease($releaseId, ReleaseFailed::whileAttachingAssetToRelease($exception));
8781
}
8882
}
8983

@@ -99,21 +93,22 @@ private function publishRelease(int $releaseId): void
9993
],
10094
]
10195
);
102-
} catch (\RuntimeException $exception) {
103-
$this->deleteRelease($releaseId);
104-
throw new \RuntimeException('Error while publishing release. Maybe the tag name already exists?', 0, $exception);
96+
} catch (HttpExceptionInterface $exception) {
97+
$this->deleteRelease($releaseId, ReleaseFailed::whilePublishingRelease($exception));
10598
}
10699
}
107100

108-
private function deleteRelease(int $releaseId): void
101+
private function deleteRelease(int $releaseId, ReleaseFailed $previous): void
109102
{
110103
try {
111104
$this->client->request(
112105
'DELETE',
113106
sprintf('https://api.github.com/repos/%s/%s/releases/%s', self::GITHUB_USER, self::GITHUB_REPO, $releaseId)
114107
);
115-
} catch (\RuntimeException $exception) {
116-
throw new \RuntimeException('Error while deleting release.', 0, $exception);
108+
} catch (HttpExceptionInterface $exception) {
109+
throw new DeleteReleaseFailed($previous, $exception);
117110
}
111+
112+
throw $previous;
118113
}
119114
}

tests/Release/ReleaserTest.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Symfony\Component\HttpClient\MockHttpClient;
77
use Symfony\Component\HttpClient\Response\MockResponse;
88
use SymfonyDocsBuilder\Phar\Compiler;
9+
use SymfonyDocsBuilder\Release\Exception\ReleaseFailed;
910
use SymfonyDocsBuilder\Release\Releaser;
1011

1112
class ReleaserTest extends TestCase
@@ -63,7 +64,7 @@ public function testCreateReleaseThrowExceptionIf401IsReturned(): void
6364
{
6465
$releaser = new Releaser(new MockHttpClient([new MockResponse('', ['http_code' => 401])]), $this->createMock(Compiler::class));
6566

66-
$this->expectException(\RuntimeException::class);
67+
$this->expectException(ReleaseFailed::class);
6768
$this->expectExceptionMessage('Error while trying to create release: Invalid token.');
6869

6970
$releaser->createRelease('v1.0.0');
@@ -87,7 +88,7 @@ public function testReleaseIsDeletedIfAddAssetReturnsAnError(): void
8788
self::fail(sprintf("Unexpected request:\n- method: %s\n- url: %s", $method, $url));
8889
};
8990

90-
$this->expectException(\RuntimeException::class);
91+
$this->expectException(ReleaseFailed::class);
9192
$this->expectExceptionMessage('Error while adding asset to release.');
9293

9394
$releaser = new Releaser(new MockHttpClient($callback), $this->createMock(Compiler::class));

0 commit comments

Comments
 (0)