feat: dashboard live deployment view

This commit is contained in:
Andras Bacsai 2024-01-27 18:44:40 +01:00
parent c46d38907e
commit 561e424a7d
11 changed files with 118 additions and 41 deletions

View File

@ -2,18 +2,35 @@
namespace App\Livewire; namespace App\Livewire;
use App\Models\ApplicationDeploymentQueue;
use App\Models\Project; use App\Models\Project;
use App\Models\Server; use App\Models\Server;
use Illuminate\Support\Collection;
use Livewire\Component; use Livewire\Component;
class Dashboard extends Component class Dashboard extends Component
{ {
public $projects = []; public $projects = [];
public $servers = []; public Collection $servers;
public Collection $deployments_per_server;
public function mount() public function mount()
{ {
$this->servers = Server::ownedByCurrentTeam()->get(); $this->servers = Server::ownedByCurrentTeam()->get();
$this->projects = Project::ownedByCurrentTeam()->get(); $this->projects = Project::ownedByCurrentTeam()->get();
$this->get_deployments();
}
public function get_deployments()
{
$this->deployments_per_server = ApplicationDeploymentQueue::whereIn("status", ["in_progress", "queued"])->whereIn("server_id", $this->servers->pluck("id"))->get([
"id",
"application_id",
"application_name",
"deployment_url",
"pull_request_id",
"server_name",
"server_id",
"status"
])->sortBy('id');
} }
// public function getIptables() // public function getIptables()
// { // {

View File

@ -54,8 +54,7 @@ public function deployNew()
} }
$this->setDeploymentUuid(); $this->setDeploymentUuid();
queue_application_deployment( queue_application_deployment(
application_id: $this->application->id, application: $this->application,
server_id: $this->application->destination->server->id,
deployment_uuid: $this->deploymentUuid, deployment_uuid: $this->deploymentUuid,
force_rebuild: false, force_rebuild: false,
is_new_deployment: true, is_new_deployment: true,
@ -83,8 +82,7 @@ public function deploy(bool $force_rebuild = false)
} }
$this->setDeploymentUuid(); $this->setDeploymentUuid();
queue_application_deployment( queue_application_deployment(
application_id: $this->application->id, application: $this->application,
server_id: $this->application->destination->server->id,
deployment_uuid: $this->deploymentUuid, deployment_uuid: $this->deploymentUuid,
force_rebuild: $force_rebuild, force_rebuild: $force_rebuild,
); );
@ -113,8 +111,7 @@ public function restartNew()
{ {
$this->setDeploymentUuid(); $this->setDeploymentUuid();
queue_application_deployment( queue_application_deployment(
application_id: $this->application->id, application: $this->application,
server_id: $this->application->destination->server->id,
deployment_uuid: $this->deploymentUuid, deployment_uuid: $this->deploymentUuid,
restart_only: true, restart_only: true,
is_new_deployment: true, is_new_deployment: true,
@ -130,8 +127,7 @@ public function restart()
{ {
$this->setDeploymentUuid(); $this->setDeploymentUuid();
queue_application_deployment( queue_application_deployment(
application_id: $this->application->id, application: $this->application,
server_id: $this->application->destination->server->id,
deployment_uuid: $this->deploymentUuid, deployment_uuid: $this->deploymentUuid,
restart_only: true, restart_only: true,
); );

View File

@ -47,8 +47,7 @@ public function deploy(int $pull_request_id, string|null $pull_request_html_url
]); ]);
} }
queue_application_deployment( queue_application_deployment(
application_id: $this->application->id, application: $this->application,
server_id: $this->application->destination->server->id,
deployment_uuid: $this->deployment_uuid, deployment_uuid: $this->deployment_uuid,
force_rebuild: false, force_rebuild: false,
pull_request_id: $pull_request_id, pull_request_id: $pull_request_id,

View File

@ -24,8 +24,7 @@ public function rollbackImage($commit)
$deployment_uuid = new Cuid2(7); $deployment_uuid = new Cuid2(7);
queue_application_deployment( queue_application_deployment(
application_id: $this->application->id, application: $this->application,
server_id: $this->application->destination->server->id,
deployment_uuid: $deployment_uuid, deployment_uuid: $deployment_uuid,
commit: $commit, commit: $commit,
force_rebuild: false, force_rebuild: false,

View File

@ -6,14 +6,23 @@
use App\Models\ApplicationDeploymentQueue; use App\Models\ApplicationDeploymentQueue;
use App\Models\ApplicationPreview; use App\Models\ApplicationPreview;
use App\Models\Server; use App\Models\Server;
use Spatie\Url\Url;
use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Yaml;
function queue_application_deployment(int $application_id, int $server_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, ?string $git_type = null, bool $is_new_deployment = false) function queue_application_deployment(Application $application, string $deployment_uuid, int | null $pull_request_id = 0, string $commit = 'HEAD', bool $force_rebuild = false, bool $is_webhook = false, bool $restart_only = false, ?string $git_type = null, bool $is_new_deployment = false)
{ {
$application_id = $application->id;
$deployment_link = Url::fromString($application->link() . "/deployment/{$deployment_uuid}");
$deployment_url = $deployment_link->getPath();
$server_id = $application->destination->server->id;
$server_name = $application->destination->server->name;
$deployment = ApplicationDeploymentQueue::create([ $deployment = ApplicationDeploymentQueue::create([
'application_id' => $application_id, 'application_id' => $application_id,
'application_name' => $application->name,
'server_id' => $server_id, 'server_id' => $server_id,
'server_name' => $server_name,
'deployment_uuid' => $deployment_uuid, 'deployment_uuid' => $deployment_uuid,
'deployment_url' => $deployment_url,
'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,

View File

@ -0,0 +1,32 @@
<?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->string('application_name')->nullable();
$table->string('server_name')->nullable();
$table->string('deployment_url')->nullable();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('application_deployment_queues', function (Blueprint $table) {
$table->dropColumn('application_name');
$table->dropColumn('server_name');
$table->dropColumn('deployment_url');
});
}
};

View File

@ -19,7 +19,7 @@ .scrollbar {
} }
.main { .main {
@apply pt-4 pl-24 pr-10 mx-auto; @apply pt-4 pl-24 pr-10 lg:pr-32 lg:pl-44;
} }
.custom-modal { .custom-modal {

View File

@ -11,7 +11,7 @@
@auth @auth
<livewire:realtime-connection /> <livewire:realtime-connection />
@endauth @endauth
<main class="pb-10 main max-w-screen-2xl"> <main class="pb-10 main">
{{ $slot }} {{ $slot }}
</main> </main>
@endsection @endsection

View File

@ -11,7 +11,8 @@
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" /> d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg> </svg>
<span>Your subscription has been activated! Welcome onboard! <br>It could take a few seconds before your subscription is activated.<br> Please be patient.</span> <span>Your subscription has been activated! Welcome onboard! <br>It could take a few seconds before your
subscription is activated.<br> Please be patient.</span>
</div> </div>
@endif @endif
@if ($projects->count() === 0 && $servers->count() === 0) @if ($projects->count() === 0 && $servers->count() === 0)
@ -29,14 +30,14 @@
@foreach ($projects as $project) @foreach ($projects as $project)
<div class="gap-2 border border-transparent cursor-pointer box group"> <div class="gap-2 border border-transparent cursor-pointer box group">
@if (data_get($project, 'environments.0.name')) @if (data_get($project, 'environments.0.name'))
<a class="flex flex-col flex-1 mx-6 hover:no-underline" <a class="flex flex-col flex-1 mx-6 hover:no-underline"
href="{{ route('project.resource.index', ['project_uuid' => data_get($project, 'uuid'), 'environment_name' => data_get($project, 'environments.0.name', 'production')]) }}"> href="{{ route('project.resource.index', ['project_uuid' => data_get($project, 'uuid'), 'environment_name' => data_get($project, 'environments.0.name', 'production')]) }}">
<div class="font-bold text-white">{{ $project->name }}</div> <div class="font-bold text-white">{{ $project->name }}</div>
<div class="description"> <div class="description">
{{ $project->description }}</div> {{ $project->description }}</div>
</a> </a>
@else @else
<a class="flex flex-col flex-1 mx-6 hover:no-underline" <a class="flex flex-col flex-1 mx-6 hover:no-underline"
href="{{ route('project.show', ['project_uuid' => data_get($project, 'uuid')]) }}"> href="{{ route('project.show', ['project_uuid' => data_get($project, 'uuid')]) }}">
<div class="font-bold text-white">{{ $project->name }}</div> <div class="font-bold text-white">{{ $project->name }}</div>
<div class="description"> <div class="description">
@ -44,11 +45,11 @@
</a> </a>
@endif @endif
<div class="flex items-center"> <div class="flex items-center">
<a class="mx-4 rounded group-hover:text-white hover:no-underline" <a class="mx-4 rounded group-hover:text-white hover:no-underline"
href="{{ route('project.resource.create', ['project_uuid' => data_get($project, 'uuid'), 'environment_name' => data_get($project, 'environments.0.name', 'production')]) }}"> href="{{ route('project.resource.create', ['project_uuid' => data_get($project, 'uuid'), 'environment_name' => data_get($project, 'environments.0.name', 'production')]) }}">
<span class="font-bold hover:text-warning">+ New Resource</span> <span class="font-bold hover:text-warning">+ New Resource</span>
</a> </a>
<a class="mx-4 rounded group-hover:text-white" <a class="mx-4 rounded group-hover:text-white"
href="{{ route('project.edit', ['project_uuid' => data_get($project, 'uuid')]) }}"> href="{{ route('project.edit', ['project_uuid' => data_get($project, 'uuid')]) }}">
<svg xmlns="http://www.w3.org/2000/svg" class="icon hover:text-warning" viewBox="0 0 24 24" <svg xmlns="http://www.w3.org/2000/svg" class="icon hover:text-warning" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
@ -72,12 +73,11 @@
<div class="grid grid-cols-1 gap-2 xl:grid-cols-2"> <div class="grid grid-cols-1 gap-2 xl:grid-cols-2">
@endif @endif
@foreach ($servers as $server) @foreach ($servers as $server)
<a href="{{ route('server.show', ['server_uuid' => data_get($server, 'uuid')]) }}" <a href="{{ route('server.show', ['server_uuid' => data_get($server, 'uuid')]) }}" @class([
@class([ 'gap-2 border cursor-pointer box group',
'gap-2 border cursor-pointer box group', 'border-transparent' => $server->settings->is_reachable,
'border-transparent' => $server->settings->is_reachable, 'border-red-500' => !$server->settings->is_reachable,
'border-red-500' => !$server->settings->is_reachable, ])>
])>
<div class="flex flex-col mx-6"> <div class="flex flex-col mx-6">
<div class="font-bold text-white"> <div class="font-bold text-white">
{{ $server->name }} {{ $server->name }}
@ -99,6 +99,38 @@
<div class="flex-1"></div> <div class="flex-1"></div>
</a> </a>
@endforeach @endforeach
<div class="flex items-center gap-2">
<h3 class="py-4">Deployments </h3>
@if ($deployments_per_server->count() > 0)
<x-loading />
@endif
</div>
<div wire:poll.1000ms="get_deployments" class="grid grid-cols-1 gap-2 lg:grid-cols-3">
@forelse ($deployments_per_server as $deployment)
<a href="{{ url($deployment->deployment_url) }}" @class([
'gap-2 cursor-pointer box group border-l-2 border-dotted',
'border-yellow-500' => $deployment->status === 'queued',
'border-green-500' => $deployment->status === 'in_progress',
])>
<div class="flex flex-col mx-6">
<div class="font-bold text-white">
{{ $deployment->application_name }}
</div>
@if ($deployment->pull_request_id !== 0)
<div class="description">
PR #{{ $deployment->pull_request_id }}
</div>
@endif
<div class="description">
{{ $deployment->status }} on server {{ $deployment->server_name }}.
</div>
</div>
<div class="flex-1"></div>
</a>
@empty
<div>No queued / in progress deployments</div>
@endforelse
</div>
</div> </div>
<script> <script>
function gotoProject(uuid, environment = 'production') { function gotoProject(uuid, environment = 'production') {

View File

@ -70,8 +70,7 @@
$type = $resource->getMorphClass(); $type = $resource->getMorphClass();
if ($type === 'App\Models\Application') { if ($type === 'App\Models\Application') {
queue_application_deployment( queue_application_deployment(
server_id: $resource->destination->server->id, application: $resource,
application_id: $resource->id,
deployment_uuid: new Cuid2(7), deployment_uuid: new Cuid2(7),
force_rebuild: $force, force_rebuild: $force,
); );

View File

@ -151,8 +151,7 @@
ray('Deploying ' . $application->name . ' with branch ' . $branch); ray('Deploying ' . $application->name . ' with branch ' . $branch);
$deployment_uuid = new Cuid2(7); $deployment_uuid = new Cuid2(7);
queue_application_deployment( queue_application_deployment(
server_id: $application->destination->server->id, application: $application,
application_id: $application->id,
deployment_uuid: $deployment_uuid, deployment_uuid: $deployment_uuid,
force_rebuild: false, force_rebuild: false,
is_webhook: true is_webhook: true
@ -180,8 +179,7 @@
]); ]);
} }
queue_application_deployment( queue_application_deployment(
server_id: $application->destination->server->id, application: $application,
application_id: $application->id,
pull_request_id: $pull_request_id, pull_request_id: $pull_request_id,
deployment_uuid: $deployment_uuid, deployment_uuid: $deployment_uuid,
force_rebuild: false, force_rebuild: false,
@ -300,8 +298,7 @@
ray('Deploying ' . $application->name . ' with branch ' . $branch); ray('Deploying ' . $application->name . ' with branch ' . $branch);
$deployment_uuid = new Cuid2(7); $deployment_uuid = new Cuid2(7);
queue_application_deployment( queue_application_deployment(
server_id: $application->destination->server->id, application: $application,
application_id: $application->id,
deployment_uuid: $deployment_uuid, deployment_uuid: $deployment_uuid,
force_rebuild: false, force_rebuild: false,
is_webhook: true is_webhook: true
@ -324,8 +321,7 @@
]); ]);
} }
queue_application_deployment( queue_application_deployment(
server_id: $application->destination->server->id, application: $application,
application_id: $application->id,
pull_request_id: $pull_request_id, pull_request_id: $pull_request_id,
deployment_uuid: $deployment_uuid, deployment_uuid: $deployment_uuid,
force_rebuild: false, force_rebuild: false,
@ -430,8 +426,7 @@
ray('Deploying ' . $application->name . ' with branch ' . $branch); ray('Deploying ' . $application->name . ' with branch ' . $branch);
$deployment_uuid = new Cuid2(7); $deployment_uuid = new Cuid2(7);
queue_application_deployment( queue_application_deployment(
server_id: $application->destination->server->id, application: $application,
application_id: $application->id,
deployment_uuid: $deployment_uuid, deployment_uuid: $deployment_uuid,
force_rebuild: false, force_rebuild: false,
is_webhook: true is_webhook: true
@ -454,8 +449,7 @@
]); ]);
} }
queue_application_deployment( queue_application_deployment(
server_id: $application->destination->server->id, application: $application,
application_id: $application->id,
pull_request_id: $pull_request_id, pull_request_id: $pull_request_id,
deployment_uuid: $deployment_uuid, deployment_uuid: $deployment_uuid,
force_rebuild: false, force_rebuild: false,