From 033433f553bc964ec9ce3e8d834ad7dd7b95dddd Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Tue, 11 Nov 2025 23:24:53 +0100 Subject: [PATCH] fix(ServiceParser): prioritize manually migrated services over image detection for database identification --- bootstrap/helpers/parsers.php | 90 +++++++++++++++++++++++++++++------ bootstrap/helpers/shared.php | 77 +++++++++++++++++++----------- 2 files changed, 123 insertions(+), 44 deletions(-) diff --git a/bootstrap/helpers/parsers.php b/bootstrap/helpers/parsers.php index 48b02d6e3..7012e2087 100644 --- a/bootstrap/helpers/parsers.php +++ b/bootstrap/helpers/parsers.php @@ -1433,22 +1433,40 @@ function serviceParser(Service $resource): Collection } $image = data_get_str($service, 'image'); - $isDatabase = isDatabaseImage($image, $service); - if ($isDatabase) { - $applicationFound = ServiceApplication::where('name', $serviceName)->where('service_id', $resource->id)->first(); - if ($applicationFound) { - $savedService = $applicationFound; + + // Check for manually migrated services first (respects user's conversion choice) + $migratedApp = ServiceApplication::where('name', $serviceName) + ->where('service_id', $resource->id) + ->where('is_migrated', true) + ->first(); + $migratedDb = ServiceDatabase::where('name', $serviceName) + ->where('service_id', $resource->id) + ->where('is_migrated', true) + ->first(); + + if ($migratedApp || $migratedDb) { + // Use the migrated service type, ignoring image detection + $isDatabase = (bool) $migratedDb; + $savedService = $migratedApp ?: $migratedDb; + } else { + // Use image detection for non-migrated services + $isDatabase = isDatabaseImage($image, $service); + if ($isDatabase) { + $applicationFound = ServiceApplication::where('name', $serviceName)->where('service_id', $resource->id)->first(); + if ($applicationFound) { + $savedService = $applicationFound; + } else { + $savedService = ServiceDatabase::firstOrCreate([ + 'name' => $serviceName, + 'service_id' => $resource->id, + ]); + } } else { - $savedService = ServiceDatabase::firstOrCreate([ + $savedService = ServiceApplication::firstOrCreate([ 'name' => $serviceName, 'service_id' => $resource->id, ]); } - } else { - $savedService = ServiceApplication::firstOrCreate([ - 'name' => $serviceName, - 'service_id' => $resource->id, - ]); } // Update image if it changed if ($savedService->image !== $image) { @@ -1463,7 +1481,24 @@ function serviceParser(Service $resource): Collection $environment = collect(data_get($service, 'environment', [])); $buildArgs = collect(data_get($service, 'build.args', [])); $environment = $environment->merge($buildArgs); - $isDatabase = isDatabaseImage($image, $service); + + // Check for manually migrated services first (respects user's conversion choice) + $migratedApp = ServiceApplication::where('name', $serviceName) + ->where('service_id', $resource->id) + ->where('is_migrated', true) + ->first(); + $migratedDb = ServiceDatabase::where('name', $serviceName) + ->where('service_id', $resource->id) + ->where('is_migrated', true) + ->first(); + + if ($migratedApp || $migratedDb) { + // Use the migrated service type, ignoring image detection + $isDatabase = (bool) $migratedDb; + } else { + // Use image detection for non-migrated services + $isDatabase = isDatabaseImage($image, $service); + } $containerName = "$serviceName-{$resource->uuid}"; @@ -1483,7 +1518,11 @@ function serviceParser(Service $resource): Collection if ($serviceName === 'plausible') { $predefinedPort = '8000'; } - if ($isDatabase) { + + if ($migratedApp || $migratedDb) { + // Use the already determined migrated service + $savedService = $migratedApp ?: $migratedDb; + } elseif ($isDatabase) { $applicationFound = ServiceApplication::where('name', $serviceName)->where('service_id', $resource->id)->first(); if ($applicationFound) { $savedService = $applicationFound; @@ -1756,7 +1795,25 @@ function serviceParser(Service $resource): Collection $environment = convertToKeyValueCollection($environment); $coolifyEnvironments = collect([]); - $isDatabase = isDatabaseImage($image, $service); + // Check for manually migrated services first (respects user's conversion choice) + $migratedApp = ServiceApplication::where('name', $serviceName) + ->where('service_id', $resource->id) + ->where('is_migrated', true) + ->first(); + $migratedDb = ServiceDatabase::where('name', $serviceName) + ->where('service_id', $resource->id) + ->where('is_migrated', true) + ->first(); + + if ($migratedApp || $migratedDb) { + // Use the migrated service type, ignoring image detection + $isDatabase = (bool) $migratedDb; + $savedService = $migratedApp ?: $migratedDb; + } else { + // Use image detection for non-migrated services + $isDatabase = isDatabaseImage($image, $service); + } + $volumesParsed = collect([]); $containerName = "$serviceName-{$resource->uuid}"; @@ -1778,7 +1835,10 @@ function serviceParser(Service $resource): Collection $predefinedPort = '8000'; } - if ($isDatabase) { + if ($migratedApp || $migratedDb) { + // Use the already determined migrated service + $savedService = $migratedApp ?: $migratedDb; + } elseif ($isDatabase) { $applicationFound = ServiceApplication::where('name', $serviceName)->where('service_id', $resource->id)->first(); if ($applicationFound) { $savedService = $applicationFound; diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index effde712a..d9e76f399 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -1353,52 +1353,71 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal // Decide if the service is a database $image = data_get_str($service, 'image'); - $isDatabase = isDatabaseImage($image, $service); - data_set($service, 'is_database', $isDatabase); - // Create new serviceApplication or serviceDatabase - if ($isDatabase) { - if ($isNew) { - $savedService = ServiceDatabase::create([ - 'name' => $serviceName, - 'image' => $image, - 'service_id' => $resource->id, - ]); - } else { - $savedService = ServiceDatabase::where([ - 'name' => $serviceName, - 'service_id' => $resource->id, - ])->first(); - if (is_null($savedService)) { + // Check for manually migrated services first (respects user's conversion choice) + $migratedApp = ServiceApplication::where('name', $serviceName) + ->where('service_id', $resource->id) + ->where('is_migrated', true) + ->first(); + $migratedDb = ServiceDatabase::where('name', $serviceName) + ->where('service_id', $resource->id) + ->where('is_migrated', true) + ->first(); + + if ($migratedApp || $migratedDb) { + // Use the migrated service type, ignoring image detection + $isDatabase = (bool) $migratedDb; + $savedService = $migratedApp ?: $migratedDb; + } else { + // Use image detection for non-migrated services + $isDatabase = isDatabaseImage($image, $service); + + // Create new serviceApplication or serviceDatabase + if ($isDatabase) { + if ($isNew) { $savedService = ServiceDatabase::create([ 'name' => $serviceName, 'image' => $image, 'service_id' => $resource->id, ]); + } else { + $savedService = ServiceDatabase::where([ + 'name' => $serviceName, + 'service_id' => $resource->id, + ])->first(); + if (is_null($savedService)) { + $savedService = ServiceDatabase::create([ + 'name' => $serviceName, + 'image' => $image, + 'service_id' => $resource->id, + ]); + } } - } - } else { - if ($isNew) { - $savedService = ServiceApplication::create([ - 'name' => $serviceName, - 'image' => $image, - 'service_id' => $resource->id, - ]); } else { - $savedService = ServiceApplication::where([ - 'name' => $serviceName, - 'service_id' => $resource->id, - ])->first(); - if (is_null($savedService)) { + if ($isNew) { $savedService = ServiceApplication::create([ 'name' => $serviceName, 'image' => $image, 'service_id' => $resource->id, ]); + } else { + $savedService = ServiceApplication::where([ + 'name' => $serviceName, + 'service_id' => $resource->id, + ])->first(); + if (is_null($savedService)) { + $savedService = ServiceApplication::create([ + 'name' => $serviceName, + 'image' => $image, + 'service_id' => $resource->id, + ]); + } } } } + data_set($service, 'is_database', $isDatabase); + // Check if image changed if ($savedService->image !== $image) { $savedService->image = $image;