fix: pull requests
feat: add follow for full screen logs
This commit is contained in:
parent
b557ea1e1d
commit
0838343841
@ -138,9 +138,16 @@ public function __construct(int $application_deployment_queue_id)
|
||||
public function handle(): void
|
||||
{
|
||||
// ray()->measure();
|
||||
$containers = getCurrentApplicationContainerStatus($this->server, $this->application->id);
|
||||
if ($containers->count() > 0) {
|
||||
$containers = getCurrentApplicationContainerStatus($this->server, $this->application->id, $this->pull_request_id);
|
||||
if ($containers->count() === 1) {
|
||||
$this->currently_running_container_name = data_get($containers[0], 'Names');
|
||||
} else {
|
||||
$foundContainer = $containers->filter(function ($container) {
|
||||
return !str(data_get($container, 'Names'))->startsWith("{$this->application->uuid}-pr-");
|
||||
})->first();
|
||||
if ($foundContainer) {
|
||||
$this->currently_running_container_name = data_get($foundContainer, 'Names');
|
||||
}
|
||||
}
|
||||
if ($this->pull_request_id !== 0 && $this->pull_request_id !== null) {
|
||||
$this->currently_running_container_name = $this->container_name;
|
||||
@ -747,14 +754,21 @@ private function generate_compose_file()
|
||||
$labels = collect(generateLabelsApplication($this->application, $this->preview));
|
||||
}
|
||||
if ($this->pull_request_id !== 0) {
|
||||
$newLabels = collect(generateLabelsApplication($this->application, $this->preview));
|
||||
$newHostLabel = $newLabels->filter(function ($label) {
|
||||
return str($label)->contains('Host');
|
||||
});
|
||||
$labels = $labels->reject(function ($label) {
|
||||
return str($label)->contains('Host');
|
||||
});
|
||||
$newLabels = collect(generateLabelsApplication($this->application, $this->preview));
|
||||
$hostLabels = $newLabels->filter(function ($label) {
|
||||
return str($label)->contains('Host');
|
||||
|
||||
$labels = $labels->map(function ($label) {
|
||||
$pattern = '/([a-zA-Z0-9]+)-(\d+)-(http|https)/';
|
||||
$replacement = "$1-pr-{$this->pull_request_id}-$2-$3";
|
||||
$newLabel = preg_replace($pattern, $replacement, $label);
|
||||
return $newLabel;
|
||||
});
|
||||
$labels = $labels->merge($hostLabels);
|
||||
$labels = $labels->merge($newHostLabel);
|
||||
}
|
||||
$labels = $labels->merge(defaultLabels($this->application->id, $this->application->uuid, $this->pull_request_id))->toArray();
|
||||
$docker_compose = [
|
||||
|
@ -18,7 +18,6 @@
|
||||
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class ContainerStatusJob implements ShouldQueue, ShouldBeEncrypted
|
||||
{
|
||||
@ -26,6 +25,7 @@ class ContainerStatusJob implements ShouldQueue, ShouldBeEncrypted
|
||||
|
||||
public function __construct(public Server $server)
|
||||
{
|
||||
$this->handle();
|
||||
}
|
||||
public function middleware(): array
|
||||
{
|
||||
|
@ -6,11 +6,14 @@
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Str;
|
||||
use Spatie\Url\Url;
|
||||
use Visus\Cuid2\Cuid2;
|
||||
|
||||
function getCurrentApplicationContainerStatus(Server $server, int $id): Collection
|
||||
function getCurrentApplicationContainerStatus(Server $server, int $id, ?int $pullRequestId = null): Collection
|
||||
{
|
||||
$containers = instant_remote_process(["docker ps -a --filter='label=coolify.applicationId={$id}' --format '{{json .}}' "], $server);
|
||||
if ($pullRequestId) {
|
||||
$containers = instant_remote_process(["docker ps -a --filter='label=coolify.applicationId={$id}' --filter='label=coolify.pullRequestId={$pullRequestId}' --format '{{json .}}' "], $server);
|
||||
} else {
|
||||
$containers = instant_remote_process(["docker ps -a --filter='label=coolify.applicationId={$id}' --format '{{json .}}'"], $server);
|
||||
}
|
||||
if (!$containers) {
|
||||
return collect([]);
|
||||
}
|
||||
@ -77,20 +80,6 @@ function executeInDocker(string $containerId, string $command)
|
||||
// return "docker exec {$this->deployment_uuid} bash -c '{$command} |& tee -a /proc/1/fd/1; [ \$PIPESTATUS -eq 0 ] || exit \$PIPESTATUS'";
|
||||
}
|
||||
|
||||
function getApplicationContainerStatus(Application $application)
|
||||
{
|
||||
$server = data_get($application, 'destination.server');
|
||||
$id = $application->id;
|
||||
if (!$server) {
|
||||
return 'exited';
|
||||
}
|
||||
$containers = getCurrentApplicationContainerStatus($server, $id);
|
||||
if ($containers->count() > 0) {
|
||||
$status = data_get($containers[0], 'State', 'exited');
|
||||
return $status;
|
||||
}
|
||||
return 'exited';
|
||||
}
|
||||
function getContainerStatus(Server $server, string $container_id, bool $all_data = false, bool $throwError = false)
|
||||
{
|
||||
$container = instant_remote_process(["docker inspect --format '{{json .}}' {$container_id}"], $server, $throwError);
|
||||
@ -212,9 +201,9 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview
|
||||
$onlyPort = $ports[0];
|
||||
}
|
||||
$pull_request_id = data_get($preview, 'pull_request_id', 0);
|
||||
$appId = $application->id;
|
||||
if ($pull_request_id !== 0 && $pull_request_id !== null) {
|
||||
$appId = $appId . '-pr-' . $pull_request_id;
|
||||
$appUuid = $application->uuid;
|
||||
if ($pull_request_id !== 0) {
|
||||
$appUuid = $appUuid . '-pr-' . $pull_request_id;
|
||||
}
|
||||
$labels = collect([]);
|
||||
if ($application->fqdn) {
|
||||
@ -224,7 +213,7 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview
|
||||
$domains = Str::of(data_get($application, 'fqdn'))->explode(',');
|
||||
}
|
||||
// Add Traefik labels no matter which proxy is selected
|
||||
$labels = $labels->merge(fqdnLabelsForTraefik($application->uuid, $domains, $application->settings->is_force_https_enabled, $onlyPort));
|
||||
$labels = $labels->merge(fqdnLabelsForTraefik($appUuid, $domains, $application->settings->is_force_https_enabled, $onlyPort));
|
||||
}
|
||||
return $labels->all();
|
||||
}
|
||||
|
@ -122,5 +122,5 @@ .subtitle {
|
||||
@apply pt-2 pb-10;
|
||||
}
|
||||
.fullscreen {
|
||||
@apply fixed top-0 left-0 w-full h-full z-[9999] bg-coolgray-200 overflow-y-auto scrollbar ;
|
||||
@apply fixed top-0 left-0 w-full h-full z-[9999] bg-coolgray-100 overflow-y-auto scrollbar pb-4 ;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div class="pt-4" x-data="{ fullscreen: false }">
|
||||
<div class="pt-4" x-data="{ fullscreen: false, alwaysScroll: false, intervalId: null }">
|
||||
<livewire:project.application.deployment-navbar :application_deployment_queue="$application_deployment_queue" />
|
||||
@if (data_get($application_deployment_queue, 'status') === 'in_progress')
|
||||
<div class="flex items-center gap-1 pt-2 ">Deployment is
|
||||
@ -6,24 +6,35 @@
|
||||
</div>
|
||||
<x-loading class="loading-ring" />
|
||||
</div>
|
||||
<div class="">Logs will be updated automatically.</div>
|
||||
{{-- <div class="">Logs will be updated automatically.</div> --}}
|
||||
@else
|
||||
<div class="pt-2 ">Deployment is <span
|
||||
class="text-warning">{{ Str::headline(data_get($application_deployment_queue, 'status')) }}</span>.
|
||||
</div>
|
||||
@endif
|
||||
<div :class="fullscreen ? 'fullscreen' : ''">
|
||||
<div id="screen" :class="fullscreen ? 'fullscreen' : ''">
|
||||
<div @if ($isKeepAliveOn) wire:poll.2000ms="polling" @endif
|
||||
class="relative flex flex-col-reverse w-full p-2 px-4 mt-4 overflow-y-auto text-xs border border-dotted rounded scrollbar border-coolgray-400"
|
||||
:class="fullscreen ? '' : 'max-h-[32rem]'">
|
||||
<button title="Minimize" x-show="fullscreen" class="fixed top-2 right-2"
|
||||
x-on:click="fullscreen = !fullscreen"><svg class="icon" viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
class="relative flex flex-col-reverse w-full p-2 px-4 mt-4 overflow-y-auto scrollbar border-coolgray-400"
|
||||
:class="fullscreen ? '' : 'max-h-[40rem] border border-dotted rounded'">
|
||||
<button title="Minimize" x-show="fullscreen" class="fixed top-4 right-4" x-on:click="makeFullscreen"><svg
|
||||
class="icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2" d="M6 14h4m0 0v4m0-4l-6 6m14-10h-4m0 0V6m0 4l6-6" />
|
||||
</svg></button>
|
||||
<button title="Go Top" x-show="fullscreen" class="fixed top-4 right-28" x-on:click="goTop"> <svg
|
||||
class="icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2" d="M12 5v14m4-10l-4-4M8 9l4-4" />
|
||||
</svg></button>
|
||||
<button title="Follow Logs" x-show="fullscreen" :class="alwaysScroll ? 'text-warning' : ''"
|
||||
class="fixed top-4 right-16" x-on:click="toggleScroll"><svg class="icon" viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2" d="M12 5v14m4-4l-4 4m-4-4l4 4" />
|
||||
</svg></button>
|
||||
|
||||
<button title="Fullscreen" x-show="!fullscreen" class="absolute top-2 right-8"
|
||||
x-on:click="fullscreen = !fullscreen"><svg class="fixed icon" viewBox="0 0 24 24"
|
||||
x-on:click="makeFullscreen"><svg class="fixed icon" viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none">
|
||||
<path
|
||||
@ -32,7 +43,7 @@ class="relative flex flex-col-reverse w-full p-2 px-4 mt-4 overflow-y-auto text-
|
||||
d="M9.793 12.793a1 1 0 0 1 1.497 1.32l-.083.094L6.414 19H9a1 1 0 0 1 .117 1.993L9 21H4a1 1 0 0 1-.993-.883L3 20v-5a1 1 0 0 1 1.993-.117L5 15v2.586l4.793-4.793ZM20 3a1 1 0 0 1 .993.883L21 4v5a1 1 0 0 1-1.993.117L19 9V6.414l-4.793 4.793a1 1 0 0 1-1.497-1.32l.083-.094L17.586 5H15a1 1 0 0 1-.117-1.993L15 3h5Z" />
|
||||
</g>
|
||||
</svg></button>
|
||||
<span class="flex flex-col">
|
||||
<div id="logs" class="flex flex-col">
|
||||
@if (decode_remote_command_output($application_deployment_queue)->count() > 0)
|
||||
@foreach (decode_remote_command_output($application_deployment_queue) as $line)
|
||||
<div @class([
|
||||
@ -49,7 +60,40 @@ class="relative flex flex-col-reverse w-full p-2 px-4 mt-4 overflow-y-auto text-
|
||||
@else
|
||||
<span class="font-mono text-neutral-400">No logs yet.</span>
|
||||
@endif
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function makeFullscreen() {
|
||||
this.fullscreen = !this.fullscreen;
|
||||
if (this.fullscreen === false) {
|
||||
this.alwaysScroll = false;
|
||||
clearInterval(this.intervalId);
|
||||
}
|
||||
}
|
||||
|
||||
function toggleScroll() {
|
||||
this.alwaysScroll = !this.alwaysScroll;
|
||||
|
||||
if (this.alwaysScroll) {
|
||||
this.intervalId = setInterval(() => {
|
||||
const screen = document.getElementById('screen');
|
||||
const logs = document.getElementById('logs');
|
||||
if (screen.scrollTop !== logs.scrollHeight) {
|
||||
screen.scrollTop = logs.scrollHeight;
|
||||
}
|
||||
}, 100);
|
||||
} else {
|
||||
clearInterval(this.intervalId);
|
||||
this.intervalId = null;
|
||||
}
|
||||
}
|
||||
|
||||
function goTop() {
|
||||
this.alwaysScroll = false;
|
||||
clearInterval(this.intervalId);
|
||||
const screen = document.getElementById('screen');
|
||||
screen.scrollTop = 0;
|
||||
}
|
||||
</script>
|
||||
</div>
|
||||
|
@ -78,11 +78,9 @@
|
||||
Redeploy
|
||||
@endif
|
||||
</x-forms.button>
|
||||
@if (data_get($preview, 'status') !== 'exited')
|
||||
<x-forms.button wire:click="stop({{ data_get($preview, 'pull_request_id') }})">Remove
|
||||
Preview
|
||||
</x-forms.button>
|
||||
@endif
|
||||
<x-forms.button wire:click="stop({{ data_get($preview, 'pull_request_id') }})">Remove
|
||||
Preview
|
||||
</x-forms.button>
|
||||
<a
|
||||
href="{{ route('project.application.deployments', [...$parameters, 'pull_request_id' => data_get($preview, 'pull_request_id')]) }}">
|
||||
<x-forms.button>
|
||||
|
@ -13,17 +13,18 @@
|
||||
<x-forms.input label="Only Show Number of Lines" placeholder="1000" required id="numberOfLines"></x-forms.input>
|
||||
<x-forms.button type="submit">Refresh</x-forms.button>
|
||||
</form>
|
||||
|
||||
<div x-data="{ fullscreen: false }" :class="fullscreen ? 'fullscreen' : 'container w-full pt-4 mx-auto'">
|
||||
<div
|
||||
class="relative flex flex-col-reverse w-full p-4 pt-6 overflow-y-auto text-xs text-white border border-solid rounded scrollbar border-coolgray-300" :class="fullscreen ? '' : 'max-h-[32rem]'">
|
||||
<button title="Minimize" x-show="fullscreen" class="fixed top-2 right-2" x-on:click="fullscreen = !fullscreen"><svg
|
||||
class="icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<div class="relative flex flex-col-reverse w-full p-4 pt-6 overflow-y-auto text-white scrollbar border-coolgray-300"
|
||||
:class="fullscreen ? '' : 'max-h-[40rem] border border-solid rounded'">
|
||||
<button title="Minimize" x-show="fullscreen" class="fixed top-4 right-4"
|
||||
x-on:click="fullscreen = !fullscreen"><svg class="icon" viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2" d="M6 14h4m0 0v4m0-4l-6 6m14-10h-4m0 0V6m0 4l6-6" />
|
||||
</svg></button>
|
||||
<button title="Fullscreen" x-show="!fullscreen" class="absolute top-2 right-8" x-on:click="fullscreen = !fullscreen"><svg
|
||||
class="fixed icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<button title="Fullscreen" x-show="!fullscreen" class="absolute top-2 right-8"
|
||||
x-on:click="fullscreen = !fullscreen"><svg class="fixed icon" viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none">
|
||||
<path
|
||||
d="M24 0v24H0V0h24ZM12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035c-.01-.004-.019-.001-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427c-.002-.01-.009-.017-.017-.018Zm.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093c.012.004.023 0 .029-.008l.004-.014l-.034-.614c-.003-.012-.01-.02-.02-.022Zm-.715.002a.023.023 0 0 0-.027.006l-.006.014l-.034.614c0 .012.007.02.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01l-.184-.092Z" />
|
||||
|
Loading…
Reference in New Issue
Block a user