preview comments

This commit is contained in:
Andras Bacsai
2023-06-13 15:01:11 +02:00
parent cafe9019c1
commit 8dbe3cfe0c
14 changed files with 157 additions and 23 deletions

View File

@@ -38,7 +38,7 @@ class Previews extends Component
public function load_prs()
{
try {
['rate_limit_remaining' => $rate_limit_remaining, 'data' => $data] = get_from_git_api($this->application->source, "/repos/{$this->application->git_repository}/pulls");
['rate_limit_remaining' => $rate_limit_remaining, 'data' => $data] = git_api(source: $this->application->source, endpoint: "/repos/{$this->application->git_repository}/pulls");
$this->rate_limit_remaining = $rate_limit_remaining;
$this->pull_requests = $data->sortBy('number')->values();
} catch (\Throwable $e) {

View File

@@ -66,7 +66,7 @@ class PublicGitRepository extends Component
$this->get_git_source();
try {
['data' => $data] = get_from_git_api($this->git_source, "/repos/{$this->git_repository}/branches");
['data' => $data] = git_api(source: $this->git_source, endpoint: "/repos/{$this->git_repository}/branches");
$this->branches = collect($data)->pluck('name')->toArray();
} catch (\Throwable $e) {
return general_error_handler(err: $e, that: $this);

View File

@@ -34,7 +34,6 @@ class ApplicationContainerStatusJob implements ShouldQueue, ShouldBeUnique
{
try {
$status = get_container_status(server: $this->application->destination->server, container_id: $this->container_name, throwError: false);
ray('ApplicationContainerStatusJob', $status);
if ($this->pull_request_id) {
$preview = ApplicationPreview::findPreviewByApplicationAndPullId($this->application->id, $this->pull_request_id);
$preview->status = $status;

View File

@@ -92,13 +92,29 @@ class ApplicationDeploymentJob implements ShouldQueue
public function handle(): void
{
try {
ray()->clearScreen();
if ($this->application->deploymentType() === 'source') {
$this->source = $this->application->source->getMorphClass()::where('id', $this->application->source->id)->first();
}
$this->workdir = "/artifacts/{$this->deployment_uuid}";
if ($this->pull_request_id !== 0) {
ray('Deploying pull/' . $this->pull_request_id . '/head for application: ' . $this->application->name);
if ($this->application->fqdn) {
$preview_fqdn = data_get($this->preview, 'fqdn');
$template = $this->application->preview_url_template;
$url = Url::fromString($this->application->fqdn);
$host = $url->getHost();
$schema = $url->getScheme();
$random = new Cuid2(7);
$preview_fqdn = str_replace('{{random}}', $random, $template);
$preview_fqdn = str_replace('{{domain}}', $host, $preview_fqdn);
$preview_fqdn = str_replace('{{pr_id}}', $this->pull_request_id, $preview_fqdn);
$preview_fqdn = "$schema://$preview_fqdn";
$this->preview->fqdn = $preview_fqdn;
$this->preview->save();
}
$this->deploy_pull_request();
} else {
$this->deploy();
@@ -203,6 +219,12 @@ COPY --from=$this->build_image_name /app/{$this->application->publish_directory}
}
private function deploy_pull_request()
{
dispatch(new ApplicationPullRequestUpdateJob(
application_id: $this->application->id,
pull_request_id: $this->pull_request_id,
deployment_uuid: $this->deployment_uuid,
status: 'in_progress'
));
$this->build_image_name = "{$this->application->uuid}:pr-{$this->pull_request_id}-build";
$this->production_image_name = "{$this->application->uuid}:pr-{$this->pull_request_id}";
$this->container_name = generate_container_name($this->application->uuid, $this->pull_request_id);
@@ -282,12 +304,12 @@ COPY --from=$this->build_image_name /app/{$this->application->publish_directory}
]);
$this->activity->save();
}
dispatch(new ApplicationContainerStatusJob(
application: $this->application,
container_name: $this->container_name,
pull_request_id: $this->pull_request_id
dispatch(new ApplicationPullRequestUpdateJob(
application_id: $this->application->id,
pull_request_id: $this->pull_request_id,
deployment_uuid: $this->deployment_uuid,
status: $status
));
queue_next_deployment($this->application);
}
private function execute_in_builder(string $command)

View File

@@ -0,0 +1,82 @@
<?php
namespace App\Jobs;
use App\Enums\ProcessStatus;
use App\Models\Application;
use App\Models\ApplicationPreview;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class ApplicationPullRequestUpdateJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public string $build_logs_url;
public Application $application;
public ApplicationPreview $preview;
public string $body;
public function __construct(
public string $application_id,
public int $pull_request_id,
public string $deployment_uuid,
public string $status
) {
}
public function handle()
{
try {
$this->application = Application::findOrFail($this->application_id);
$this->preview = ApplicationPreview::findPreviewByApplicationAndPullId($this->application->id, $this->pull_request_id);
$this->build_logs_url = base_url() . "/project/{$this->application->environment->project->uuid}/{$this->application->environment->name}/application/{$this->application->uuid}/deployment/{$this->deployment_uuid}";
if ($this->status === ProcessStatus::IN_PROGRESS->value) {
$this->body = "The preview deployment is in progress. 🟡\n\n";
}
if ($this->status === ProcessStatus::FINISHED->value) {
$this->body = "The preview deployment is ready. 🟢\n\n";
if ($this->preview->fqdn) {
$this->body .= "[Open Preview]({$this->preview->fqdn}) | ";
}
}
if ($this->status === ProcessStatus::ERROR->value) {
$this->body = "The preview deployment failed. 🔴\n\n";
}
$this->body .= "[Open Build Logs](" . $this->build_logs_url . ")\n\n\n";
$this->body .= "Last updated at: " . now()->toDateTimeString() . " CET";
ray('Updating comment', $this->body);
if ($this->preview->pull_request_issue_comment_id) {
$this->update_comment();
} else {
$this->create_comment();
}
} catch (\Exception $e) {
ray($e);
throw $e;
}
}
private function update_comment()
{
['data' => $data] = git_api(source: $this->application->source, endpoint: "/repos/{$this->application->git_repository}/issues/comments/{$this->preview->pull_request_issue_comment_id}", method: 'patch', data: [
'body' => $this->body,
], throwError: false);
if (data_get($data, 'message') === 'Not Found') {
ray('Comment not found. Creating new one.');
$this->create_comment();
}
}
private function create_comment()
{
['data' => $data] = git_api(source: $this->application->source, endpoint: "/repos/{$this->application->git_repository}/issues/{$this->pull_request_id}/comments", method: 'post', data: [
'body' => $this->body,
]);
$this->preview->pull_request_issue_comment_id = $data['id'];
$this->preview->save();
}
}

View File

@@ -8,6 +8,7 @@ class ApplicationPreview extends BaseModel
'uuid',
'pull_request_id',
'pull_request_html_url',
'pull_request_issue_comment_id',
'fqdn',
'status',
'application_id',

View File

@@ -19,10 +19,18 @@ class AppServiceProvider extends ServiceProvider
*/
public function boot(): void
{
Http::macro('github', function (string $api_url) {
return Http::withHeaders([
'Accept' => 'application/vnd.github.v3+json'
])->baseUrl($api_url);
Http::macro('github', function (string $api_url, string|null $github_access_token = null) {
if ($github_access_token) {
return Http::withHeaders([
'X-GitHub-Api-Version' => '2022-11-28',
'Accept' => 'application/vnd.github.v3+json',
'Authorization' => "Bearer $github_access_token",
])->baseUrl($api_url);
} else {
return Http::withHeaders([
'Accept' => 'application/vnd.github.v3+json',
])->baseUrl($api_url);
}
});
}
}