-
Notifications
You must be signed in to change notification settings - Fork 84
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #334 from tighten/tm/buggregator
Adds Buggregator as a tool
- Loading branch information
Showing
3 changed files
with
158 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
<?php | ||
|
||
namespace App\Services; | ||
|
||
use App\Shell\GitHubDockerTags; | ||
|
||
class Buggregator extends BaseService | ||
{ | ||
protected static $category = Category::TOOLS; | ||
|
||
protected $dockerTagsClass = GitHubDockerTags::class; | ||
protected $organization = 'ghcr.io'; | ||
protected $imageName = 'buggregator/server'; | ||
protected $tag = 'latest'; | ||
protected $defaultPort = 8000; | ||
protected $prompts = [ | ||
[ | ||
'shortname' => 'smtp_port', | ||
'prompt' => 'What is the SMTP port?', | ||
'default' => '1025', | ||
], | ||
[ | ||
'shortname' => 'var_dumper_port', | ||
'prompt' => 'What is the VarDumper server port?', | ||
'default' => '9912', | ||
], | ||
[ | ||
'shortname' => 'monolog_port', | ||
'prompt' => 'What is the Monolog port?', | ||
'default' => '9913', | ||
], | ||
[ | ||
'shortname' => 'network_alias', | ||
'prompt' => 'What network alias to you want to assign to this container? This alias can be used by other services on the same network.', | ||
'default' => 'buggregator', | ||
], | ||
]; | ||
|
||
protected $dockerRunTemplate = '-p "${:port}":8000 \ | ||
-p "${:smtp_port}":1025 \ | ||
-p "${:var_dumper_port}":9912 \ | ||
-p "${:monolog_port}":9913 \ | ||
--network-alias "${:network_alias}" \ | ||
"${:organization}"/"${:image_name}":"${:tag}"'; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
<?php | ||
|
||
namespace App\Shell; | ||
|
||
use Illuminate\Support\Collection; | ||
use Psr\Http\Message\StreamInterface; | ||
use RuntimeException; | ||
|
||
class GitHubDockerTags extends DockerTags | ||
{ | ||
public function getTags(): Collection | ||
{ | ||
return collect(json_decode($this->getTagsResponse(), true)['tags']); | ||
} | ||
|
||
public function getLatestTag(): string | ||
{ | ||
return $this->getTags()->first(); | ||
} | ||
|
||
protected function getTagsResponse(): StreamInterface | ||
{ | ||
$token = $this->getToken(); | ||
|
||
return $this->guzzle | ||
->get($this->buildTagsUrl(), [ | ||
'headers' => [ | ||
'Authorization' => "Bearer {$token}", | ||
], | ||
]) | ||
->getBody(); | ||
} | ||
|
||
protected function getToken(): string | ||
{ | ||
$image = $this->service->imageName(); | ||
|
||
$response = $this->guzzle->get('https://ghcr.io/token?' . http_build_query([ | ||
'scope' => "repository:{$image}:pull", | ||
]), [ | ||
'http_errors' => false, | ||
]); | ||
|
||
if ($response->getStatusCode() !== 200) { | ||
throw new RuntimeException("Something went wrong getting the Token from GitHub's registry."); | ||
} | ||
|
||
return json_decode($response->getBody(), true)['token']; | ||
} | ||
|
||
protected function tagsUrlTemplate(): string | ||
{ | ||
return 'https://%s/v2/%s/tags/list'; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
<?php | ||
|
||
namespace Tests\Feature; | ||
|
||
use App\Services\Buggregator; | ||
use App\Shell\GitHubDockerTags; | ||
use GuzzleHttp\Client; | ||
use GuzzleHttp\Handler\MockHandler; | ||
use GuzzleHttp\HandlerStack; | ||
use GuzzleHttp\Psr7\Response; | ||
use Mockery as M; | ||
use RuntimeException; | ||
use Tests\TestCase; | ||
|
||
class GitHubTagsTest extends TestCase | ||
{ | ||
/** @test */ | ||
function it_fetches_latest_tag() | ||
{ | ||
$handlerStack = HandlerStack::create($this->mockImagesResponseHandler()); | ||
$client = new Client(['handler' => $handlerStack]); | ||
|
||
/** @var GitHubDockerTags $dockerTags */ | ||
$dockerTags = M::mock(GitHubDockerTags::class, [$client, app(Buggregator::class)])->makePartial(); | ||
|
||
$this->assertEquals('latest', $dockerTags->getLatestTag()); | ||
} | ||
|
||
/** @test */ | ||
function it_throws_exception_when_token_request_fails() | ||
{ | ||
$handlerStack = HandlerStack::create($this->mockImagesResponseHandler(false)); | ||
$client = new Client(['handler' => $handlerStack]); | ||
|
||
/** @var GitHubDockerTags $dockerTags */ | ||
$dockerTags = M::mock(GitHubDockerTags::class, [$client, app(Buggregator::class)])->makePartial(); | ||
|
||
$this->expectException(RuntimeException::class); | ||
|
||
$dockerTags->getLatestTag(); | ||
} | ||
|
||
private function mockImagesResponseHandler($tokenWorks = true) | ||
{ | ||
return new MockHandler([ | ||
new Response($tokenWorks ? 200 : 400, [], json_encode([ | ||
'token' => 'fake-token', | ||
])), | ||
new Response(200, [], json_encode([ | ||
'tags' => [ | ||
'latest', | ||
'1.0.0', | ||
'1.0.0.rc-1', | ||
], | ||
])), | ||
]); | ||
} | ||
} |