diff --git a/app/Actions/CoolifyTask/RunRemoteProcess.php b/app/Actions/CoolifyTask/RunRemoteProcess.php index 842bdd2ac..cdbf6813c 100644 --- a/app/Actions/CoolifyTask/RunRemoteProcess.php +++ b/app/Actions/CoolifyTask/RunRemoteProcess.php @@ -5,6 +5,7 @@ use App\Enums\ActivityTypes; use App\Enums\ProcessStatus; use App\Jobs\ApplicationDeploymentJob; +use App\Models\Server; use Illuminate\Process\ProcessResult; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Process; @@ -94,7 +95,7 @@ public function __invoke(): ProcessResult ]); $this->activity->save(); if ($processResult->exitCode() != 0 && !$this->ignore_errors) { - throw new \RuntimeException($processResult->errorOutput()); + throw new \RuntimeException($processResult->errorOutput(), $processResult->exitCode()); } return $processResult; @@ -102,12 +103,11 @@ public function __invoke(): ProcessResult protected function getCommand(): string { - $user = $this->activity->getExtraProperty('user'); - $server_ip = $this->activity->getExtraProperty('server_ip'); - $port = $this->activity->getExtraProperty('port'); + $server_uuid = $this->activity->getExtraProperty('server_uuid'); $command = $this->activity->getExtraProperty('command'); + $server = Server::whereUuid($server_uuid)->firstOrFail(); - return generateSshCommand($server_ip, $user, $port, $command); + return generateSshCommand($server, $command); } protected function handleOutput(string $type, string $output) diff --git a/app/Actions/Proxy/StartProxy.php b/app/Actions/Proxy/StartProxy.php index 7e2878b7e..343d2328e 100644 --- a/app/Actions/Proxy/StartProxy.php +++ b/app/Actions/Proxy/StartProxy.php @@ -27,6 +27,10 @@ public function __invoke(Server $server, bool $async = true): Activity|string $server->proxy->last_applied_settings = Str::of($docker_compose_yml_base64)->pipe('md5')->value; $server->save(); $commands = [ + "command -v lsof >/dev/null || echo '####### Installing lsof...'", + "command -v lsof >/dev/null || apt-get update", + "command -v lsof >/dev/null || apt install -y lsof", + "command -v lsof >/dev/null || command -v fuser >/dev/null || apt install -y psmisc", "echo '####### Creating required Docker networks...'", ...$create_networks_command, "cd $proxy_path", @@ -35,8 +39,11 @@ public function __invoke(Server $server, bool $async = true): Activity|string 'docker compose pull', "echo '####### Stopping existing coolify-proxy...'", 'docker compose down -v --remove-orphans', - "lsof -nt -i:80 | xargs -r kill -9", - "lsof -nt -i:443 | xargs -r kill -9", + "command -v lsof >/dev/null && lsof -nt -i:80 | xargs -r kill -9", + "command -v lsof >/dev/null && lsof -nt -i:443 | xargs -r kill -9", + "command -v fuser >/dev/null && fuser -k 80/tcp", + "command -v fuser >/dev/null && fuser -k 443/tcp", + "command -v fuser >/dev/null || command -v lsof >/dev/null || echo '####### Could not kill existing processes listening on port 80 & 443. Please stop the process holding these ports...'", "systemctl disable nginx > /dev/null 2>&1 || true", "systemctl disable apache2 > /dev/null 2>&1 || true", "systemctl disable apache > /dev/null 2>&1 || true", diff --git a/app/Data/CoolifyTaskArgs.php b/app/Data/CoolifyTaskArgs.php index 44e62147c..07d7c0c81 100644 --- a/app/Data/CoolifyTaskArgs.php +++ b/app/Data/CoolifyTaskArgs.php @@ -12,10 +12,8 @@ class CoolifyTaskArgs extends Data { public function __construct( - public string $server_ip, + public string $server_uuid, public string $command, - public int $port, - public string $user, public string $type, public ?string $type_uuid = null, public ?Model $model = null, diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 8fe4a1130..9bfde1793 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -45,8 +45,11 @@ class Handler extends ExceptionHandler public function register(): void { $this->reportable(function (Throwable $e) { + if (isDev()) { + return; + } $this->settings = InstanceSettings::get(); - if ($this->settings->do_not_track || isDev()) { + if ($this->settings->do_not_track) { return; } app('sentry')->configureScope( diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 0794d2507..0f4934846 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -14,7 +14,6 @@ use Illuminate\Support\Facades\Crypt; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Str; -use Throwable; class Controller extends BaseController { @@ -153,7 +152,7 @@ public function acceptInvitation() } else { abort(401); } - } catch (Throwable $e) { + } catch (\Throwable $e) { ray($e->getMessage()); throw $e; } @@ -172,7 +171,7 @@ public function revokeInvitation() } $invitation->delete(); return redirect()->route('team.index'); - } catch (Throwable $e) { + } catch (\Throwable $e) { throw $e; } } diff --git a/app/Http/Livewire/Boarding/Index.php b/app/Http/Livewire/Boarding/Index.php index 77675441d..0a20c68fc 100644 --- a/app/Http/Livewire/Boarding/Index.php +++ b/app/Http/Livewire/Boarding/Index.php @@ -9,6 +9,7 @@ use App\Models\Team; use Illuminate\Support\Collection; use Livewire\Component; +use Visus\Cuid2\Cuid2; class Index extends Component { @@ -53,7 +54,8 @@ public function mount() $this->remoteServerHost = 'coolify-testing-host'; } } - public function explanation() { + public function explanation() + { if (isCloud()) { return $this->setServerType('remote'); } @@ -115,7 +117,8 @@ public function selectExistingServer() $this->getProxyType(); $this->getProjects(); } - public function getProxyType() { + public function getProxyType() + { $proxyTypeSet = $this->createdServer->proxy->type; if (!$proxyTypeSet) { $this->currentState = 'select-proxy'; @@ -153,49 +156,68 @@ public function saveServer() { $this->validate([ 'remoteServerName' => 'required', - 'remoteServerHost' => 'required', - 'remoteServerPort' => 'required', + 'remoteServerHost' => 'required|ip', + 'remoteServerPort' => 'required|integer', 'remoteServerUser' => 'required', ]); $this->privateKey = formatPrivateKey($this->privateKey); - $this->createdPrivateKey = PrivateKey::create([ - 'name' => $this->privateKeyName, - 'description' => $this->privateKeyDescription, - 'private_key' => $this->privateKey, - 'team_id' => currentTeam()->id - ]); - $this->createdServer = Server::create([ - 'name' => $this->remoteServerName, - 'ip' => $this->remoteServerHost, - 'port' => $this->remoteServerPort, - 'user' => $this->remoteServerUser, - 'description' => $this->remoteServerDescription, - 'private_key_id' => $this->createdPrivateKey->id, - 'team_id' => currentTeam()->id - ]); + $this->createdPrivateKey = new PrivateKey(); + $this->createdPrivateKey->private_key = $this->privateKey; + $this->createdPrivateKey->name = $this->privateKeyName; + $this->createdPrivateKey->description = $this->privateKeyDescription; + $this->createdPrivateKey->team_id = currentTeam()->id; + $foundServer = Server::whereIp($this->remoteServerHost)->first(); + if ($foundServer) { + return $this->emit('error', 'IP address is already in use by another team.'); + } + $this->createdServer = new Server(); + $this->createdServer->uuid = (string)new Cuid2(7); + $this->createdServer->name = $this->remoteServerName; + $this->createdServer->ip = $this->remoteServerHost; + $this->createdServer->port = $this->remoteServerPort; + $this->createdServer->user = $this->remoteServerUser; + $this->createdServer->description = $this->remoteServerDescription; + $this->createdServer->privateKey = $this->createdPrivateKey; + $this->createdServer->team_id = currentTeam()->id; + + ray($this->createdServer); + + $this->validateServer(); } - public function validateServer() { + public function validateServer() + { try { - ['uptime' => $uptime, 'dockerVersion' => $dockerVersion] = validateServer($this->createdServer); - if (!$uptime) { - throw new \Exception('Server is not reachable.'); - } else { - $this->createdServer->settings->update([ - 'is_reachable' => true, - ]); - $this->emit('success', 'Server is reachable.'); - } - ray($dockerVersion, $uptime); - if (!$dockerVersion) { - $this->emit('error', 'Docker is not installed on the server.'); - $this->currentState = 'install-docker'; - return; + $customErrorMessage = "Server is not reachable:"; + config()->set('coolify.mux_enabled', false); + instant_remote_process(['uptime'], $this->createdServer, true); + $dockerVersion = instant_remote_process(["docker version|head -2|grep -i version| awk '{print $2}'"], $this->createdServer, true); + $dockerVersion = checkMinimumDockerEngineVersion($dockerVersion); + if (is_null($dockerVersion)) { + throw new \Exception('No Docker Engine or older than 23 version installed.'); } + $customErrorMessage = "Cannot create Server or Private Key. Please try again."; + $createdPrivateKey = PrivateKey::create([ + 'name' => $this->privateKeyName, + 'description' => $this->privateKeyDescription, + 'private_key' => $this->privateKey, + 'team_id' => currentTeam()->id + ]); + $server = Server::create([ + 'name' => $this->remoteServerName, + 'ip' => $this->remoteServerHost, + 'port' => $this->remoteServerPort, + 'user' => $this->remoteServerUser, + 'description' => $this->remoteServerDescription, + 'private_key_id' => $createdPrivateKey->id, + 'team_id' => currentTeam()->id, + ]); + $server->settings->is_reachable = true; + $server->settings->is_usable = true; + $server->settings->save(); $this->getProxyType(); - } catch (\Throwable $e) { - return general_error_handler(customErrorMessage: "Server is not reachable. Reason: {$e->getMessage()}", that: $this); + return handleError(error: $e, customErrorMessage: $customErrorMessage, livewire: $this); } } public function installDocker() @@ -215,14 +237,16 @@ public function selectProxy(string|null $proxyType = null) $this->getProjects(); } - public function getProjects() { + public function getProjects() + { $this->projects = Project::ownedByCurrentTeam(['name'])->get(); if ($this->projects->count() > 0) { $this->selectedExistingProject = $this->projects->first()->id; } $this->currentState = 'create-project'; } - public function selectExistingProject() { + public function selectExistingProject() + { $this->createdProject = Project::find($this->selectedExistingProject); $this->currentState = 'create-resource'; } @@ -242,7 +266,7 @@ public function showNewResource() [ 'project_uuid' => $this->createdProject->uuid, 'environment_name' => 'production', - 'server'=> $this->createdServer->id, + 'server' => $this->createdServer->id, ] ); } diff --git a/app/Http/Livewire/Destination/Form.php b/app/Http/Livewire/Destination/Form.php index 9bfb8cf74..632a26370 100644 --- a/app/Http/Livewire/Destination/Form.php +++ b/app/Http/Livewire/Destination/Form.php @@ -38,7 +38,7 @@ public function delete() $this->destination->delete(); return redirect()->route('dashboard'); } catch (\Throwable $e) { - return general_error_handler(err: $e); + return handleError($e); } } } diff --git a/app/Http/Livewire/Destination/New/StandaloneDocker.php b/app/Http/Livewire/Destination/New/StandaloneDocker.php index 519b1e700..9f928d81e 100644 --- a/app/Http/Livewire/Destination/New/StandaloneDocker.php +++ b/app/Http/Livewire/Destination/New/StandaloneDocker.php @@ -72,7 +72,7 @@ public function submit() $this->createNetworkAndAttachToProxy(); return redirect()->route('destination.show', $docker->uuid); } catch (\Throwable $e) { - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } } diff --git a/app/Http/Livewire/ForcePasswordReset.php b/app/Http/Livewire/ForcePasswordReset.php index 732859280..64612faf9 100644 --- a/app/Http/Livewire/ForcePasswordReset.php +++ b/app/Http/Livewire/ForcePasswordReset.php @@ -37,7 +37,7 @@ public function submit() } return redirect()->route('dashboard'); } catch (\Throwable $e) { - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } } } diff --git a/app/Http/Livewire/Help.php b/app/Http/Livewire/Help.php index 79d7db1ee..e0ce53d63 100644 --- a/app/Http/Livewire/Help.php +++ b/app/Http/Livewire/Help.php @@ -44,7 +44,7 @@ public function submit() send_user_an_email($mail, auth()->user()?->email, 'hi@coollabs.io'); $this->emit('success', 'Your message has been sent successfully. We will get in touch with you as soon as possible.'); } catch (\Throwable $e) { - return general_error_handler($e, $this); + return handleError($e, $this); } } public function render() diff --git a/app/Http/Livewire/Notifications/EmailSettings.php b/app/Http/Livewire/Notifications/EmailSettings.php index 5bbf846f4..33283d16b 100644 --- a/app/Http/Livewire/Notifications/EmailSettings.php +++ b/app/Http/Livewire/Notifications/EmailSettings.php @@ -64,7 +64,7 @@ public function submitFromFields() $this->team->save(); $this->emit('success', 'Settings saved successfully.'); } catch (\Throwable $e) { - return general_error_handler($e, $this); + return handleError($e, $this); } } public function sendTestNotification() @@ -83,7 +83,7 @@ public function instantSaveInstance() $this->team->save(); $this->emit('success', 'Settings saved successfully.'); } catch (\Throwable $e) { - return general_error_handler($e, $this); + return handleError($e, $this); } } @@ -94,7 +94,7 @@ public function instantSaveResend() $this->submitResend(); } catch (\Throwable $e) { $this->team->smtp_enabled = false; - return general_error_handler($e, $this); + return handleError($e, $this); } } public function instantSave() @@ -104,7 +104,7 @@ public function instantSave() $this->submit(); } catch (\Throwable $e) { $this->team->smtp_enabled = false; - return general_error_handler($e, $this); + return handleError($e, $this); } } public function saveModel() @@ -130,7 +130,7 @@ public function submit() $this->emit('success', 'Settings saved successfully.'); } catch (\Throwable $e) { $this->team->smtp_enabled = false; - return general_error_handler($e, $this); + return handleError($e, $this); } } public function submitResend() @@ -146,7 +146,7 @@ public function submitResend() $this->emit('success', 'Settings saved successfully.'); } catch (\Throwable $e) { $this->team->resend_enabled = false; - return general_error_handler($e, $this); + return handleError($e, $this); } } public function copyFromInstanceSettings() diff --git a/app/Http/Livewire/PrivateKey/Change.php b/app/Http/Livewire/PrivateKey/Change.php index a85bac8d2..742212396 100644 --- a/app/Http/Livewire/PrivateKey/Change.php +++ b/app/Http/Livewire/PrivateKey/Change.php @@ -25,8 +25,8 @@ public function mount() { try { $this->public_key = $this->private_key->publicKey(); - }catch(\Exception $e) { - return general_error_handler(err: $e, that: $this); + }catch(\Throwable $e) { + return handleError($e, $this); } } public function delete() @@ -39,7 +39,7 @@ public function delete() } $this->emit('error', 'This private key is in use and cannot be deleted. Please delete all servers, applications, and GitHub/GitLab apps that use this private key before deleting it.'); } catch (\Throwable $e) { - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } } @@ -50,7 +50,7 @@ public function changePrivateKey() $this->private_key->save(); refresh_server_connection($this->private_key); } catch (\Throwable $e) { - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } } } diff --git a/app/Http/Livewire/PrivateKey/Create.php b/app/Http/Livewire/PrivateKey/Create.php index c48b4490e..cf8414b3e 100644 --- a/app/Http/Livewire/PrivateKey/Create.php +++ b/app/Http/Livewire/PrivateKey/Create.php @@ -58,7 +58,7 @@ public function createPrivateKey() } return redirect()->route('security.private-key.show', ['private_key_uuid' => $private_key->uuid]); } catch (\Throwable $e) { - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } } } diff --git a/app/Http/Livewire/Profile/Form.php b/app/Http/Livewire/Profile/Form.php index 926d638f1..728830702 100644 --- a/app/Http/Livewire/Profile/Form.php +++ b/app/Http/Livewire/Profile/Form.php @@ -34,7 +34,7 @@ public function submit() 'name' => $this->name, ]); } catch (\Throwable $e) { - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } } } diff --git a/app/Http/Livewire/Project/AddEmpty.php b/app/Http/Livewire/Project/AddEmpty.php index 8d2399a47..0f6c9873e 100644 --- a/app/Http/Livewire/Project/AddEmpty.php +++ b/app/Http/Livewire/Project/AddEmpty.php @@ -29,7 +29,7 @@ public function submit() ]); return redirect()->route('project.show', $project->uuid); } catch (\Throwable $e) { - general_error_handler($e, $this); + return handleError($e, $this); } finally { $this->name = ''; } diff --git a/app/Http/Livewire/Project/AddEnvironment.php b/app/Http/Livewire/Project/AddEnvironment.php index fc0ac61c6..334dd78f9 100644 --- a/app/Http/Livewire/Project/AddEnvironment.php +++ b/app/Http/Livewire/Project/AddEnvironment.php @@ -32,7 +32,7 @@ public function submit() 'environment_name' => $environment->name, ]); } catch (\Throwable $e) { - general_error_handler($e, $this); + handleError($e, $this); } finally { $this->name = ''; } diff --git a/app/Http/Livewire/Project/Application/DeploymentNavbar.php b/app/Http/Livewire/Project/Application/DeploymentNavbar.php index 1646d46e0..b0cad0395 100644 --- a/app/Http/Livewire/Project/Application/DeploymentNavbar.php +++ b/app/Http/Livewire/Project/Application/DeploymentNavbar.php @@ -65,7 +65,7 @@ public function cancel() ]); } } catch (\Throwable $e) { - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } } } diff --git a/app/Http/Livewire/Project/Application/General.php b/app/Http/Livewire/Project/Application/General.php index bd0006b23..cb66a4ac2 100644 --- a/app/Http/Livewire/Project/Application/General.php +++ b/app/Http/Livewire/Project/Application/General.php @@ -160,7 +160,7 @@ public function submit() $this->application->save(); $this->emit('success', 'Application settings updated!'); } catch (\Throwable $e) { - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } } } diff --git a/app/Http/Livewire/Project/Application/Previews.php b/app/Http/Livewire/Project/Application/Previews.php index afe8a16f9..59cf38185 100644 --- a/app/Http/Livewire/Project/Application/Previews.php +++ b/app/Http/Livewire/Project/Application/Previews.php @@ -30,7 +30,7 @@ public function load_prs() $this->pull_requests = $data->sortBy('number')->values(); } catch (\Throwable $e) { $this->rate_limit_remaining = 0; - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } } @@ -59,7 +59,7 @@ public function deploy(int $pull_request_id, string|null $pull_request_html_url 'environment_name' => $this->parameters['environment_name'], ]); } catch (\Throwable $e) { - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } } @@ -79,7 +79,7 @@ public function stop(int $pull_request_id) ApplicationPreview::where('application_id', $this->application->id)->where('pull_request_id', $pull_request_id)->delete(); $this->application->refresh(); } catch (\Throwable $e) { - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } } diff --git a/app/Http/Livewire/Project/Application/Rollback.php b/app/Http/Livewire/Project/Application/Rollback.php index d4ac53045..1d73b7c85 100644 --- a/app/Http/Livewire/Project/Application/Rollback.php +++ b/app/Http/Livewire/Project/Application/Rollback.php @@ -65,7 +65,7 @@ public function loadImages() ]; })->toArray(); } catch (\Throwable $e) { - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } } } diff --git a/app/Http/Livewire/Project/Database/CreateScheduledBackup.php b/app/Http/Livewire/Project/Database/CreateScheduledBackup.php index d9887efbf..8fcd89a0b 100644 --- a/app/Http/Livewire/Project/Database/CreateScheduledBackup.php +++ b/app/Http/Livewire/Project/Database/CreateScheduledBackup.php @@ -43,7 +43,7 @@ public function submit(): void ]); $this->emit('refreshScheduledBackups'); } catch (\Throwable $e) { - general_error_handler($e, $this); + handleError($e, $this); } finally { $this->frequency = ''; $this->save_s3 = true; diff --git a/app/Http/Livewire/Project/Database/Heading.php b/app/Http/Livewire/Project/Database/Heading.php index f2fe8f033..60144073e 100644 --- a/app/Http/Livewire/Project/Database/Heading.php +++ b/app/Http/Livewire/Project/Database/Heading.php @@ -35,7 +35,7 @@ public function mount() public function stop() { - remote_process( + instant_remote_process( ["docker rm -f {$this->database->uuid}"], $this->database->destination->server ); @@ -45,7 +45,7 @@ public function stop() } $this->database->status = 'stopped'; $this->database->save(); - $this->emit('refresh'); + $this->check_status(); // $this->database->environment->project->team->notify(new StatusChanged($this->database)); } diff --git a/app/Http/Livewire/Project/Database/InitScript.php b/app/Http/Livewire/Project/Database/InitScript.php index ba70b75d3..a371bb33e 100644 --- a/app/Http/Livewire/Project/Database/InitScript.php +++ b/app/Http/Livewire/Project/Database/InitScript.php @@ -36,7 +36,7 @@ public function submit() $this->script['filename'] = $this->filename; $this->emitUp('save_init_script', $this->script); } catch (Exception $e) { - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } } diff --git a/app/Http/Livewire/Project/Database/Postgresql/General.php b/app/Http/Livewire/Project/Database/Postgresql/General.php index b96ecf3e3..9045eee69 100644 --- a/app/Http/Livewire/Project/Database/Postgresql/General.php +++ b/app/Http/Livewire/Project/Database/Postgresql/General.php @@ -5,6 +5,7 @@ use App\Models\StandalonePostgresql; use Exception; use Livewire\Component; + use function Aws\filter; class General extends Component @@ -73,9 +74,9 @@ public function instantSave() } $this->getDbUrl(); $this->database->save(); - } catch(Exception $e) { + } catch(\Throwable $e) { $this->database->is_public = !$this->database->is_public; - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } } @@ -140,7 +141,7 @@ public function submit() $this->database->save(); $this->emit('success', 'Database updated successfully.'); } catch (Exception $e) { - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } } } diff --git a/app/Http/Livewire/Project/Edit.php b/app/Http/Livewire/Project/Edit.php index 9d5342b5a..94b6979ae 100644 --- a/app/Http/Livewire/Project/Edit.php +++ b/app/Http/Livewire/Project/Edit.php @@ -20,7 +20,7 @@ public function submit() $this->project->save(); $this->emit('saved'); } catch (\Throwable $e) { - return general_error_handler($e, $this); + return handleError($e, $this); } } } diff --git a/app/Http/Livewire/Project/New/GithubPrivateRepository.php b/app/Http/Livewire/Project/New/GithubPrivateRepository.php index cf371404a..3594e671b 100644 --- a/app/Http/Livewire/Project/New/GithubPrivateRepository.php +++ b/app/Http/Livewire/Project/New/GithubPrivateRepository.php @@ -165,7 +165,7 @@ public function submit() 'project_uuid' => $project->uuid, ]); } catch (\Throwable $e) { - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } } diff --git a/app/Http/Livewire/Project/New/GithubPrivateRepositoryDeployKey.php b/app/Http/Livewire/Project/New/GithubPrivateRepositoryDeployKey.php index 21fa87e42..6dbf7cbf6 100644 --- a/app/Http/Livewire/Project/New/GithubPrivateRepositoryDeployKey.php +++ b/app/Http/Livewire/Project/New/GithubPrivateRepositoryDeployKey.php @@ -118,7 +118,7 @@ public function submit() 'application_uuid' => $application->uuid, ]); } catch (\Throwable $e) { - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } } diff --git a/app/Http/Livewire/Project/New/PublicGitRepository.php b/app/Http/Livewire/Project/New/PublicGitRepository.php index 105a56167..7f294ced1 100644 --- a/app/Http/Livewire/Project/New/PublicGitRepository.php +++ b/app/Http/Livewire/Project/New/PublicGitRepository.php @@ -76,14 +76,14 @@ public function load_branch() $this->get_branch(); $this->selected_branch = $this->git_branch; } catch (\Throwable $e) { - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } if (!$this->branch_found && $this->git_branch == 'main') { try { $this->git_branch = 'master'; $this->get_branch(); } catch (\Throwable $e) { - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } } } @@ -162,7 +162,7 @@ public function submit() 'application_uuid' => $application->uuid, ]); } catch (\Throwable $e) { - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } } } diff --git a/app/Http/Livewire/Project/New/Select.php b/app/Http/Livewire/Project/New/Select.php index 9a64a0e31..89a58d20e 100644 --- a/app/Http/Livewire/Project/New/Select.php +++ b/app/Http/Livewire/Project/New/Select.php @@ -41,7 +41,7 @@ public function mount() // instantCommand("psql {$this->existingPostgresqlUrl} -c 'SELECT 1'"); // $this->emit('success', 'Successfully connected to the database.'); // } catch (\Throwable $e) { - // return general_error_handler($e, $this); + // return handleError($e, $this); // } // } public function setType(string $type) diff --git a/app/Http/Livewire/Project/Shared/EnvironmentVariable/All.php b/app/Http/Livewire/Project/Shared/EnvironmentVariable/All.php index d73c644ef..bdb6ab50b 100644 --- a/app/Http/Livewire/Project/Shared/EnvironmentVariable/All.php +++ b/app/Http/Livewire/Project/Shared/EnvironmentVariable/All.php @@ -114,7 +114,7 @@ public function submit($data) $this->refreshEnvs(); $this->emit('success', 'Environment variable added successfully.'); } catch (\Throwable $e) { - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } } } diff --git a/app/Http/Livewire/Project/Shared/ResourceLimits.php b/app/Http/Livewire/Project/Shared/ResourceLimits.php index edf6702c6..5959cb9ac 100644 --- a/app/Http/Livewire/Project/Shared/ResourceLimits.php +++ b/app/Http/Livewire/Project/Shared/ResourceLimits.php @@ -54,7 +54,7 @@ public function submit() $this->resource->save(); $this->emit('success', 'Resource limits updated successfully.'); } catch (\Throwable $e) { - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } } } diff --git a/app/Http/Livewire/Project/Shared/Storages/All.php b/app/Http/Livewire/Project/Shared/Storages/All.php index db9dd19f5..30fa9e9e9 100644 --- a/app/Http/Livewire/Project/Shared/Storages/All.php +++ b/app/Http/Livewire/Project/Shared/Storages/All.php @@ -29,7 +29,7 @@ public function submit($data) $this->emit('success', 'Storage added successfully'); $this->emit('clearAddStorage'); } catch (\Throwable $e) { - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } } } diff --git a/app/Http/Livewire/RunCommand.php b/app/Http/Livewire/RunCommand.php index 2f0edc9da..b8f4c6af8 100755 --- a/app/Http/Livewire/RunCommand.php +++ b/app/Http/Livewire/RunCommand.php @@ -33,7 +33,7 @@ public function runCommand() $activity = remote_process([$this->command], Server::where('uuid', $this->server)->first(), ignore_errors: true); $this->emit('newMonitorActivity', $activity->id); } catch (\Throwable $e) { - return general_error_handler(err: $e); + return handleError($e, $this); } } } diff --git a/app/Http/Livewire/Server/Form.php b/app/Http/Livewire/Server/Form.php index 184c59704..56cec63da 100644 --- a/app/Http/Livewire/Server/Form.php +++ b/app/Http/Livewire/Server/Form.php @@ -51,12 +51,12 @@ public function installDocker() public function validateServer() { try { - ['uptime' => $uptime, 'dockerVersion' => $dockerVersion] = validateServer($this->server); + ['uptime' => $uptime, 'dockerVersion' => $dockerVersion] = validateServer($this->server, true); if ($uptime) { $this->uptime = $uptime; - $this->emit('success', 'Server is reachable!'); + $this->emit('success', 'Server is reachable.'); } else { - $this->emit('error', 'Server is not reachable'); + $this->emit('error', 'Server is not reachable.'); return; } if ($dockerVersion) { @@ -64,10 +64,10 @@ public function validateServer() $this->emit('proxyStatusUpdated'); $this->emit('success', 'Docker Engine 23+ is installed!'); } else { - $this->emit('error', 'Old (lower than 23) or no Docker version detected. Install Docker Engine on the General tab.'); + $this->emit('error', 'No Docker Engine or older than 23 version installed.'); } } catch (\Throwable $e) { - return general_error_handler($e, that: $this); + return handleError($e, $this, customErrorMessage: "Server is not reachable: "); } } @@ -82,7 +82,7 @@ public function delete() $this->server->delete(); return redirect()->route('server.all'); } catch (\Throwable $e) { - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } } public function submit() diff --git a/app/Http/Livewire/Server/New/ByIp.php b/app/Http/Livewire/Server/New/ByIp.php index 20377dc5d..f08b2ddb8 100644 --- a/app/Http/Livewire/Server/New/ByIp.php +++ b/app/Http/Livewire/Server/New/ByIp.php @@ -79,7 +79,7 @@ public function submit() $server->settings->save(); return redirect()->route('server.show', $server->uuid); } catch (\Throwable $e) { - return general_error_handler(err: $e); + return handleError($e); } } } diff --git a/app/Http/Livewire/Server/Proxy.php b/app/Http/Livewire/Server/Proxy.php index 174d426b5..d65518975 100644 --- a/app/Http/Livewire/Server/Proxy.php +++ b/app/Http/Livewire/Server/Proxy.php @@ -56,7 +56,7 @@ public function submit() setup_default_redirect_404(redirect_url: $this->server->proxy->redirect_url, server: $this->server); $this->emit('success', 'Proxy configuration saved.'); } catch (\Throwable $e) { - return general_error_handler(err: $e); + return handleError($e); } } @@ -65,7 +65,7 @@ public function reset_proxy_configuration() try { $this->proxy_settings = resolve(CheckConfigurationSync::class)($this->server, true); } catch (\Throwable $e) { - return general_error_handler(err: $e); + return handleError($e); } } @@ -75,7 +75,7 @@ public function loadProxyConfiguration() ray('loadProxyConfiguration'); $this->proxy_settings = resolve(CheckConfigurationSync::class)($this->server); } catch (\Throwable $e) { - return general_error_handler(err: $e); + return handleError($e); } } } diff --git a/app/Http/Livewire/Server/Proxy/Status.php b/app/Http/Livewire/Server/Proxy/Status.php index a0b90b7be..f808fdb81 100644 --- a/app/Http/Livewire/Server/Proxy/Status.php +++ b/app/Http/Livewire/Server/Proxy/Status.php @@ -24,7 +24,7 @@ public function getProxyStatus() $this->emit('proxyStatusUpdated'); } } catch (\Throwable $e) { - return general_error_handler(err: $e); + return handleError($e); } } public function getProxyStatusWithNoti() diff --git a/app/Http/Livewire/Server/Show.php b/app/Http/Livewire/Server/Show.php index 025fc82ff..79d39bb19 100644 --- a/app/Http/Livewire/Server/Show.php +++ b/app/Http/Livewire/Server/Show.php @@ -18,7 +18,7 @@ public function mount() return redirect()->route('server.all'); } } catch (\Throwable $e) { - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } } public function render() diff --git a/app/Http/Livewire/Server/ShowPrivateKey.php b/app/Http/Livewire/Server/ShowPrivateKey.php index 1ec98b8b2..c9054f7df 100644 --- a/app/Http/Livewire/Server/ShowPrivateKey.php +++ b/app/Http/Livewire/Server/ShowPrivateKey.php @@ -28,14 +28,14 @@ public function setPrivateKey($newPrivateKeyId) ]); $this->server->refresh(); refresh_server_connection($this->server->privateKey); - return general_error_handler($e, that: $this); + return handleError($e, $this); } } public function checkConnection() { try { - ['uptime' => $uptime, 'dockerVersion' => $dockerVersion] = validateServer($this->server); + ['uptime' => $uptime, 'dockerVersion' => $dockerVersion] = validateServer($this->server, true); if ($uptime) { $this->emit('success', 'Server is reachable with this private key.'); } else { @@ -48,7 +48,7 @@ public function checkConnection() $this->emit('error', 'Old (lower than 23) or no Docker version detected. Install Docker Engine on the General tab.'); } } catch (\Throwable $e) { - throw new \Exception($e->getMessage()); + return handleError($e, $this); } } diff --git a/app/Http/Livewire/Settings/Email.php b/app/Http/Livewire/Settings/Email.php index f03fccc46..85a4dc04d 100644 --- a/app/Http/Livewire/Settings/Email.php +++ b/app/Http/Livewire/Settings/Email.php @@ -51,7 +51,7 @@ public function submitFromFields() { $this->settings->save(); $this->emit('success', 'Settings saved successfully.'); } catch (\Throwable $e) { - return general_error_handler($e, $this); + return handleError($e, $this); } } public function submitResend() { @@ -64,7 +64,7 @@ public function submitResend() { $this->emit('success', 'Settings saved successfully.'); } catch (\Throwable $e) { $this->settings->resend_enabled = false; - return general_error_handler($e, $this); + return handleError($e, $this); } } public function instantSaveResend() { @@ -72,7 +72,7 @@ public function instantSaveResend() { $this->settings->smtp_enabled = false; $this->submitResend(); } catch (\Throwable $e) { - return general_error_handler($e, $this); + return handleError($e, $this); } } public function instantSave() @@ -81,7 +81,7 @@ public function instantSave() $this->settings->resend_enabled = false; $this->submit(); } catch (\Throwable $e) { - return general_error_handler($e, $this); + return handleError($e, $this); } } @@ -100,7 +100,7 @@ public function submit() $this->settings->save(); $this->emit('success', 'Settings saved successfully.'); } catch (\Throwable $e) { - return general_error_handler($e, $this); + return handleError($e, $this); } } diff --git a/app/Http/Livewire/Source/Github/Change.php b/app/Http/Livewire/Source/Github/Change.php index 41ce367d9..d0b717730 100644 --- a/app/Http/Livewire/Source/Github/Change.php +++ b/app/Http/Livewire/Source/Github/Change.php @@ -52,7 +52,7 @@ public function submit() $this->validate(); $this->github_app->save(); } catch (\Throwable $e) { - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } } @@ -66,7 +66,7 @@ public function delete() $this->github_app->delete(); redirect()->route('source.all'); } catch (\Throwable $e) { - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } } } diff --git a/app/Http/Livewire/Source/Github/Create.php b/app/Http/Livewire/Source/Github/Create.php index 83e6e2988..75951d946 100644 --- a/app/Http/Livewire/Source/Github/Create.php +++ b/app/Http/Livewire/Source/Github/Create.php @@ -50,7 +50,7 @@ public function createGitHubApp() } redirect()->route('source.github.show', ['github_app_uuid' => $github_app->uuid]); } catch (\Throwable $e) { - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } } } diff --git a/app/Http/Livewire/Subscription/Actions.php b/app/Http/Livewire/Subscription/Actions.php index 1ed3ca378..2f97e899d 100644 --- a/app/Http/Livewire/Subscription/Actions.php +++ b/app/Http/Livewire/Subscription/Actions.php @@ -31,7 +31,7 @@ public function cancel() $this->emit('reloadWindow', 5000); } } catch (\Throwable $e) { - return general_error_handler($e, $this); + return handleError($e, $this); } } public function resume() @@ -66,7 +66,7 @@ public function resume() $this->emit('reloadWindow', 5000); } } catch (\Throwable $e) { - return general_error_handler($e, $this); + return handleError($e, $this); } } public function stripeCustomerPortal() { diff --git a/app/Http/Livewire/Team/Create.php b/app/Http/Livewire/Team/Create.php index d5b80e53b..71d84d5ca 100644 --- a/app/Http/Livewire/Team/Create.php +++ b/app/Http/Livewire/Team/Create.php @@ -32,7 +32,7 @@ public function submit() refreshSession(); return redirect()->route('team.index'); } catch (\Throwable $e) { - return general_error_handler($e, $this); + return handleError($e, $this); } } } diff --git a/app/Http/Livewire/Team/Form.php b/app/Http/Livewire/Team/Form.php index febbf33a3..ba17140c4 100644 --- a/app/Http/Livewire/Team/Form.php +++ b/app/Http/Livewire/Team/Form.php @@ -28,7 +28,7 @@ public function submit() try { $this->team->save(); } catch (\Throwable $e) { - return general_error_handler($e, $this); + return handleError($e, $this); } } } diff --git a/app/Http/Livewire/Team/InviteLink.php b/app/Http/Livewire/Team/InviteLink.php index c22c54a61..8fea3a6b8 100644 --- a/app/Http/Livewire/Team/InviteLink.php +++ b/app/Http/Livewire/Team/InviteLink.php @@ -36,7 +36,7 @@ private function generate_invite_link(bool $sendEmail = false) try { $member_emails = currentTeam()->members()->get()->pluck('email'); if ($member_emails->contains($this->email)) { - return general_error_handler(that: $this, customErrorMessage: "$this->email is already a member of " . currentTeam()->name . "."); + return handleError(livewire: $this, customErrorMessage: "$this->email is already a member of " . currentTeam()->name . "."); } $uuid = new Cuid2(32); $link = url('/') . config('constants.invitation.link.base_url') . $uuid; @@ -57,7 +57,7 @@ private function generate_invite_link(bool $sendEmail = false) if (!is_null($invitation)) { $invitationValid = $invitation->isValid(); if ($invitationValid) { - return general_error_handler(that: $this, customErrorMessage: "Pending invitation already exists for $this->email."); + return handleError(livewire: $this, customErrorMessage: "Pending invitation already exists for $this->email."); } else { $invitation->delete(); } @@ -91,7 +91,7 @@ private function generate_invite_link(bool $sendEmail = false) if ($e->getCode() === '23505') { $error_message = 'Invitation already sent.'; } - return general_error_handler(err: $e, that: $this, customErrorMessage: $error_message); + return handleError(error: $e, livewire: $this, customErrorMessage: $error_message); } } } diff --git a/app/Http/Livewire/Team/Storage/Create.php b/app/Http/Livewire/Team/Storage/Create.php index 28e6f63c7..bcac861f8 100644 --- a/app/Http/Livewire/Team/Storage/Create.php +++ b/app/Http/Livewire/Team/Storage/Create.php @@ -68,7 +68,7 @@ public function submit() $this->storage->save(); return redirect()->route('team.storages.show', $this->storage->uuid); } catch (\Throwable $e) { - return general_error_handler($e, $this); + return handleError($e, $this); } } @@ -78,7 +78,7 @@ private function test_s3_connection() $this->storage->testConnection(); return $this->emit('success', 'Connection is working. Tested with "ListObjectsV2" action.'); } catch (\Throwable $e) { - return general_error_handler($e, $this); + return handleError($e, $this); } } } diff --git a/app/Http/Livewire/Team/Storage/Form.php b/app/Http/Livewire/Team/Storage/Form.php index 1572c45ac..223c5ac41 100644 --- a/app/Http/Livewire/Team/Storage/Form.php +++ b/app/Http/Livewire/Team/Storage/Form.php @@ -33,7 +33,7 @@ public function test_s3_connection() $this->storage->testConnection(); return $this->emit('success', 'Connection is working. Tested with "ListObjectsV2" action.'); } catch (\Throwable $e) { - return general_error_handler($e, $this); + return handleError($e, $this); } } @@ -43,7 +43,7 @@ public function delete() $this->storage->delete(); return redirect()->route('team.storages.all'); } catch (\Throwable $e) { - return general_error_handler($e, $this); + return handleError($e, $this); } } @@ -56,7 +56,7 @@ public function submit() $this->storage->save(); $this->emit('success', 'Storage settings saved.'); } catch (\Throwable $e) { - return general_error_handler($e, $this); + return handleError($e, $this); } } } diff --git a/app/Http/Livewire/Upgrade.php b/app/Http/Livewire/Upgrade.php index 69300b0eb..46f97027a 100644 --- a/app/Http/Livewire/Upgrade.php +++ b/app/Http/Livewire/Upgrade.php @@ -38,7 +38,7 @@ public function upgrade() resolve(UpdateCoolify::class)(true); Toaster::success("Upgrading to {$this->latestVersion} version..."); } catch (\Throwable $e) { - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } } } diff --git a/app/Http/Livewire/Waitlist/Index.php b/app/Http/Livewire/Waitlist/Index.php index 86f8d8929..06d92b6cb 100644 --- a/app/Http/Livewire/Waitlist/Index.php +++ b/app/Http/Livewire/Waitlist/Index.php @@ -54,7 +54,7 @@ public function submit() $this->emit('success', 'Check your email to verify your email address.'); dispatch(new SendConfirmationForWaitlistJob($this->email, $waitlist->uuid)); } catch (\Throwable $e) { - return general_error_handler(err: $e, that: $this); + return handleError($e, $this); } } } diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index dd6648603..484c8709e 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -177,7 +177,7 @@ private function deploy_simple_dockerfile() $this->prepare_builder_image(); $this->execute_remote_command( [ - $this->execute_in_builder("echo '$dockerfile_base64' | base64 -d > $this->workdir/Dockerfile") + executeInDocker($this->deployment_uuid, "echo '$dockerfile_base64' | base64 -d > $this->workdir/Dockerfile") ], ); $this->build_image_name = Str::lower("{$this->application->git_repository}:build"); @@ -302,7 +302,7 @@ private function deploy_pull_request() $this->stop_running_container(); $this->execute_remote_command( ["echo -n 'Starting preview deployment.'"], - [$this->execute_in_builder("docker compose --project-directory {$this->workdir} up -d >/dev/null"), "hidden" => true], + [executeInDocker($this->deployment_uuid, "docker compose --project-directory {$this->workdir} up -d >/dev/null"), "hidden" => true], ); } @@ -324,16 +324,12 @@ private function prepare_builder_image() "hidden" => true, ], [ - "command" => $this->execute_in_builder("mkdir -p {$this->workdir}") + "command" => executeInDocker($this->deployment_uuid, "mkdir -p {$this->workdir}") ], ); } - private function execute_in_builder(string $command) - { - return "docker exec {$this->deployment_uuid} bash -c '{$command}'"; - // return "docker exec {$this->deployment_uuid} bash -c '{$command} |& tee -a /proc/1/fd/1; [ \$PIPESTATUS -eq 0 ] || exit \$PIPESTATUS'"; - } + private function clone_repository() { @@ -345,7 +341,7 @@ private function clone_repository() $this->importing_git_repository() ], [ - $this->execute_in_builder("cd {$this->workdir} && git rev-parse HEAD"), + executeInDocker($this->deployment_uuid, "cd {$this->workdir} && git rev-parse HEAD"), "hidden" => true, "save" => "git_commit_sha" ], @@ -372,13 +368,13 @@ private function importing_git_repository() $git_clone_command = "{$git_clone_command} {$this->source->html_url}/{$this->application->git_repository} {$this->workdir}"; $git_clone_command = $this->set_git_import_settings($git_clone_command); - $commands->push($this->execute_in_builder($git_clone_command)); + $commands->push(executeInDocker($this->deployment_uuid, $git_clone_command)); } else { $github_access_token = generate_github_installation_token($this->source); - $commands->push($this->execute_in_builder("git clone -q -b {$this->application->git_branch} $source_html_url_scheme://x-access-token:$github_access_token@$source_html_url_host/{$this->application->git_repository}.git {$this->workdir}")); + $commands->push(executeInDocker($this->deployment_uuid, "git clone -q -b {$this->application->git_branch} $source_html_url_scheme://x-access-token:$github_access_token@$source_html_url_host/{$this->application->git_repository}.git {$this->workdir}")); } if ($this->pull_request_id !== 0) { - $commands->push($this->execute_in_builder("cd {$this->workdir} && git fetch origin pull/{$this->pull_request_id}/head:$pr_branch_name && git checkout $pr_branch_name")); + $commands->push(executeInDocker($this->deployment_uuid, "cd {$this->workdir} && git fetch origin pull/{$this->pull_request_id}/head:$pr_branch_name && git checkout $pr_branch_name")); } return $commands->implode(' && '); } @@ -388,10 +384,10 @@ private function importing_git_repository() $git_clone_command = "GIT_SSH_COMMAND=\"ssh -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" {$git_clone_command} {$this->application->git_full_url} {$this->workdir}"; $git_clone_command = $this->set_git_import_settings($git_clone_command); $commands = collect([ - $this->execute_in_builder("mkdir -p /root/.ssh"), - $this->execute_in_builder("echo '{$private_key}' | base64 -d > /root/.ssh/id_rsa"), - $this->execute_in_builder("chmod 600 /root/.ssh/id_rsa"), - $this->execute_in_builder($git_clone_command) + executeInDocker($this->deployment_uuid, "mkdir -p /root/.ssh"), + executeInDocker($this->deployment_uuid, "echo '{$private_key}' | base64 -d > /root/.ssh/id_rsa"), + executeInDocker($this->deployment_uuid, "chmod 600 /root/.ssh/id_rsa"), + executeInDocker($this->deployment_uuid, $git_clone_command) ]); return $commands->implode(' && '); } @@ -414,7 +410,7 @@ private function set_git_import_settings($git_clone_command) private function cleanup_git() { $this->execute_remote_command( - [$this->execute_in_builder("rm -fr {$this->workdir}/.git")], + [executeInDocker($this->deployment_uuid, "rm -fr {$this->workdir}/.git")], ); } @@ -425,8 +421,8 @@ private function generate_nixpacks_confs() "echo -n 'Generating nixpacks configuration.'", ], [$this->nixpacks_build_cmd()], - [$this->execute_in_builder("cp {$this->workdir}/.nixpacks/Dockerfile {$this->workdir}/Dockerfile")], - [$this->execute_in_builder("rm -f {$this->workdir}/.nixpacks/Dockerfile")] + [executeInDocker($this->deployment_uuid, "cp {$this->workdir}/.nixpacks/Dockerfile {$this->workdir}/Dockerfile")], + [executeInDocker($this->deployment_uuid, "rm -f {$this->workdir}/.nixpacks/Dockerfile")] ); } @@ -444,7 +440,7 @@ private function nixpacks_build_cmd() $nixpacks_command .= " --install-cmd \"{$this->application->install_command}\""; } $nixpacks_command .= " {$this->workdir}"; - return $this->execute_in_builder($nixpacks_command); + return executeInDocker($this->deployment_uuid, $nixpacks_command); } private function generate_env_variables() @@ -522,7 +518,7 @@ private function generate_compose_file() } $this->docker_compose = Yaml::dump($docker_compose, 10); $this->docker_compose_base64 = base64_encode($this->docker_compose); - $this->execute_remote_command([$this->execute_in_builder("echo '{$this->docker_compose_base64}' | base64 -d > {$this->workdir}/docker-compose.yml"), "hidden" => true]); + $this->execute_remote_command([executeInDocker($this->deployment_uuid, "echo '{$this->docker_compose_base64}' | base64 -d > {$this->workdir}/docker-compose.yml"), "hidden" => true]); } private function generate_local_persistent_volumes() @@ -679,7 +675,7 @@ private function build_image() if ($this->application->settings->is_static) { $this->execute_remote_command([ - $this->execute_in_builder("docker build --network host -f {$this->workdir}/Dockerfile {$this->build_args} --progress plain -t $this->build_image_name {$this->workdir}"), "hidden" => true + executeInDocker($this->deployment_uuid, "docker build --network host -f {$this->workdir}/Dockerfile {$this->build_args} --progress plain -t $this->build_image_name {$this->workdir}"), "hidden" => true ]); $dockerfile = base64_encode("FROM {$this->application->static_image} @@ -706,18 +702,18 @@ private function build_image() }"); $this->execute_remote_command( [ - $this->execute_in_builder("echo '{$dockerfile}' | base64 -d > {$this->workdir}/Dockerfile-prod") + executeInDocker($this->deployment_uuid, "echo '{$dockerfile}' | base64 -d > {$this->workdir}/Dockerfile-prod") ], [ - $this->execute_in_builder("echo '{$nginx_config}' | base64 -d > {$this->workdir}/nginx.conf") + executeInDocker($this->deployment_uuid, "echo '{$nginx_config}' | base64 -d > {$this->workdir}/nginx.conf") ], [ - $this->execute_in_builder("docker build --network host -f {$this->workdir}/Dockerfile-prod {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true + executeInDocker($this->deployment_uuid, "docker build --network host -f {$this->workdir}/Dockerfile-prod {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true ] ); } else { $this->execute_remote_command([ - $this->execute_in_builder("docker build --network host -f {$this->workdir}/Dockerfile {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true + executeInDocker($this->deployment_uuid, "docker build --network host -f {$this->workdir}/Dockerfile {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true ]); } } @@ -727,7 +723,7 @@ private function stop_running_container() if ($this->currently_running_container_name) { $this->execute_remote_command( ["echo -n 'Removing old version of your application.'"], - [$this->execute_in_builder("docker rm -f $this->currently_running_container_name >/dev/null 2>&1"), "hidden" => true], + [executeInDocker($this->deployment_uuid, "docker rm -f $this->currently_running_container_name >/dev/null 2>&1"), "hidden" => true], ); } } @@ -736,7 +732,7 @@ private function start_by_compose_file() { $this->execute_remote_command( ["echo -n 'Rolling update started.'"], - [$this->execute_in_builder("docker compose --project-directory {$this->workdir} up -d >/dev/null"), "hidden" => true], + [executeInDocker($this->deployment_uuid, "docker compose --project-directory {$this->workdir} up -d >/dev/null"), "hidden" => true], ); } @@ -759,7 +755,7 @@ private function generate_build_env_variables() private function add_build_env_variables_to_dockerfile() { $this->execute_remote_command([ - $this->execute_in_builder("cat {$this->workdir}/Dockerfile"), "hidden" => true, "save" => 'dockerfile' + executeInDocker($this->deployment_uuid, "cat {$this->workdir}/Dockerfile"), "hidden" => true, "save" => 'dockerfile' ]); $dockerfile = collect(Str::of($this->saved_outputs->get('dockerfile'))->trim()->explode("\n")); @@ -768,7 +764,7 @@ private function add_build_env_variables_to_dockerfile() } $dockerfile_base64 = base64_encode($dockerfile->implode("\n")); $this->execute_remote_command([ - $this->execute_in_builder("echo '{$dockerfile_base64}' | base64 -d > {$this->workdir}/Dockerfile"), + executeInDocker($this->deployment_uuid, "echo '{$dockerfile_base64}' | base64 -d > {$this->workdir}/Dockerfile"), "hidden" => true ]); } diff --git a/app/Jobs/DatabaseBackupJob.php b/app/Jobs/DatabaseBackupJob.php index 578a5ec43..740a700eb 100644 --- a/app/Jobs/DatabaseBackupJob.php +++ b/app/Jobs/DatabaseBackupJob.php @@ -18,7 +18,6 @@ use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\Middleware\WithoutOverlapping; use Illuminate\Queue\SerializesModels; -use Throwable; use Illuminate\Support\Str; class DatabaseBackupJob implements ShouldQueue, ShouldBeEncrypted @@ -117,7 +116,7 @@ private function backup_standalone_postgresql(): void $this->backup_status = 'success'; $this->team->notify(new BackupSuccess($this->backup, $this->database)); - } catch (Throwable $e) { + } catch (\Throwable $e) { $this->backup_status = 'failed'; $this->add_to_backup_output($e->getMessage()); ray('Backup failed for ' . $this->container_name . ' at ' . $this->server->name . ':' . $this->backup_location . '\n\nError:' . $e->getMessage()); diff --git a/app/Notifications/Application/DeploymentFailed.php b/app/Notifications/Application/DeploymentFailed.php index ea9e05652..efac09097 100644 --- a/app/Notifications/Application/DeploymentFailed.php +++ b/app/Notifications/Application/DeploymentFailed.php @@ -4,8 +4,6 @@ use App\Models\Application; use App\Models\ApplicationPreview; -use App\Notifications\Channels\DiscordChannel; -use App\Notifications\Channels\EmailChannel; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage; @@ -18,13 +16,14 @@ class DeploymentFailed extends Notification implements ShouldQueue public $tries = 5; public Application $application; - public string $deployment_uuid; public ?ApplicationPreview $preview = null; + public string $deployment_uuid; public string $application_name; - public ?string $deployment_url = null; public string $project_uuid; public string $environment_name; + + public ?string $deployment_url = null; public ?string $fqdn = null; public function __construct(Application $application, string $deployment_uuid, ?ApplicationPreview $preview = null) diff --git a/app/Notifications/Application/DeploymentSuccess.php b/app/Notifications/Application/DeploymentSuccess.php index ea789b69a..3b2d6e17f 100644 --- a/app/Notifications/Application/DeploymentSuccess.php +++ b/app/Notifications/Application/DeploymentSuccess.php @@ -4,8 +4,6 @@ use App\Models\Application; use App\Models\ApplicationPreview; -use App\Notifications\Channels\DiscordChannel; -use App\Notifications\Channels\EmailChannel; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage; @@ -18,14 +16,15 @@ class DeploymentSuccess extends Notification implements ShouldQueue public $tries = 5; public Application $application; - public string $deployment_uuid; public ApplicationPreview|null $preview = null; + public string $deployment_uuid; public string $application_name; - public string|null $deployment_url = null; public string $project_uuid; public string $environment_name; - public string|null $fqdn; + + public ?string $deployment_url = null; + public ?string $fqdn; public function __construct(Application $application, string $deployment_uuid, ApplicationPreview|null $preview = null) { diff --git a/app/Notifications/Application/StatusChanged.php b/app/Notifications/Application/StatusChanged.php index 11bd9f524..90ac92304 100644 --- a/app/Notifications/Application/StatusChanged.php +++ b/app/Notifications/Application/StatusChanged.php @@ -2,8 +2,7 @@ namespace App\Notifications\Application; -use App\Notifications\Channels\DiscordChannel; -use App\Notifications\Channels\EmailChannel; +use App\Models\Application; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage; @@ -15,13 +14,14 @@ class StatusChanged extends Notification implements ShouldQueue use Queueable; public $tries = 5; - public $application; + public Application $application; public string $application_name; - public string|null $application_url = null; public string $project_uuid; public string $environment_name; - public string|null $fqdn; + + public ?string $application_url = null; + public ?string $fqdn; public function __construct($application) { diff --git a/app/Traits/ExecuteRemoteCommand.php b/app/Traits/ExecuteRemoteCommand.php index 7416e1ce3..67761a69d 100644 --- a/app/Traits/ExecuteRemoteCommand.php +++ b/app/Traits/ExecuteRemoteCommand.php @@ -11,7 +11,7 @@ trait ExecuteRemoteCommand { - public string|null $save = null; + public ?string $save = null; public function execute_remote_command(...$commands) { @@ -25,11 +25,8 @@ public function execute_remote_command(...$commands) throw new \RuntimeException('Server is not set or is not an instance of Server model'); } - $ip = data_get($this->server, 'ip'); - $user = data_get($this->server, 'user'); - $port = data_get($this->server, 'port'); - $commandsText->each(function ($single_command) use ($ip, $user, $port) { + $commandsText->each(function ($single_command) { $command = data_get($single_command, 'command') ?? $single_command[0] ?? null; if ($command === null) { throw new \RuntimeException('Command is not set'); @@ -38,7 +35,7 @@ public function execute_remote_command(...$commands) $ignore_errors = data_get($single_command, 'ignore_errors', false); $this->save = data_get($single_command, 'save'); - $remote_command = generateSshCommand( $ip, $user, $port, $command); + $remote_command = generateSshCommand($this->server, $command); $process = Process::timeout(3600)->idleTimeout(3600)->start($remote_command, function (string $type, string $output) use ($command, $hidden) { $output = Str::of($output)->trim(); $new_log_entry = [ diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php index 0d99af516..279630ca1 100644 --- a/bootstrap/helpers/docker.php +++ b/bootstrap/helpers/docker.php @@ -59,6 +59,18 @@ function format_docker_envs_to_json($rawOutput) return collect([]); } } +function checkMinimumDockerEngineVersion($dockerVersion) { + $majorDockerVersion = Str::of($dockerVersion)->before('.')->value(); + if ($majorDockerVersion <= 22) { + $dockerVersion = null; + } + return $dockerVersion; +} +function executeInDocker(string $containerId, string $command) +{ + return "docker exec {$containerId} bash -c '{$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'); diff --git a/bootstrap/helpers/remoteProcess.php b/bootstrap/helpers/remoteProcess.php index a124efae8..ae16c7bc0 100644 --- a/bootstrap/helpers/remoteProcess.php +++ b/bootstrap/helpers/remoteProcess.php @@ -36,12 +36,10 @@ function remote_process( return resolve(PrepareCoolifyTask::class, [ 'remoteProcessArgs' => new CoolifyTaskArgs( - server_ip: $server->ip, + server_uuid: $server->uuid, command: <<port, - user: $server->user, type: $type, type_uuid: $type_uuid, model: $model, @@ -66,15 +64,14 @@ function addPrivateKeyToSshAgent(Server $server) Storage::disk('ssh-keys')->makeDirectory('.'); Storage::disk('ssh-mux')->makeDirectory('.'); Storage::disk('ssh-keys')->put($sshKeyFileLocation, $server->privateKey->private_key); - return '/var/www/html/storage/app/ssh/keys/' . $sshKeyFileLocation; + $location = '/var/www/html/storage/app/ssh/keys/' . $sshKeyFileLocation; + return $location; } -function generateSshCommand(string $server_ip, string $user, string $port, string $command, bool $isMux = true) +function generateSshCommand(Server $server, string $command, bool $isMux = true) { - $server = Server::where('ip', $server_ip)->first(); - if (!$server) { - throw new \Exception("Server with ip {$server_ip} not found"); - } + $user = $server->user; + $port = $server->port; $privateKeyLocation = addPrivateKeyToSshAgent($server); $timeout = config('constants.ssh.command_timeout'); $connectionTimeout = config('constants.ssh.connection_timeout'); @@ -95,27 +92,21 @@ function generateSshCommand(string $server_ip, string $user, string $port, strin . '-o RequestTTY=no ' . '-o LogLevel=ERROR ' . "-p {$port} " - . "{$user}@{$server_ip} " + . "{$user}@{$server->ip} " . " 'bash -se' << \\$delimiter" . PHP_EOL . $command . PHP_EOL . $delimiter; // ray($ssh_command); return $ssh_command; } -function instant_remote_process(array $command, Server $server, $throwError = true, $repeat = 1) +function instant_remote_process(array $command, Server $server, $throwError = true) { $command_string = implode("\n", $command); - $ssh_command = generateSshCommand($server->ip, $server->user, $server->port, $command_string); + $ssh_command = generateSshCommand($server, $command_string); $process = Process::run($ssh_command); $output = trim($process->output()); $exitCode = $process->exitCode(); if ($exitCode !== 0) { - if ($repeat > 1) { - ray("repeat: ", $repeat); - Sleep::for(200)->milliseconds(); - return instant_remote_process($command, $server, $throwError, $repeat - 1); - } - // ray('ERROR OCCURED: ' . $process->errorOutput()); if (!$throwError) { return null; } @@ -161,11 +152,10 @@ function refresh_server_connection(PrivateKey $private_key) } } -function validateServer(Server $server) +function validateServer(Server $server, bool $throwError = false) { try { - refresh_server_connection($server->privateKey); - $uptime = instant_remote_process(['uptime'], $server, false); + $uptime = instant_remote_process(['uptime'], $server, $throwError); if (!$uptime) { $server->settings->is_reachable = false; return [ @@ -175,7 +165,7 @@ function validateServer(Server $server) } $server->settings->is_reachable = true; - $dockerVersion = instant_remote_process(["docker version|head -2|grep -i version| awk '{print $2}'"], $server, false); + $dockerVersion = instant_remote_process(["docker version|head -2|grep -i version| awk '{print $2}'"], $server, $throwError); if (!$dockerVersion) { $dockerVersion = null; return [ @@ -183,9 +173,8 @@ function validateServer(Server $server) "dockerVersion" => null, ]; } - $majorDockerVersion = Str::of($dockerVersion)->before('.')->value(); - if ($majorDockerVersion <= 22) { - $dockerVersion = null; + $dockerVersion = checkMinimumDockerEngineVersion($dockerVersion); + if (is_null($dockerVersion)) { $server->settings->is_usable = false; } else { $server->settings->is_usable = true; diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 39066e1b6..44e5d48bc 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -69,12 +69,34 @@ function refreshSession(?Team $team = null): void } } Cache::forget('team:' . auth()->user()->id); - Cache::remember('team:' . auth()->user()->id, 3600, function() use ($team) { + Cache::remember('team:' . auth()->user()->id, 3600, function () use ($team) { return $team; }); session(['currentTeam' => $team]); } -function general_error_handler(Throwable | null $err = null, $that = null, $isJson = false, $customErrorMessage = null): mixed +function handleError(?Throwable $error = null, ?Livewire\Component $livewire = null, ?string $customErrorMessage = null) +{ + ray('handleError'); + if ($error instanceof Throwable) { + $message = $error->getMessage(); + } else { + $message = null; + } + if ($customErrorMessage) { + $message = $customErrorMessage . ' ' . $message; + } + if ($error instanceof TooManyRequestsException) { + if (isset($livewire)) { + return $livewire->emit('error', "Too many requests. Please try again in {$error->secondsUntilAvailable} seconds."); + } + return "Too many requests. Please try again in {$error->secondsUntilAvailable} seconds."; + } + if (isset($livewire)) { + return $livewire->emit('error', $message); + } + throw new RuntimeException($message); +} +function general_error_handler(Throwable $err, Livewire\Component $that = null, $isJson = false, $customErrorMessage = null): mixed { try { ray($err); @@ -95,7 +117,7 @@ function general_error_handler(Throwable | null $err = null, $that = null, $isJs } throw new Exception($customErrorMessage ?? $err->getMessage()); } - } catch (Throwable $e) { + } catch (\Throwable $e) { if ($that) { return $that->emit('error', $customErrorMessage ?? $e->getMessage()); } elseif ($isJson) { @@ -122,7 +144,7 @@ function get_latest_version_of_coolify(): string $response = Http::get('https://cdn.coollabs.io/coolify/versions.json'); $versions = $response->json(); return data_get($versions, 'coolify.v4.version'); - } catch (Throwable $e) { + } catch (\Throwable $e) { //throw $e; ray($e->getMessage()); return '0.0.0'; @@ -321,7 +343,8 @@ function setNotificationChannels($notifiable, $event) } return $channels; } -function parseEnvFormatToArray($env_file_contents) { +function parseEnvFormatToArray($env_file_contents) +{ $env_array = array(); $lines = explode("\n", $env_file_contents); foreach ($lines as $line) { @@ -334,8 +357,7 @@ function parseEnvFormatToArray($env_file_contents) { $value = substr($line, $equals_pos + 1); if (substr($value, 0, 1) === '"' && substr($value, -1) === '"') { $value = substr($value, 1, -1); - } - elseif (substr($value, 0, 1) === "'" && substr($value, -1) === "'") { + } elseif (substr($value, 0, 1) === "'" && substr($value, -1) === "'") { $value = substr($value, 1, -1); } $env_array[$key] = $value; diff --git a/config/toaster.php b/config/toaster.php index 4dd1244b1..950a98a01 100644 --- a/config/toaster.php +++ b/config/toaster.php @@ -30,14 +30,14 @@ * * Minimum: 3000 (in milliseconds) */ - 'duration' => 5000, + 'duration' => 1500, /** * The horizontal position of each toast. * * Supported: "center", "left" or "right" */ - 'position' => 'right', + 'position' => 'center', /** * Whether messages passed as translation keys should be translated automatically. diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php index 41ab319b4..47ac188f2 100644 --- a/resources/views/auth/login.blade.php +++ b/resources/views/auth/login.blade.php @@ -24,17 +24,17 @@ class="text-xs normal-case hover:no-underline btn btn-sm bg-coollabs-gradient">
@csrf @env('local') - - {{ __('auth.forgot_password') }}? @else - - + + {{ __('auth.forgot_password') }}? diff --git a/resources/views/components/applications/navbar.blade.php b/resources/views/components/applications/navbar.blade.php index 897c68662..00a390826 100644 --- a/resources/views/components/applications/navbar.blade.php +++ b/resources/views/components/applications/navbar.blade.php @@ -11,7 +11,7 @@
- @if ($application->status === 'running') + @if ($application->status !== 'exited')