diff --git a/app/Actions/Service/DeleteService.php b/app/Actions/Service/DeleteService.php
index 1a411cf59..420f40f3b 100644
--- a/app/Actions/Service/DeleteService.php
+++ b/app/Actions/Service/DeleteService.php
@@ -45,6 +45,9 @@ class DeleteService
foreach ($service->databases()->get() as $database) {
$database->forceDelete();
}
+ foreach ($service->scheduled_tasks as $task) {
+ $task->delete();
+ }
$service->tags()->detach();
}
}
diff --git a/app/Console/Commands/CleanupStuckedResources.php b/app/Console/Commands/CleanupStuckedResources.php
index 38d87e24b..d2882e9b3 100644
--- a/app/Console/Commands/CleanupStuckedResources.php
+++ b/app/Console/Commands/CleanupStuckedResources.php
@@ -3,6 +3,7 @@
namespace App\Console\Commands;
use App\Models\Application;
+use App\Models\ScheduledTask;
use App\Models\Service;
use App\Models\ServiceApplication;
use App\Models\ServiceDatabase;
@@ -108,6 +109,17 @@ class CleanupStuckedResources extends Command
} catch (\Throwable $e) {
echo "Error in cleaning stuck serviceapp: {$e->getMessage()}\n";
}
+ try {
+ $scheduled_tasks = ScheduledTask::all();
+ foreach ($scheduled_tasks as $scheduled_task) {
+ if (!$scheduled_task->service && !$scheduled_task->application) {
+ echo "Deleting stuck scheduledtask: {$scheduled_task->name}\n";
+ $scheduled_task->delete();
+ }
+ }
+ } catch (\Throwable $e) {
+ echo "Error in cleaning stuck scheduledtasks: {$e->getMessage()}\n";
+ }
// Cleanup any resources that are not attached to any environment or destination or server
try {
diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php
index 37266ca5d..bba2da818 100644
--- a/app/Console/Kernel.php
+++ b/app/Console/Kernel.php
@@ -120,8 +120,8 @@ class Kernel extends ConsoleKernel
return;
}
foreach ($scheduled_tasks as $scheduled_task) {
- $service = $scheduled_task->service()->get();
- $application = $scheduled_task->application()->get();
+ $service = $scheduled_task->service;
+ $application = $scheduled_task->application;
if (!$application && !$service) {
ray('application/service attached to scheduled task does not exist');
diff --git a/app/Jobs/ServerStatusJob.php b/app/Jobs/ServerStatusJob.php
index b327c3a7c..d0243fa9a 100644
--- a/app/Jobs/ServerStatusJob.php
+++ b/app/Jobs/ServerStatusJob.php
@@ -16,7 +16,7 @@ class ServerStatusJob implements ShouldQueue, ShouldBeEncrypted
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
- public ?int $disk_usage = null;
+ public int|string|null $disk_usage = null;
public $tries = 4;
public function backoff(): int
{
diff --git a/app/Livewire/Project/Service/FileStorage.php b/app/Livewire/Project/Service/FileStorage.php
index ab7736c97..da85a1a6e 100644
--- a/app/Livewire/Project/Service/FileStorage.php
+++ b/app/Livewire/Project/Service/FileStorage.php
@@ -41,7 +41,7 @@ class FileStorage extends Component
$this->fileStorage->content = null;
}
$this->fileStorage->save();
- $this->fileStorage->saveStorageOnServer($this->service);
+ $this->fileStorage->saveStorageOnServer();
$this->dispatch('success', 'File updated successfully.');
} catch (\Throwable $e) {
$this->fileStorage->setRawAttributes($original);
diff --git a/app/Models/Application.php b/app/Models/Application.php
index 0ba1d24d1..b37476565 100644
--- a/app/Models/Application.php
+++ b/app/Models/Application.php
@@ -48,6 +48,9 @@ class Application extends BaseModel
$application->persistentStorages()->delete();
$application->environment_variables()->delete();
$application->environment_variables_preview()->delete();
+ foreach ($application->scheduled_tasks as $task) {
+ $task->delete();
+ }
$application->tags()->detach();
});
}
diff --git a/app/Models/LocalFileVolume.php b/app/Models/LocalFileVolume.php
index 6750f2dc4..76a15f655 100644
--- a/app/Models/LocalFileVolume.php
+++ b/app/Models/LocalFileVolume.php
@@ -13,24 +13,34 @@ class LocalFileVolume extends BaseModel
protected static function booted()
{
static::created(function (LocalFileVolume $fileVolume) {
- $fileVolume->saveStorageOnServer($fileVolume->service);
+ $fileVolume->load(['service']);
+ $fileVolume->saveStorageOnServer();
});
}
public function service()
{
return $this->morphTo('resource');
}
- public function saveStorageOnServer(ServiceApplication|ServiceDatabase $service)
+ public function saveStorageOnServer()
{
- ray('saveStorageOnServer');
- $workdir = $service->service->workdir();
- $server = $service->service->server;
+ $workdir = $this->resource->service->workdir();
+ $server = $this->resource->service->server;
$commands = collect([
"mkdir -p $workdir > /dev/null 2>&1 || true",
"cd $workdir"
]);
+ $is_directory = $this->is_directory;
+ if ($is_directory) {
+ $commands->push("mkdir -p $this->fs_path > /dev/null 2>&1 || true");
+ }
+ if (str($this->fs_path)->startsWith('.') || str($this->fs_path)->startsWith('/') || str($this->fs_path)->startsWith('~')) {
+ $parent_dir = str($this->fs_path)->beforeLast('/');
+ if ($parent_dir != '') {
+ $commands->push("mkdir -p $parent_dir > /dev/null 2>&1 || true");
+ }
+ }
$fileVolume = $this;
- $path = Str::of(data_get($fileVolume, 'fs_path'));
+ $path = str(data_get($fileVolume, 'fs_path'));
$content = data_get($fileVolume, 'content');
if ($path->startsWith('.')) {
$path = $path->after('.');
@@ -39,17 +49,18 @@ class LocalFileVolume extends BaseModel
$isFile = instant_remote_process(["test -f $path && echo OK || echo NOK"], $server);
$isDir = instant_remote_process(["test -d $path && echo OK || echo NOK"], $server);
if ($isFile == 'OK' && $fileVolume->is_directory) {
- throw new \Exception("File $path is a file on the server, but you are trying to mark it as a directory. Please delete the file on the server or mark it as directory.");
+ throw new \Exception("The following file is a file on the server, but you are trying to mark it as a directory. Please delete the file on the server or mark it as directory.");
} else if ($isDir == 'OK' && !$fileVolume->is_directory) {
- throw new \Exception("File $path is a directory on the server, but you are trying to mark it as a file. Please delete the directory on the server or mark it as directory.");
+ throw new \Exception("The following file is a directory on the server, but you are trying to mark it as a file.
Please delete the directory on the server or mark it as directory.");
}
if (!$fileVolume->is_directory && $isDir == 'NOK') {
- $content = base64_encode($content);
- $commands->push("echo '$content' | base64 -d > $path");
+ if ($content) {
+ $content = base64_encode($content);
+ $commands->push("echo '$content' | base64 -d > $path");
+ }
} else if ($isDir == 'NOK' && $fileVolume->is_directory) {
$commands->push("mkdir -p $path > /dev/null 2>&1 || true");
}
- ray($commands->toArray());
return instant_remote_process($commands, $server);
}
}
diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php
index 10d8f313b..9ab26e59a 100644
--- a/bootstrap/helpers/shared.php
+++ b/bootstrap/helpers/shared.php
@@ -125,6 +125,9 @@ function handleError(?Throwable $error = null, ?Livewire\Component $livewire = n
}
if (isset($livewire)) {
+ if (str($message)->length() > 20) {
+ return $livewire->dispatch('error', 'Error occured', $message);
+ }
return $livewire->dispatch('error', $message);
}
throw new Exception($message);
@@ -527,28 +530,32 @@ function getTopLevelNetworks(Service|Application $resource)
$definedNetwork = collect([$resource->uuid]);
$services = collect($services)->map(function ($service, $_) use ($topLevelNetworks, $definedNetwork) {
$serviceNetworks = collect(data_get($service, 'networks', []));
+ $hasHostNetworkMode = data_get($service, 'network_mode') === 'host' ? true : false;
- // Collect/create/update networks
- if ($serviceNetworks->count() > 0) {
- foreach ($serviceNetworks as $networkName => $networkDetails) {
- $networkExists = $topLevelNetworks->contains(function ($value, $key) use ($networkName) {
- return $value == $networkName || $key == $networkName;
- });
- if (!$networkExists) {
- $topLevelNetworks->put($networkDetails, null);
+ // Only add 'networks' key if 'network_mode' is not 'host'
+ if (!$hasHostNetworkMode) {
+ // Collect/create/update networks
+ if ($serviceNetworks->count() > 0) {
+ foreach ($serviceNetworks as $networkName => $networkDetails) {
+ $networkExists = $topLevelNetworks->contains(function ($value, $key) use ($networkName) {
+ return $value == $networkName || $key == $networkName;
+ });
+ if (!$networkExists) {
+ $topLevelNetworks->put($networkDetails, null);
+ }
}
}
- }
- $definedNetworkExists = $topLevelNetworks->contains(function ($value, $_) use ($definedNetwork) {
- return $value == $definedNetwork;
- });
- if (!$definedNetworkExists) {
- foreach ($definedNetwork as $network) {
- $topLevelNetworks->put($network, [
- 'name' => $network,
- 'external' => true
- ]);
+ $definedNetworkExists = $topLevelNetworks->contains(function ($value, $_) use ($definedNetwork) {
+ return $value == $definedNetwork;
+ });
+ if (!$definedNetworkExists) {
+ foreach ($definedNetwork as $network) {
+ $topLevelNetworks->put($network, [
+ 'name' => $network,
+ 'external' => true
+ ]);
+ }
}
}
@@ -628,6 +635,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
$serviceNetworks = collect(data_get($service, 'networks', []));
$serviceVariables = collect(data_get($service, 'environment', []));
$serviceLabels = collect(data_get($service, 'labels', []));
+ $hasHostNetworkMode = data_get($service, 'network_mode') === 'host' ? true : false;
if ($serviceLabels->count() > 0) {
$removedLabels = collect([]);
$serviceLabels = $serviceLabels->filter(function ($serviceLabel, $serviceLabelName) use ($removedLabels) {
@@ -698,7 +706,6 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
$savedService->image = $image;
$savedService->save();
}
-
// Collect/create/update networks
if ($serviceNetworks->count() > 0) {
foreach ($serviceNetworks as $networkName => $networkDetails) {
@@ -729,37 +736,39 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
$savedService->ports = $collectedPorts->implode(',');
$savedService->save();
- // Add Coolify specific networks
- $definedNetworkExists = $topLevelNetworks->contains(function ($value, $_) use ($definedNetwork) {
- return $value == $definedNetwork;
- });
- if (!$definedNetworkExists) {
- foreach ($definedNetwork as $network) {
- $topLevelNetworks->put($network, [
- 'name' => $network,
- 'external' => true
- ]);
+ if (!$hasHostNetworkMode) {
+ // Add Coolify specific networks
+ $definedNetworkExists = $topLevelNetworks->contains(function ($value, $_) use ($definedNetwork) {
+ return $value == $definedNetwork;
+ });
+ if (!$definedNetworkExists) {
+ foreach ($definedNetwork as $network) {
+ $topLevelNetworks->put($network, [
+ 'name' => $network,
+ 'external' => true
+ ]);
+ }
}
- }
- $networks = collect();
- foreach ($serviceNetworks as $key => $serviceNetwork) {
- if (gettype($serviceNetwork) === 'string') {
- // networks:
- // - appwrite
- $networks->put($serviceNetwork, null);
- } else if (gettype($serviceNetwork) === 'array') {
- // networks:
- // default:
- // ipv4_address: 192.168.203.254
- // $networks->put($serviceNetwork, null);
- ray($key);
- $networks->put($key, $serviceNetwork);
+ $networks = collect();
+ foreach ($serviceNetworks as $key => $serviceNetwork) {
+ if (gettype($serviceNetwork) === 'string') {
+ // networks:
+ // - appwrite
+ $networks->put($serviceNetwork, null);
+ } else if (gettype($serviceNetwork) === 'array') {
+ // networks:
+ // default:
+ // ipv4_address: 192.168.203.254
+ // $networks->put($serviceNetwork, null);
+ ray($key);
+ $networks->put($key, $serviceNetwork);
+ }
}
+ foreach ($definedNetwork as $key => $network) {
+ $networks->put($network, null);
+ }
+ data_set($service, 'networks', $networks->toArray());
}
- foreach ($definedNetwork as $key => $network) {
- $networks->put($network, null);
- }
- data_set($service, 'networks', $networks->toArray());
// Collect/create/update volumes
if ($serviceVolumes->count() > 0) {
diff --git a/config/sentry.php b/config/sentry.php
index b4d0a5bb8..071a24929 100644
--- a/config/sentry.php
+++ b/config/sentry.php
@@ -7,7 +7,7 @@ return [
// The release version of your application
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
- 'release' => '4.0.0-beta.215',
+ 'release' => '4.0.0-beta.216',
// When left empty or `null` the Laravel environment will be used
'environment' => config('app.env'),
diff --git a/config/version.php b/config/version.php
index 5160b78a0..e1bf71945 100644
--- a/config/version.php
+++ b/config/version.php
@@ -1,3 +1,3 @@