refactor(push-server-update): enhance application preview handling by incorporating pull request IDs and adding status update protections

This commit is contained in:
Andras Bacsai
2025-06-04 10:03:36 +02:00
parent 684bd823c6
commit 97ec579910

View File

@@ -9,7 +9,6 @@ use App\Actions\Proxy\StartProxy;
use App\Actions\Server\StartLogDrain; use App\Actions\Server\StartLogDrain;
use App\Actions\Shared\ComplexStatusCheck; use App\Actions\Shared\ComplexStatusCheck;
use App\Models\Application; use App\Models\Application;
use App\Models\ApplicationPreview;
use App\Models\Server; use App\Models\Server;
use App\Models\ServiceApplication; use App\Models\ServiceApplication;
use App\Models\ServiceDatabase; use App\Models\ServiceDatabase;
@@ -122,7 +121,9 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue
$this->allApplicationsWithAdditionalServers = $this->applications->filter(function ($application) { $this->allApplicationsWithAdditionalServers = $this->applications->filter(function ($application) {
return $application->additional_servers->count() > 0; return $application->additional_servers->count() > 0;
}); });
$this->allApplicationPreviewsIds = $this->previews->pluck('id'); $this->allApplicationPreviewsIds = $this->previews->map(function ($preview) {
return $preview->application_id.':'.$preview->pull_request_id;
});
$this->allDatabaseUuids = $this->databases->pluck('uuid'); $this->allDatabaseUuids = $this->databases->pluck('uuid');
$this->allTcpProxyUuids = $this->databases->where('is_public', true)->pluck('uuid'); $this->allTcpProxyUuids = $this->databases->where('is_public', true)->pluck('uuid');
$this->services->each(function ($service) { $this->services->each(function ($service) {
@@ -147,7 +148,7 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue
} }
if ($labels->has('coolify.applicationId')) { if ($labels->has('coolify.applicationId')) {
$applicationId = $labels->get('coolify.applicationId'); $applicationId = $labels->get('coolify.applicationId');
$pullRequestId = data_get($labels, 'coolify.pullRequestId', '0'); $pullRequestId = $labels->get('coolify.pullRequestId', '0');
try { try {
if ($pullRequestId === '0') { if ($pullRequestId === '0') {
if ($this->allApplicationIds->contains($applicationId) && $this->isRunning($containerStatus)) { if ($this->allApplicationIds->contains($applicationId) && $this->isRunning($containerStatus)) {
@@ -155,10 +156,11 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue
} }
$this->updateApplicationStatus($applicationId, $containerStatus); $this->updateApplicationStatus($applicationId, $containerStatus);
} else { } else {
if ($this->allApplicationPreviewsIds->contains($applicationId) && $this->isRunning($containerStatus)) { $previewKey = $applicationId.':'.$pullRequestId;
$this->foundApplicationPreviewsIds->push($applicationId); if ($this->allApplicationPreviewsIds->contains($previewKey) && $this->isRunning($containerStatus)) {
$this->foundApplicationPreviewsIds->push($previewKey);
} }
$this->updateApplicationPreviewStatus($applicationId, $containerStatus); $this->updateApplicationPreviewStatus($applicationId, $pullRequestId, $containerStatus);
} }
} catch (\Exception $e) { } catch (\Exception $e) {
} }
@@ -215,14 +217,18 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue
$application->save(); $application->save();
} }
private function updateApplicationPreviewStatus(string $applicationId, string $containerStatus) private function updateApplicationPreviewStatus(string $applicationId, string $pullRequestId, string $containerStatus)
{ {
$application = $this->previews->where('id', $applicationId)->first(); $application = $this->previews->where('application_id', $applicationId)
->where('pull_request_id', $pullRequestId)
->first();
if (! $application) { if (! $application) {
return; return;
} }
$application->status = $containerStatus; if ($application->status !== $containerStatus) {
$application->save(); $application->status = $containerStatus;
$application->save();
}
} }
private function updateNotFoundApplicationStatus() private function updateNotFoundApplicationStatus()
@@ -232,6 +238,17 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue
$notFoundApplicationIds->each(function ($applicationId) { $notFoundApplicationIds->each(function ($applicationId) {
$application = Application::find($applicationId); $application = Application::find($applicationId);
if ($application) { if ($application) {
// Don't mark as exited if already exited
if (str($application->status)->startsWith('exited')) {
return;
}
// Only protection: Verify we received any container data at all
// If containers collection is completely empty, Sentinel might have failed
if ($this->containers->isEmpty()) {
return;
}
$application->status = 'exited'; $application->status = 'exited';
$application->save(); $application->save();
} }
@@ -243,9 +260,32 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue
{ {
$notFoundApplicationPreviewsIds = $this->allApplicationPreviewsIds->diff($this->foundApplicationPreviewsIds); $notFoundApplicationPreviewsIds = $this->allApplicationPreviewsIds->diff($this->foundApplicationPreviewsIds);
if ($notFoundApplicationPreviewsIds->isNotEmpty()) { if ($notFoundApplicationPreviewsIds->isNotEmpty()) {
$notFoundApplicationPreviewsIds->each(function ($applicationPreviewId) { $notFoundApplicationPreviewsIds->each(function ($previewKey) {
$applicationPreview = ApplicationPreview::find($applicationPreviewId); // Parse the previewKey format "application_id:pull_request_id"
$parts = explode(':', $previewKey);
if (count($parts) !== 2) {
return;
}
$applicationId = $parts[0];
$pullRequestId = $parts[1];
$applicationPreview = $this->previews->where('application_id', $applicationId)
->where('pull_request_id', $pullRequestId)
->first();
if ($applicationPreview) { if ($applicationPreview) {
// Don't mark as exited if already exited
if (str($applicationPreview->status)->startsWith('exited')) {
return;
}
// Only protection: Verify we received any container data at all
// If containers collection is completely empty, Sentinel might have failed
if ($this->containers->isEmpty()) {
return;
}
$applicationPreview->status = 'exited'; $applicationPreview->status = 'exited';
$applicationPreview->save(); $applicationPreview->save();
} }