feat: restart application
fix: a few things in application deployment job
This commit is contained in:
		@@ -65,4 +65,18 @@ class Heading extends Component
 | 
				
			|||||||
        $this->application->save();
 | 
					        $this->application->save();
 | 
				
			||||||
        $this->application->refresh();
 | 
					        $this->application->refresh();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    public function restart() {
 | 
				
			||||||
 | 
					        $this->setDeploymentUuid();
 | 
				
			||||||
 | 
					        queue_application_deployment(
 | 
				
			||||||
 | 
					            application_id: $this->application->id,
 | 
				
			||||||
 | 
					            deployment_uuid: $this->deploymentUuid,
 | 
				
			||||||
 | 
					            restart_only: true,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        return redirect()->route('project.application.deployment', [
 | 
				
			||||||
 | 
					            'project_uuid' => $this->parameters['project_uuid'],
 | 
				
			||||||
 | 
					            'application_uuid' => $this->parameters['application_uuid'],
 | 
				
			||||||
 | 
					            'deployment_uuid' => $this->deploymentUuid,
 | 
				
			||||||
 | 
					            'environment_name' => $this->parameters['environment_name'],
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -44,6 +44,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
 | 
				
			|||||||
    private int $pull_request_id;
 | 
					    private int $pull_request_id;
 | 
				
			||||||
    private string $commit;
 | 
					    private string $commit;
 | 
				
			||||||
    private bool $force_rebuild;
 | 
					    private bool $force_rebuild;
 | 
				
			||||||
 | 
					    private bool $restart_only;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private ?string $dockerImage = null;
 | 
					    private ?string $dockerImage = null;
 | 
				
			||||||
    private ?string $dockerImageTag = null;
 | 
					    private ?string $dockerImageTag = null;
 | 
				
			||||||
@@ -94,6 +95,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
 | 
				
			|||||||
        $this->pull_request_id = $this->application_deployment_queue->pull_request_id;
 | 
					        $this->pull_request_id = $this->application_deployment_queue->pull_request_id;
 | 
				
			||||||
        $this->commit = $this->application_deployment_queue->commit;
 | 
					        $this->commit = $this->application_deployment_queue->commit;
 | 
				
			||||||
        $this->force_rebuild = $this->application_deployment_queue->force_rebuild;
 | 
					        $this->force_rebuild = $this->application_deployment_queue->force_rebuild;
 | 
				
			||||||
 | 
					        $this->restart_only = $this->application_deployment_queue->restart_only;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $source = data_get($this->application, 'source');
 | 
					        $source = data_get($this->application, 'source');
 | 
				
			||||||
        if ($source) {
 | 
					        if ($source) {
 | 
				
			||||||
@@ -182,7 +184,9 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
 | 
				
			|||||||
            $this->application->git_repository = "$gitHost:$gitRepo";
 | 
					            $this->application->git_repository = "$gitHost:$gitRepo";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            if ($this->application->dockerfile) {
 | 
					            if ($this->restart_only) {
 | 
				
			||||||
 | 
					                $this->just_restart();
 | 
				
			||||||
 | 
					            } else if ($this->application->dockerfile) {
 | 
				
			||||||
                $this->deploy_simple_dockerfile();
 | 
					                $this->deploy_simple_dockerfile();
 | 
				
			||||||
            } else if ($this->application->build_pack === 'dockerimage') {
 | 
					            } else if ($this->application->build_pack === 'dockerimage') {
 | 
				
			||||||
                $this->deploy_dockerimage_buildpack();
 | 
					                $this->deploy_dockerimage_buildpack();
 | 
				
			||||||
@@ -264,6 +268,49 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
 | 
				
			|||||||
    //         [executeInDocker($this->deployment_uuid, "docker compose --project-directory {$this->workdir} up -d"), "hidden" => true],
 | 
					    //         [executeInDocker($this->deployment_uuid, "docker compose --project-directory {$this->workdir} up -d"), "hidden" => true],
 | 
				
			||||||
    //     );
 | 
					    //     );
 | 
				
			||||||
    // }
 | 
					    // }
 | 
				
			||||||
 | 
					    private function generate_image_names()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if ($this->application->dockerfile) {
 | 
				
			||||||
 | 
					            $this->build_image_name = Str::lower("{$this->application->git_repository}:build");
 | 
				
			||||||
 | 
					            $this->production_image_name = Str::lower("{$this->application->uuid}:latest");
 | 
				
			||||||
 | 
					        } else if ($this->application->build_pack === 'dockerimage') {
 | 
				
			||||||
 | 
					            $this->production_image_name = Str::lower("{$this->dockerImage}:{$this->dockerImageTag}");
 | 
				
			||||||
 | 
					        } else if ($this->pull_request_id !== 0) {
 | 
				
			||||||
 | 
					            $this->build_image_name = Str::lower("{$this->application->uuid}:pr-{$this->pull_request_id}-build");
 | 
				
			||||||
 | 
					            $this->production_image_name = Str::lower("{$this->application->uuid}:pr-{$this->pull_request_id}");
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            $tag = Str::of("{$this->commit}-{$this->application->id}-{$this->pull_request_id}");
 | 
				
			||||||
 | 
					            if (strlen($tag) > 128) {
 | 
				
			||||||
 | 
					                $tag = $tag->substr(0, 128);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            $this->build_image_name = Str::lower("{$this->application->git_repository}:{$tag}-build");
 | 
				
			||||||
 | 
					            $this->production_image_name = Str::lower("{$this->application->uuid}:{$tag}");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        ray('Build Image Name: ' . $this->build_image_name . ' & Production Image Name: ' . $this->production_image_name)->green();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    private function just_restart()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->execute_remote_command(
 | 
				
			||||||
 | 
					            [
 | 
				
			||||||
 | 
					                "echo 'Starting deployment of {$this->application->git_repository}:{$this->application->git_branch}.'"
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        $this->prepare_builder_image();
 | 
				
			||||||
 | 
					        $this->check_git_if_build_needed();
 | 
				
			||||||
 | 
					        $this->set_base_dir();
 | 
				
			||||||
 | 
					        $this->generate_image_names();
 | 
				
			||||||
 | 
					        $this->execute_remote_command([
 | 
				
			||||||
 | 
					            "docker images -q {$this->production_image_name} 2>/dev/null", "hidden" => true, "save" => "local_image_found"
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					        if (str($this->saved_outputs->get('local_image_found'))->isNotEmpty()) {
 | 
				
			||||||
 | 
					            $this->generate_compose_file();
 | 
				
			||||||
 | 
					            $this->rolling_update();
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        $this->execute_remote_command([
 | 
				
			||||||
 | 
					            "echo 'Cannot find image {$this->production_image_name} locally. Please redeploy the application.'",
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    private function save_environment_variables()
 | 
					    private function save_environment_variables()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $envs = collect([]);
 | 
					        $envs = collect([]);
 | 
				
			||||||
@@ -291,9 +338,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
 | 
				
			|||||||
                executeInDocker($this->deployment_uuid, "echo '$dockerfile_base64' | base64 -d > $this->workdir/Dockerfile")
 | 
					                executeInDocker($this->deployment_uuid, "echo '$dockerfile_base64' | base64 -d > $this->workdir/Dockerfile")
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        $this->build_image_name = Str::lower("{$this->application->git_repository}:build");
 | 
					        $this->generate_image_names();
 | 
				
			||||||
        $this->production_image_name = Str::lower("{$this->application->uuid}:latest");
 | 
					 | 
				
			||||||
        // ray('Build Image Name: ' . $this->build_image_name . ' & Production Image Name: ' . $this->production_image_name)->green();
 | 
					 | 
				
			||||||
        $this->generate_compose_file();
 | 
					        $this->generate_compose_file();
 | 
				
			||||||
        $this->generate_build_env_variables();
 | 
					        $this->generate_build_env_variables();
 | 
				
			||||||
        $this->add_build_env_variables_to_dockerfile();
 | 
					        $this->add_build_env_variables_to_dockerfile();
 | 
				
			||||||
@@ -311,7 +356,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
 | 
				
			|||||||
                "echo 'Starting deployment of {$this->dockerImage}:{$this->dockerImageTag}.'"
 | 
					                "echo 'Starting deployment of {$this->dockerImage}:{$this->dockerImageTag}.'"
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        $this->production_image_name = Str::lower("{$this->dockerImage}:{$this->dockerImageTag}");
 | 
					        $this->generate_image_names();
 | 
				
			||||||
        $this->prepare_builder_image();
 | 
					        $this->prepare_builder_image();
 | 
				
			||||||
        $this->generate_compose_file();
 | 
					        $this->generate_compose_file();
 | 
				
			||||||
        $this->rolling_update();
 | 
					        $this->rolling_update();
 | 
				
			||||||
@@ -330,14 +375,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
 | 
				
			|||||||
        $this->prepare_builder_image();
 | 
					        $this->prepare_builder_image();
 | 
				
			||||||
        $this->clone_repository();
 | 
					        $this->clone_repository();
 | 
				
			||||||
        $this->set_base_dir();
 | 
					        $this->set_base_dir();
 | 
				
			||||||
        $tag = Str::of("{$this->commit}-{$this->application->id}-{$this->pull_request_id}");
 | 
					        $this->generate_image_names();
 | 
				
			||||||
        if (strlen($tag) > 128) {
 | 
					 | 
				
			||||||
            $tag = $tag->substr(0, 128);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $this->build_image_name = Str::lower("{$this->application->git_repository}:{$tag}-build");
 | 
					 | 
				
			||||||
        $this->production_image_name = Str::lower("{$this->application->uuid}:{$tag}");
 | 
					 | 
				
			||||||
        // ray('Build Image Name: ' . $this->build_image_name . ' & Production Image Name: ' . $this->production_image_name)->green();
 | 
					 | 
				
			||||||
        $this->cleanup_git();
 | 
					        $this->cleanup_git();
 | 
				
			||||||
        $this->generate_compose_file();
 | 
					        $this->generate_compose_file();
 | 
				
			||||||
        $this->generate_build_env_variables();
 | 
					        $this->generate_build_env_variables();
 | 
				
			||||||
@@ -355,15 +393,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
 | 
				
			|||||||
        $this->prepare_builder_image();
 | 
					        $this->prepare_builder_image();
 | 
				
			||||||
        $this->check_git_if_build_needed();
 | 
					        $this->check_git_if_build_needed();
 | 
				
			||||||
        $this->set_base_dir();
 | 
					        $this->set_base_dir();
 | 
				
			||||||
        $tag = Str::of("{$this->commit}-{$this->application->id}-{$this->pull_request_id}");
 | 
					        $this->generate_image_names();
 | 
				
			||||||
        if (strlen($tag) > 128) {
 | 
					 | 
				
			||||||
            $tag = $tag->substr(0, 128);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $this->build_image_name = Str::lower("{$this->application->git_repository}:{$tag}-build");
 | 
					 | 
				
			||||||
        $this->production_image_name = Str::lower("{$this->application->uuid}:{$tag}");
 | 
					 | 
				
			||||||
        // ray('Build Image Name: ' . $this->build_image_name . ' & Production Image Name: ' . $this->production_image_name)->green();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!$this->force_rebuild) {
 | 
					        if (!$this->force_rebuild) {
 | 
				
			||||||
            $this->execute_remote_command([
 | 
					            $this->execute_remote_command([
 | 
				
			||||||
                "docker images -q {$this->production_image_name} 2>/dev/null", "hidden" => true, "save" => "local_image_found"
 | 
					                "docker images -q {$this->production_image_name} 2>/dev/null", "hidden" => true, "save" => "local_image_found"
 | 
				
			||||||
@@ -396,7 +426,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        if (count($this->application->ports_mappings_array) > 0) {
 | 
					        if (count($this->application->ports_mappings_array) > 0) {
 | 
				
			||||||
            $this->execute_remote_command(
 | 
					            $this->execute_remote_command(
 | 
				
			||||||
                ["echo -n 'Application has ports mapped to the host system, rolling update is not supported. Stopping current container.'"],
 | 
					                ["echo -n 'Application has ports mapped to the host system, rolling update is not supported.'"],
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
            $this->stop_running_container(force: true);
 | 
					            $this->stop_running_container(force: true);
 | 
				
			||||||
            $this->start_by_compose_file();
 | 
					            $this->start_by_compose_file();
 | 
				
			||||||
@@ -545,8 +575,10 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
 | 
				
			|||||||
            );
 | 
					            );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($this->saved_outputs->get('git_commit_sha')) {
 | 
				
			||||||
            $this->commit = $this->saved_outputs->get('git_commit_sha')->before("\t");
 | 
					            $this->commit = $this->saved_outputs->get('git_commit_sha')->before("\t");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    private function clone_repository()
 | 
					    private function clone_repository()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $importCommands = $this->generate_git_import_commands();
 | 
					        $importCommands = $this->generate_git_import_commands();
 | 
				
			||||||
@@ -596,7 +628,11 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        if ($this->application->deploymentType() === 'deploy_key') {
 | 
					        if ($this->application->deploymentType() === 'deploy_key') {
 | 
				
			||||||
            $this->fullRepoUrl = $this->application->git_repository;
 | 
					            $this->fullRepoUrl = $this->application->git_repository;
 | 
				
			||||||
            $private_key = base64_encode($this->application->private_key->private_key);
 | 
					            $private_key = data_get($this->application, 'private_key.private_key');
 | 
				
			||||||
 | 
					            if (is_null($private_key)) {
 | 
				
			||||||
 | 
					                throw new Exception('Private key not found. Please add a private key to the application and try again.');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            $private_key = base64_encode($private_key);
 | 
				
			||||||
            $git_clone_command = "GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$this->customPort} -o Port={$this->customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" {$git_clone_command} {$this->application->git_repository} {$this->basedir}";
 | 
					            $git_clone_command = "GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$this->customPort} -o Port={$this->customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" {$git_clone_command} {$this->application->git_repository} {$this->basedir}";
 | 
				
			||||||
            $git_clone_command = $this->set_git_import_settings($git_clone_command);
 | 
					            $git_clone_command = $this->set_git_import_settings($git_clone_command);
 | 
				
			||||||
            $commands = collect([
 | 
					            $commands = collect([
 | 
				
			||||||
@@ -907,12 +943,12 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
 | 
				
			|||||||
            if ($this->newVersionIsHealthy || $force) {
 | 
					            if ($this->newVersionIsHealthy || $force) {
 | 
				
			||||||
                $this->execute_remote_command(
 | 
					                $this->execute_remote_command(
 | 
				
			||||||
                    ["echo -n 'Removing old version of your application.'"],
 | 
					                    ["echo -n 'Removing old version of your application.'"],
 | 
				
			||||||
                    [executeInDocker($this->deployment_uuid, "docker rm -f $this->currently_running_container_name >/dev/null 2>&1"), "hidden" => true],
 | 
					                    [executeInDocker($this->deployment_uuid, "docker rm -f $this->currently_running_container_name >/dev/null 2>&1"), "hidden" => true, "ignore_errors" => true],
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                $this->execute_remote_command(
 | 
					                $this->execute_remote_command(
 | 
				
			||||||
                    ["echo -n 'New version is not healthy, rolling back to the old version.'"],
 | 
					                    ["echo -n 'New version is not healthy, rolling back to the old version.'"],
 | 
				
			||||||
                    [executeInDocker($this->deployment_uuid, "docker rm -f $this->container_name >/dev/null 2>&1"), "hidden" => true],
 | 
					                    [executeInDocker($this->deployment_uuid, "docker rm -f $this->container_name >/dev/null 2>&1"), "hidden" => true, "ignore_errors" => true],
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,7 @@ use App\Jobs\ApplicationDeploymentJob;
 | 
				
			|||||||
use App\Models\Application;
 | 
					use App\Models\Application;
 | 
				
			||||||
use App\Models\ApplicationDeploymentQueue;
 | 
					use App\Models\ApplicationDeploymentQueue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function queue_application_deployment(int $application_id, string $deployment_uuid, int | null $pull_request_id = 0, string $commit = 'HEAD', bool $force_rebuild = false, bool $is_webhook = false)
 | 
					function queue_application_deployment(int $application_id, string $deployment_uuid, int | null $pull_request_id = 0, string $commit = 'HEAD', bool $force_rebuild = false, bool $is_webhook = false, bool $restart_only = false)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    $deployment = ApplicationDeploymentQueue::create([
 | 
					    $deployment = ApplicationDeploymentQueue::create([
 | 
				
			||||||
        'application_id' => $application_id,
 | 
					        'application_id' => $application_id,
 | 
				
			||||||
@@ -12,6 +12,7 @@ function queue_application_deployment(int $application_id, string $deployment_uu
 | 
				
			|||||||
        'pull_request_id' => $pull_request_id,
 | 
					        'pull_request_id' => $pull_request_id,
 | 
				
			||||||
        'force_rebuild' => $force_rebuild,
 | 
					        'force_rebuild' => $force_rebuild,
 | 
				
			||||||
        'is_webhook' => $is_webhook,
 | 
					        'is_webhook' => $is_webhook,
 | 
				
			||||||
 | 
					        'restart_only' => $restart_only,
 | 
				
			||||||
        'commit' => $commit,
 | 
					        'commit' => $commit,
 | 
				
			||||||
    ]);
 | 
					    ]);
 | 
				
			||||||
    $queued_deployments = ApplicationDeploymentQueue::where('application_id', $application_id)->where('status', 'queued')->get()->sortByDesc('created_at');
 | 
					    $queued_deployments = ApplicationDeploymentQueue::where('application_id', $application_id)->where('status', 'queued')->get()->sortByDesc('created_at');
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Illuminate\Database\Migrations\Migration;
 | 
				
			||||||
 | 
					use Illuminate\Database\Schema\Blueprint;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\Schema;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					return new class extends Migration
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Run the migrations.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function up(): void
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Schema::table('application_deployment_queues', function (Blueprint $table) {
 | 
				
			||||||
 | 
					            $table->boolean('restart_only')->default(false);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Reverse the migrations.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function down(): void
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Schema::table('application_deployment_queues', function (Blueprint $table) {
 | 
				
			||||||
 | 
					            $table->dropColumn('restart_only');
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -17,7 +17,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @if ($application->status !== 'exited')
 | 
					    @if ($application->status !== 'exited')
 | 
				
			||||||
        <button title="With rolling update if possible" wire:click='deploy' class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400">
 | 
					        <button title="With rolling update if possible" wire:click='deploy' class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400">
 | 
				
			||||||
            <svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-warning" viewBox="0 0 24 24" stroke-width="2"
 | 
					            <svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-orange-400" viewBox="0 0 24 24" stroke-width="2"
 | 
				
			||||||
                stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
 | 
					                stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
 | 
				
			||||||
                <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
 | 
					                <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
 | 
				
			||||||
                <path
 | 
					                <path
 | 
				
			||||||
@@ -27,6 +27,15 @@
 | 
				
			|||||||
            </svg>
 | 
					            </svg>
 | 
				
			||||||
            Redeploy
 | 
					            Redeploy
 | 
				
			||||||
        </button>
 | 
					        </button>
 | 
				
			||||||
 | 
					        <button title="Restart without rebuilding" wire:click='restart' class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400">
 | 
				
			||||||
 | 
					            <svg class="w-5 h-5 text-warning" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
 | 
				
			||||||
 | 
					                <g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
 | 
				
			||||||
 | 
					                    <path d="M19.933 13.041a8 8 0 1 1-9.925-8.788c3.899-1 7.935 1.007 9.425 4.747"/>
 | 
				
			||||||
 | 
					                    <path d="M20 4v5h-5"/>
 | 
				
			||||||
 | 
					                </g>
 | 
				
			||||||
 | 
					            </svg>
 | 
				
			||||||
 | 
					            Restart
 | 
				
			||||||
 | 
					        </button>
 | 
				
			||||||
        <button wire:click='stop' class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400">
 | 
					        <button wire:click='stop' class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400">
 | 
				
			||||||
            <svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-error" viewBox="0 0 24 24" stroke-width="2"
 | 
					            <svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-error" viewBox="0 0 24 24" stroke-width="2"
 | 
				
			||||||
                stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
 | 
					                stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user