diff --git a/app/Actions/Application/StopApplication.php b/app/Actions/Application/StopApplication.php index 8ecebeda3..a98384f45 100644 --- a/app/Actions/Application/StopApplication.php +++ b/app/Actions/Application/StopApplication.php @@ -3,7 +3,6 @@ namespace App\Actions\Application; use App\Models\Application; -use App\Notifications\Application\StatusChanged; use Lorisleiva\Actions\Concerns\AsAction; class StopApplication @@ -12,7 +11,7 @@ class StopApplication public function handle(Application $application) { $server = $application->destination->server; - $containers = getCurrentApplicationContainerStatus($server, $application->id); + $containers = getCurrentApplicationContainerStatus($server, $application->id, 0); if ($containers->count() > 0) { foreach ($containers as $container) { $containerName = data_get($container, 'Names'); diff --git a/app/Http/Livewire/Project/Shared/Logs.php b/app/Http/Livewire/Project/Shared/Logs.php index 2b0561800..f58ec672a 100644 --- a/app/Http/Livewire/Project/Shared/Logs.php +++ b/app/Http/Livewire/Project/Shared/Logs.php @@ -31,7 +31,7 @@ class Logs extends Component $this->resource = Application::where('uuid', $this->parameters['application_uuid'])->firstOrFail(); $this->status = $this->resource->status; $this->server = $this->resource->destination->server; - $containers = getCurrentApplicationContainerStatus($this->server, $this->resource->id); + $containers = getCurrentApplicationContainerStatus($this->server, $this->resource->id, 0); if ($containers->count() > 0) { $this->container = data_get($containers[0], 'Names'); } diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index 798c46b2b..1b7f4d492 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -52,7 +52,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted private GithubApp|GitlabApp|string $source = 'other'; private StandaloneDocker|SwarmDocker $destination; private Server $server; - private ApplicationPreview|null $preview = null; + private ?ApplicationPreview $preview = null; private string $container_name; private ?string $currently_running_container_name = null; @@ -139,21 +139,6 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted public function handle(): void { - // ray()->measure(); - $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; - } $this->application_deployment_queue->update([ 'status' => ApplicationDeploymentStatus::IN_PROGRESS->value, ]); @@ -502,6 +487,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted } private function deploy_pull_request() { + $this->newVersionIsHealthy = true; $this->generate_image_names(); $this->execute_remote_command([ "echo 'Starting pull request (#{$this->pull_request_id}) deployment of {$this->customRepository}:{$this->application->git_branch}.'", @@ -518,12 +504,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted // $this->generate_build_env_variables(); // $this->add_build_env_variables_to_dockerfile(); $this->build_image(); - if ($this->currently_running_container_name) { - $this->execute_remote_command( - ["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, "ignore_errors" => true], - ); - } + $this->stop_running_container(); $this->execute_remote_command( ["echo -n 'Starting preview deployment.'"], [executeInDocker($this->deployment_uuid, "docker compose --project-directory {$this->workdir} up -d"), "hidden" => true], @@ -980,18 +961,30 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf"); private function stop_running_container(bool $force = false) { - if ($this->currently_running_container_name) { - if ($this->newVersionIsHealthy || $force) { - $this->execute_remote_command( - ["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, "ignore_errors" => true], - ); + $this->execute_remote_command(["echo -n 'Removing old version of your application.'"]); + + if ($this->newVersionIsHealthy || $force) { + $containers = getCurrentApplicationContainerStatus($this->server, $this->application->id, $this->pull_request_id); + if ($this->pull_request_id !== 0) { + $containers = $containers->filter(function ($container) { + return data_get($container, 'Names') === $this->container_name; + }); } else { - $this->execute_remote_command( - ["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, "ignore_errors" => true], - ); + $containers = $containers->filter(function ($container) { + return data_get($container, 'Names') !== $this->container_name; + }); } + $containers->each(function ($container) { + $containerName = data_get($container, 'Names'); + $this->execute_remote_command( + [executeInDocker($this->deployment_uuid, "docker rm -f $containerName >/dev/null 2>&1"), "hidden" => true, "ignore_errors" => true], + ); + }); + } else { + $this->execute_remote_command( + ["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, "ignore_errors" => true], + ); } } @@ -1057,8 +1050,11 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf"); { $this->execute_remote_command( ["echo 'Oops something is not okay, are you okay? 😢'"], - ["echo '{$exception->getMessage()}'"] + ["echo '{$exception->getMessage()}'"], + ["echo -n 'Deployment failed. Removing the new version of your application.'"], + [executeInDocker($this->deployment_uuid, "docker rm -f $this->container_name >/dev/null 2>&1"), "hidden" => true, "ignore_errors" => true] ); + $this->next(ApplicationDeploymentStatus::FAILED->value); } } diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php index 874b01ebd..90c4179a7 100644 --- a/bootstrap/helpers/docker.php +++ b/bootstrap/helpers/docker.php @@ -10,15 +10,24 @@ use Visus\Cuid2\Cuid2; function getCurrentApplicationContainerStatus(Server $server, int $id, ?int $pullRequestId = null): Collection { - 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([]); - } - return format_docker_command_output_to_json($containers); + ray($id, $pullRequestId); + $containers = collect([]); + $containers = instant_remote_process(["docker ps -a --filter='label=coolify.applicationId={$id}' --format '{{json .}}' "], $server); + $containers = format_docker_command_output_to_json($containers); + $containers = $containers->map(function ($container) use ($pullRequestId) { + $labels = data_get($container, 'Labels'); + if (!str($labels)->contains("coolify.pullRequestId=")) { + data_set($container, 'Labels', $labels . ",coolify.pullRequestId={$pullRequestId}"); + return $container; + } + if (str($labels)->contains("coolify.pullRequestId=$pullRequestId")) { + return $container; + } + return null; + }); + $containers = $containers->filter(); + ray($containers); + return $containers; } function format_docker_command_output_to_json($rawOutput): Collection @@ -128,9 +137,7 @@ function defaultLabels($id, $name, $pull_request_id = 0, string $type = 'applica $labels->push("coolify." . $type . "Id=" . $id); $labels->push("coolify.type=$type"); $labels->push('coolify.name=' . $name); - if ($pull_request_id !== 0) { - $labels->push('coolify.pullRequestId=' . $pull_request_id); - } + $labels->push('coolify.pullRequestId=' . $pull_request_id); if ($type === 'service') { $labels->push('coolify.service.subId=' . $subId); $labels->push('coolify.service.subType=' . $subType); diff --git a/resources/views/livewire/project/application/deployments.blade.php b/resources/views/livewire/project/application/deployments.blade.php index ecf95ccaa..ab75a87a4 100644 --- a/resources/views/livewire/project/application/deployments.blade.php +++ b/resources/views/livewire/project/application/deployments.blade.php @@ -13,7 +13,7 @@ @forelse ($deployments as $deployment) + 'hover:bg-coolgray-200' => data_get($deployment, 'status') === 'queued' || data_get($deployment, 'status') === 'cancelled by system', 'border-warning hover:bg-warning hover:text-black' =>