lasthourcloud/app/Jobs/ApplicationDeploymentJobNew.php
Andras Bacsai 55d5b1e8da wip
2023-06-30 15:57:40 +02:00

182 lines
7.0 KiB
PHP

<?php
namespace App\Jobs;
use App\Enums\ApplicationDeploymentStatus;
use App\Models\Application;
use App\Models\ApplicationDeploymentQueue;
use App\Models\ApplicationPreview;
use App\Models\GithubApp;
use App\Models\GitlabApp;
use App\Models\Server;
use App\Models\StandaloneDocker;
use App\Models\SwarmDocker;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Spatie\Url\Url;
use Throwable;
use Visus\Cuid2\Cuid2;
class ApplicationDeploymentJobNew implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public static int $batch_counter = 0;
private int $application_deployment_queue_id;
private ApplicationDeploymentQueue $application_deployment_queue;
private Application $application;
private string $deployment_uuid;
private int $pull_request_id;
private string $commit;
private bool $force_rebuild;
private GithubApp|GitlabApp $source;
private StandaloneDocker|SwarmDocker $destination;
private Server $server;
private string $private_key_location;
private ApplicationPreview|null $preview = null;
private string $container_name;
private string $workdir;
private bool $is_debug_enabled;
public function __construct(int $application_deployment_queue_id)
{
$this->application_deployment_queue = ApplicationDeploymentQueue::find($application_deployment_queue_id);
$this->application = Application::find($this->application_deployment_queue->application_id);
$this->application_deployment_queue_id = $application_deployment_queue_id;
$this->deployment_uuid = $this->application_deployment_queue->deployment_uuid;
$this->pull_request_id = $this->application_deployment_queue->pull_request_id;
$this->commit = $this->application_deployment_queue->commit;
$this->force_rebuild = $this->application_deployment_queue->force_rebuild;
$this->source = $this->application->source->getMorphClass()::where('id', $this->application->source->id)->first();
$this->destination = $this->application->destination->getMorphClass()::where('id', $this->application->destination->id)->first();
$this->server = $this->destination->server;
$this->private_key_location = save_private_key_for_server($this->server);
$this->workdir = "/artifacts/{$this->deployment_uuid}";
$this->is_debug_enabled = $this->application->settings->is_debug_enabled;
$this->container_name = generate_container_name($this->application->uuid);
$this->private_key_location = save_private_key_for_server($this->server);
// Set preview fqdn
if ($this->pull_request_id !== 0) {
$this->preview = ApplicationPreview::findPreviewByApplicationAndPullId($this->application->id, $this->pull_request_id);
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();
}
}
}
public function handle(): void
{
$this->application_deployment_queue->update([
'status' => ApplicationDeploymentStatus::IN_PROGRESS->value,
]);
try {
if ($this->pull_request_id !== 0) {
// $this->deploy_pull_request();
} else {
$this->deploy();
}
} catch (\Exception $e) {
// $this->execute_now([
// "echo '\nOops something is not okay, are you okay? 😢'",
// "echo '\n\n{$e->getMessage()}'",
// ]);
$this->fail($e->getMessage());
} finally {
// if (isset($this->docker_compose)) {
// Storage::disk('deployments')->put(Str::kebab($this->application->name) . '/docker-compose.yml', $this->docker_compose);
// }
// execute_remote_command(
// commands: [
// "docker rm -f {$this->deployment_uuid} >/dev/null 2>&1"
// ],
// server: $this->server,
// queue: $this->application_deployment_queue,
// hide_from_output: true,
// );
}
}
public function failed(Throwable $exception): void
{
ray($exception);
$this->next(ApplicationDeploymentStatus::FAILED->value);
}
private function execute_in_builder(string $command)
{
return "docker exec {$this->deployment_uuid} bash -c '{$command} |& tee -a /proc/1/fd/1'";
}
private function deploy()
{
execute_remote_command(
commands: [
"echo -n 'Pulling latest version of the builder image (ghcr.io/coollabsio/coolify-builder).'",
],
server: $this->server,
queue: $this->application_deployment_queue,
);
execute_remote_command(
commands: [
"docker run --pull=always -d --name {$this->deployment_uuid} --rm -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/coollabsio/coolify-builder",
],
server: $this->server,
queue: $this->application_deployment_queue,
show_in_output: false,
);
execute_remote_command(
commands: [
"echo 'Done.'",
],
server: $this->server,
queue: $this->application_deployment_queue,
);
execute_remote_command(
commands: [
$this->execute_in_builder("mkdir -p {$this->workdir}")
],
server: $this->server,
queue: $this->application_deployment_queue,
);
execute_remote_command(
commands: [
"echos hello"
],
server: $this->server,
queue: $this->application_deployment_queue,
);
$this->next(ApplicationDeploymentStatus::FINISHED->value);
}
private function next(string $status)
{
// If the deployment is cancelled by the user, don't update the status
if ($this->application_deployment_queue->status !== ApplicationDeploymentStatus::CANCELLED_BY_USER->value) {
$this->application_deployment_queue->update([
'status' => $status,
]);
}
queue_next_deployment($this->application);
}
}