coolify/app/Livewire/Project/Application/Previews.php

187 lines
8.0 KiB
PHP
Raw Normal View History

2023-05-16 13:11:05 +02:00
<?php
2023-12-07 19:06:32 +01:00
namespace App\Livewire\Project\Application;
2023-05-16 13:11:05 +02:00
use App\Actions\Docker\GetContainersStatus;
2023-05-16 13:11:05 +02:00
use App\Models\Application;
2023-05-30 15:52:17 +02:00
use App\Models\ApplicationPreview;
use Illuminate\Support\Collection;
2023-05-16 13:11:05 +02:00
use Livewire\Component;
use Spatie\Url\Url;
2023-05-30 15:52:17 +02:00
use Visus\Cuid2\Cuid2;
2023-05-16 13:11:05 +02:00
class Previews extends Component
{
public Application $application;
2023-05-30 15:52:17 +02:00
public string $deployment_uuid;
public array $parameters;
public Collection $pull_requests;
public int $rate_limit_remaining;
protected $rules = [
'application.previews.*.fqdn' => 'string|nullable',
];
2023-05-30 15:52:17 +02:00
public function mount()
{
$this->pull_requests = collect();
$this->parameters = get_route_parameters();
2023-05-30 15:52:17 +02:00
}
2023-05-30 15:52:17 +02:00
public function load_prs()
{
2023-06-02 12:34:45 +02:00
try {
['rate_limit_remaining' => $rate_limit_remaining, 'data' => $data] = githubApi(source: $this->application->source, endpoint: "/repos/{$this->application->git_repository}/pulls");
2023-06-02 12:34:45 +02:00
$this->rate_limit_remaining = $rate_limit_remaining;
$this->pull_requests = $data->sortBy('number')->values();
2023-06-09 15:55:21 +02:00
} catch (\Throwable $e) {
2023-06-02 12:34:45 +02:00
$this->rate_limit_remaining = 0;
return handleError($e, $this);
2023-06-02 12:34:45 +02:00
}
2023-05-30 15:52:17 +02:00
}
public function save_preview($preview_id)
{
try {
$success = true;
$preview = $this->application->previews->find($preview_id);
if (isset($preview->fqdn)) {
$preview->fqdn = str($preview->fqdn)->replaceEnd(',', '')->trim();
$preview->fqdn = str($preview->fqdn)->replaceStart(',', '')->trim();
$preview->fqdn = str($preview->fqdn)->trim()->lower();
if (!validate_dns_entry($preview->fqdn, $this->application->destination->server)) {
$this->dispatch('error', "Validating DNS failed.", "Make sure you have added the DNS records correctly.<br><br>$preview->fqdn->{$this->application->destination->server->ip}<br><br>Check this <a target='_blank' class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/dns-configuration'>documentation</a> for further help.");
$success = false;
}
check_domain_usage(resource: $this->application, domain: $preview->fqdn);
}
if (!$preview) {
throw new \Exception('Preview not found');
}
$success && $preview->save();
$success && $this->dispatch('success', 'Preview saved.<br><br>Do not forget to redeploy the preview to apply the changes.');
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
public function generate_preview($preview_id)
{
$preview = $this->application->previews->find($preview_id);
if (!$preview) {
$this->dispatch('error', 'Preview not found.');
return;
}
$fqdn = generateFqdn($this->application->destination->server, $this->application->uuid);
$url = Url::fromString($fqdn);
$template = $this->application->preview_url_template;
$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}}', $preview_id, $preview_fqdn);
$preview_fqdn = "$schema://$preview_fqdn";
$preview->fqdn = $preview_fqdn;
$preview->save();
$this->dispatch('success', 'Domain generated.');
}
public function add(int $pull_request_id, string|null $pull_request_html_url = null)
{
try {
$this->setDeploymentUuid();
$found = ApplicationPreview::where('application_id', $this->application->id)->where('pull_request_id', $pull_request_id)->first();
if (!$found && !is_null($pull_request_html_url)) {
ApplicationPreview::create([
'application_id' => $this->application->id,
'pull_request_id' => $pull_request_id,
'pull_request_html_url' => $pull_request_html_url
]);
}
$this->application->generate_preview_fqdn($pull_request_id);
$this->application->refresh();
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
2023-05-31 14:57:42 +02:00
public function deploy(int $pull_request_id, string|null $pull_request_html_url = null)
2023-05-30 15:52:17 +02:00
{
try {
2023-06-15 09:15:41 +02:00
$this->setDeploymentUuid();
2023-05-30 17:00:11 +02:00
$found = ApplicationPreview::where('application_id', $this->application->id)->where('pull_request_id', $pull_request_id)->first();
2023-05-31 14:57:42 +02:00
if (!$found && !is_null($pull_request_html_url)) {
2023-05-30 17:00:11 +02:00
ApplicationPreview::create([
'application_id' => $this->application->id,
'pull_request_id' => $pull_request_id,
2023-05-31 10:19:29 +02:00
'pull_request_html_url' => $pull_request_html_url
2023-05-30 17:00:11 +02:00
]);
}
2023-05-30 15:52:17 +02:00
queue_application_deployment(
2024-01-27 18:44:40 +01:00
application: $this->application,
2023-05-30 15:52:17 +02:00
deployment_uuid: $this->deployment_uuid,
force_rebuild: false,
2023-05-30 15:52:17 +02:00
pull_request_id: $pull_request_id,
git_type: $found->git_type ?? null,
2023-05-30 15:52:17 +02:00
);
2024-01-07 16:23:41 +01:00
return redirect()->route('project.application.deployment.show', [
2023-05-31 10:19:29 +02:00
'project_uuid' => $this->parameters['project_uuid'],
'application_uuid' => $this->parameters['application_uuid'],
2023-05-31 14:42:37 +02:00
'deployment_uuid' => $this->deployment_uuid,
2023-05-31 10:19:29 +02:00
'environment_name' => $this->parameters['environment_name'],
2023-12-27 16:45:01 +01:00
]);
2023-06-09 15:55:21 +02:00
} catch (\Throwable $e) {
return handleError($e, $this);
2023-05-30 15:52:17 +02:00
}
}
protected function setDeploymentUuid()
{
$this->deployment_uuid = new Cuid2(7);
$this->parameters['deployment_uuid'] = $this->deployment_uuid;
}
2023-05-30 15:52:17 +02:00
public function stop(int $pull_request_id)
{
try {
if ($this->application->destination->server->isSwarm()) {
instant_remote_process(["docker stack rm {$this->application->uuid}-{$pull_request_id}"], $this->application->destination->server);
} else {
$containers = getCurrentApplicationContainerStatus($this->application->destination->server, $this->application->id, $pull_request_id);
foreach ($containers as $container) {
$name = str_replace('/', '', $container['Names']);
instant_remote_process(["docker rm -f $name"], $this->application->destination->server, throwError: false);
}
}
GetContainersStatus::dispatchSync($this->application->destination->server);
$this->application->refresh();
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
public function delete(int $pull_request_id)
2023-05-30 15:52:17 +02:00
{
try {
2023-12-18 14:01:25 +01:00
if ($this->application->destination->server->isSwarm()) {
instant_remote_process(["docker stack rm {$this->application->uuid}-{$pull_request_id}"], $this->application->destination->server);
} else {
$containers = getCurrentApplicationContainerStatus($this->application->destination->server, $this->application->id, $pull_request_id);
foreach ($containers as $container) {
$name = str_replace('/', '', $container['Names']);
instant_remote_process(["docker rm -f $name"], $this->application->destination->server, throwError: false);
}
}
2023-11-27 15:25:15 +01:00
ApplicationPreview::where('application_id', $this->application->id)->where('pull_request_id', $pull_request_id)->first()->delete();
2023-05-30 17:05:27 +02:00
$this->application->refresh();
2023-06-09 15:55:21 +02:00
} catch (\Throwable $e) {
return handleError($e, $this);
2023-05-30 15:52:17 +02:00
}
}
2023-06-16 21:16:30 +02:00
public function previewRefresh()
{
$this->application->previews->each(function ($preview) {
$preview->refresh();
});
}
2023-05-16 13:11:05 +02:00
}