Merge pull request #1222 from coollabsio/next

v4.0.0-beta.34
This commit is contained in:
Andras Bacsai 2023-09-11 23:05:30 +02:00 committed by GitHub
commit a1592373aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
98 changed files with 505 additions and 391 deletions

View File

@ -97,7 +97,6 @@ class RunRemoteProcess
'status' => $status->value,
]);
$this->activity->save();
if ($processResult->exitCode() != 0 && !$this->ignore_errors) {
throw new \RuntimeException($processResult->errorOutput());
}

View File

@ -57,13 +57,13 @@ class CheckResaleLicense
throw new \Exception('Invalid license key.');
}
throw new \Exception('Cannot activate license key.');
} catch (\Throwable $th) {
ray($th);
} catch (\Throwable $e) {
ray($e);
$settings->update([
'resale_license' => null,
'is_resale_license_active' => false,
]);
throw $th;
throw $e;
}
}
}

View File

@ -20,8 +20,8 @@ class SaveConfigurationSync
"mkdir -p $proxy_path",
"echo '$docker_compose_yml_base64' | base64 -d > $proxy_path/docker-compose.yml",
], $server);
} catch (\Throwable $th) {
ray($th);
} catch (\Throwable $e) {
ray($e);
}
}

View File

@ -2,8 +2,6 @@
namespace App\Actions\Proxy;
use App\Enums\ProxyStatus;
use App\Enums\ProxyTypes;
use App\Models\Server;
use Illuminate\Support\Str;
use Spatie\Activitylog\Models\Activity;
@ -36,11 +34,14 @@ class StartProxy
"echo '####### Creating Docker Compose file...'",
"echo '####### Pulling docker image...'",
'docker compose pull',
"echo '####### Stopping existing proxy...'",
"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",
"echo '####### Starting proxy...'",
"systemctl disable nginx > /dev/null 2>&1 || true",
"systemctl disable apache2 > /dev/null 2>&1 || true",
"systemctl disable apache > /dev/null 2>&1 || true",
"echo '####### Starting coolify-proxy...'",
'docker compose up -d --remove-orphans',
"echo '####### Proxy installed successfully...'"
], $server);

View File

@ -43,11 +43,11 @@ class UpdateCoolify
$this->update();
}
send_internal_notification('InstanceAutoUpdateJob done to version: ' . $this->latestVersion . ' from version: ' . $this->currentVersion);
} catch (\Exception $th) {
} catch (\Throwable $e) {
ray('InstanceAutoUpdateJob failed');
ray($th->getMessage());
send_internal_notification('InstanceAutoUpdateJob failed: ' . $th->getMessage());
throw $th;
ray($e->getMessage());
send_internal_notification('InstanceAutoUpdateJob failed: ' . $e->getMessage());
throw $e;
}
}

View File

@ -26,7 +26,7 @@ class Init extends Command
$deployment->status = ApplicationDeploymentStatus::FAILED->value;
$deployment->save();
}
} catch (\Exception $e) {
} catch (\Throwable $e) {
echo "Error: {$e->getMessage()}\n";
}
}

View File

@ -82,7 +82,7 @@ class SyncBunny extends Command
$pool->purge("$bunny_cdn/$bunny_cdn_path/$versions"),
]);
echo "All files uploaded & purged...\n";
} catch (\Exception $e) {
} catch (\Throwable $e) {
echo $e->getMessage();
}
}

View File

@ -21,7 +21,6 @@ use Exception;
use Illuminate\Console\Command;
use Illuminate\Mail\Message;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Facades\Process;
use Mail;
use Str;

View File

@ -19,7 +19,7 @@ class WaitlistInvite extends Command
*
* @var string
*/
protected $signature = 'waitlist:invite {email?} {--only-email}';
protected $signature = 'waitlist:invite {--people=1} {--only-email} {email?}';
/**
* The console command description.
@ -33,6 +33,12 @@ class WaitlistInvite extends Command
*/
public function handle()
{
$people = $this->option('people');
for ($i = 0; $i < $people; $i++) {
$this->main();
}
}
private function main() {
if ($this->argument('email')) {
if ($this->option('only-email')) {
$this->next_patient = User::whereEmail($this->argument('email'))->first();

View File

@ -2,6 +2,7 @@
namespace App\Console;
use App\Enums\ProxyTypes;
use App\Jobs\ApplicationContainerStatusJob;
use App\Jobs\CheckResaleLicenseJob;
use App\Jobs\CleanupInstanceStuffsJob;
@ -9,11 +10,11 @@ use App\Jobs\DatabaseBackupJob;
use App\Jobs\DatabaseContainerStatusJob;
use App\Jobs\DockerCleanupJob;
use App\Jobs\InstanceAutoUpdateJob;
use App\Jobs\ProxyCheckJob;
use App\Jobs\ResourceStatusJob;
use App\Jobs\ProxyContainerStatusJob;
use App\Models\Application;
use App\Models\InstanceSettings;
use App\Models\ScheduledDatabaseBackup;
use App\Models\Server;
use App\Models\StandalonePostgresql;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
@ -24,22 +25,26 @@ class Kernel extends ConsoleKernel
{
if (isDev()) {
$schedule->command('horizon:snapshot')->everyMinute();
// $schedule->job(new ResourceStatusJob)->everyMinute();
$schedule->job(new ProxyCheckJob)->everyFiveMinutes();
$schedule->job(new CleanupInstanceStuffsJob)->everyMinute();
// $schedule->job(new CheckResaleLicenseJob)->hourly();
$schedule->job(new DockerCleanupJob)->everyOddHour();
} else {
$schedule->command('horizon:snapshot')->everyFiveMinutes();
$schedule->job(new CleanupInstanceStuffsJob)->everyTenMinutes()->onOneServer();
// $schedule->job(new ResourceStatusJob)->everyMinute()->onOneServer();
$schedule->job(new CheckResaleLicenseJob)->hourly()->onOneServer();
$schedule->job(new ProxyCheckJob)->everyFiveMinutes()->onOneServer();
$schedule->job(new DockerCleanupJob)->everyTenMinutes()->onOneServer();
}
$this->instance_auto_update($schedule);
$this->check_scheduled_backups($schedule);
$this->check_resources($schedule);
$this->check_proxies($schedule);
}
private function check_proxies($schedule)
{
$servers = Server::all()->where('settings.is_usable', true)->where('settings.is_reachable', true)->whereNotNull('proxy.type')->where('proxy.type', '!=', ProxyTypes::NONE->value);
foreach ($servers as $server) {
$schedule->job(new ProxyContainerStatusJob($server))->everyMinute()->onOneServer();
}
}
private function check_resources($schedule)
{
@ -53,7 +58,8 @@ class Kernel extends ConsoleKernel
$schedule->job(new DatabaseContainerStatusJob($postgresql))->everyMinute()->onOneServer();
}
}
private function instance_auto_update($schedule){
private function instance_auto_update($schedule)
{
if (isDev()) {
return;
}
@ -74,7 +80,7 @@ class Kernel extends ConsoleKernel
if (!$scheduled_backup->enabled) {
continue;
}
if (is_null(data_get($scheduled_backup,'database'))) {
if (is_null(data_get($scheduled_backup, 'database'))) {
ray('database not found');
$scheduled_backup->delete();
continue;

View File

@ -25,7 +25,7 @@ class Handler extends ExceptionHandler
* @var array<int, class-string<\Throwable>>
*/
protected $dontReport = [
//
ProcessException::class
];
/**
* A list of the inputs that are never flashed to the session on validation exceptions.
@ -50,8 +50,13 @@ class Handler extends ExceptionHandler
return;
}
app('sentry')->configureScope(
function (Scope $scope){
$scope->setUser(['id'=> config('sentry.server_name')]);
function (Scope $scope) {
$scope->setUser(
[
'id' => config('sentry.server_name'),
'email' => auth()->user()->email
]
);
}
);
Integration::captureUnhandledException($e);

View File

@ -0,0 +1,10 @@
<?php
namespace App\Exceptions;
use Exception;
class ProcessException extends Exception
{
}

View File

@ -154,8 +154,8 @@ class Controller extends BaseController
$invitation->delete();
abort(401);
}
} catch (Throwable $th) {
throw $th;
} catch (Throwable $e) {
throw $e;
}
}
@ -172,8 +172,8 @@ class Controller extends BaseController
}
$invitation->delete();
return redirect()->route('team.index');
} catch (Throwable $th) {
throw $th;
} catch (Throwable $e) {
throw $e;
}
}
}

View File

@ -193,7 +193,7 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
}
$this->getProxyType();
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler(customErrorMessage: "Server is not reachable. Reason: {$e->getMessage()}", that: $this);
}
}

View File

@ -34,9 +34,9 @@ class CheckLicense extends Component
try {
resolve(CheckResaleLicense::class)();
$this->emit('reloadWindow');
} catch (\Throwable $th) {
session()->flash('error', 'Something went wrong. Please contact support. <br>Error: ' . $th->getMessage());
ray($th->getMessage());
} catch (\Throwable $e) {
session()->flash('error', 'Something went wrong. Please contact support. <br>Error: ' . $e->getMessage());
ray($e->getMessage());
return redirect()->to('/settings/license');
}
}

View File

@ -37,7 +37,7 @@ class Form extends Component
}
$this->destination->delete();
return redirect()->route('dashboard');
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler(err: $e);
}
}

View File

@ -71,7 +71,7 @@ class StandaloneDocker extends Component
}
$this->createNetworkAndAttachToProxy();
return redirect()->route('destination.show', $docker->uuid);
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler(err: $e, that: $this);
}
}

View File

@ -36,7 +36,7 @@ class ForcePasswordReset extends Component
send_internal_notification('First login for ' . auth()->user()->email);
}
return redirect()->route('dashboard');
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler(err: $e, that: $this);
}
}

View File

@ -43,7 +43,7 @@ class Help extends Component
$mail->subject("[HELP - {$subscriptionType}]: {$this->subject}");
send_user_an_email($mail, 'hi@coollabs.io');
$this->emit('success', 'Your message has been sent successfully. We will get in touch with you as soon as possible.');
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler($e, $this);
}
}

View File

@ -29,7 +29,7 @@ class DiscordSettings extends Component
{
try {
$this->submit();
} catch (\Exception $e) {
} catch (\Throwable $e) {
ray($e->getMessage());
$this->team->discord_enabled = false;
$this->validate();

View File

@ -63,7 +63,7 @@ class EmailSettings extends Component
]);
$this->team->save();
$this->emit('success', 'Settings saved successfully.');
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler($e, $this);
}
}
@ -82,7 +82,7 @@ class EmailSettings extends Component
$this->team->resend_enabled = false;
$this->team->save();
$this->emit('success', 'Settings saved successfully.');
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler($e, $this);
}
}
@ -92,7 +92,7 @@ class EmailSettings extends Component
try {
$this->team->smtp_enabled = false;
$this->submitResend();
} catch (\Exception $e) {
} catch (\Throwable $e) {
$this->team->smtp_enabled = false;
return general_error_handler($e, $this);
}
@ -102,7 +102,7 @@ class EmailSettings extends Component
try {
$this->team->resend_enabled = false;
$this->submit();
} catch (\Exception $e) {
} catch (\Throwable $e) {
$this->team->smtp_enabled = false;
return general_error_handler($e, $this);
}
@ -131,7 +131,7 @@ class EmailSettings extends Component
]);
$this->team->save();
$this->emit('success', 'Settings saved successfully.');
} catch (\Exception $e) {
} catch (\Throwable $e) {
$this->team->smtp_enabled = false;
return general_error_handler($e, $this);
}
@ -146,7 +146,7 @@ class EmailSettings extends Component
$this->team->save();
refreshSession();
$this->emit('success', 'Settings saved successfully.');
} catch (\Exception $e) {
} catch (\Throwable $e) {
$this->team->resend_enabled = false;
return general_error_handler($e, $this);
}

View File

@ -35,7 +35,7 @@ class TelegramSettings extends Component
{
try {
$this->submit();
} catch (\Exception $e) {
} catch (\Throwable $e) {
ray($e->getMessage());
$this->team->telegram_enabled = false;
$this->validate();

View File

@ -38,7 +38,7 @@ class Change extends Component
return redirect()->route('security.private-key.index');
}
$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 (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler(err: $e, that: $this);
}
}
@ -49,7 +49,7 @@ class Change extends Component
$this->private_key->private_key = formatPrivateKey($this->private_key->private_key);
$this->private_key->save();
refresh_server_connection($this->private_key);
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler(err: $e, that: $this);
}
}

View File

@ -38,7 +38,7 @@ class Create extends Component
return redirect()->route('server.create');
}
return redirect()->route('security.private-key.show', ['private_key_uuid' => $private_key->uuid]);
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler(err: $e, that: $this);
}
}

View File

@ -28,7 +28,7 @@ class AddEmpty extends Component
'team_id' => currentTeam()->id,
]);
return redirect()->route('project.show', $project->uuid);
} catch (\Exception $e) {
} catch (\Throwable $e) {
general_error_handler($e, $this);
} finally {
$this->name = '';

View File

@ -31,7 +31,7 @@ class AddEnvironment extends Component
'project_uuid' => $this->project->uuid,
'environment_name' => $environment->name,
]);
} catch (\Exception $e) {
} catch (\Throwable $e) {
general_error_handler($e, $this);
} finally {
$this->name = '';

View File

@ -48,6 +48,7 @@ class General extends Component
'application.ports_exposes' => 'required',
'application.ports_mappings' => 'nullable',
'application.dockerfile' => 'nullable',
'application.nixpkgsarchive' => 'nullable',
];
protected $validationAttributes = [
'application.name' => 'name',
@ -66,6 +67,7 @@ class General extends Component
'application.ports_exposes' => 'Ports exposes',
'application.ports_mappings' => 'Ports mappings',
'application.dockerfile' => 'Dockerfile',
'application.nixpkgsarchive' => 'Nixpkgs archive',
];
public function instantSave()
@ -159,7 +161,7 @@ class General extends Component
}
$this->application->save();
$this->emit('success', 'Application settings updated!');
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler(err: $e, that: $this);
}
}

View File

@ -51,7 +51,7 @@ class BackupEdit extends Component
$this->backup->save();
$this->backup->refresh();
$this->emit('success', 'Backup updated successfully');
} catch (\Exception $e) {
} catch (\Throwable $e) {
$this->emit('error', $e->getMessage());
}
}
@ -76,7 +76,7 @@ class BackupEdit extends Component
$this->backup->save();
$this->backup->refresh();
$this->emit('success', 'Backup updated successfully');
} catch (\Exception $e) {
} catch (\Throwable $e) {
$this->emit('error', $e->getMessage());
}
}

View File

@ -42,7 +42,7 @@ class CreateScheduledBackup extends Component
'team_id' => currentTeam()->id,
]);
$this->emit('refreshScheduledBackups');
} catch (\Exception $e) {
} catch (\Throwable $e) {
general_error_handler($e, $this);
} finally {
$this->frequency = '';

View File

@ -19,7 +19,7 @@ class Edit extends Component
try {
$this->project->save();
$this->emit('saved');
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler($e, $this);
}
}

View File

@ -164,7 +164,7 @@ class GithubPrivateRepository extends Component
'environment_name' => $environment->name,
'project_uuid' => $project->uuid,
]);
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler(err: $e, that: $this);
}
}

View File

@ -117,7 +117,7 @@ class GithubPrivateRepositoryDeployKey extends Component
'environment_name' => $environment->name,
'application_uuid' => $application->uuid,
]);
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler(err: $e, that: $this);
}
}

View File

@ -75,14 +75,14 @@ class PublicGitRepository extends Component
$this->get_git_source();
$this->get_branch();
$this->selected_branch = $this->git_branch;
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler(err: $e, that: $this);
}
if (!$this->branch_found && $this->git_branch == 'main') {
try {
$this->git_branch = 'master';
$this->get_branch();
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler(err: $e, that: $this);
}
}
@ -161,7 +161,7 @@ class PublicGitRepository extends Component
'environment_name' => $environment->name,
'application_uuid' => $application->uuid,
]);
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler(err: $e, that: $this);
}
}

View File

@ -40,7 +40,7 @@ class Select extends Component
// try {
// instantCommand("psql {$this->existingPostgresqlUrl} -c 'SELECT 1'");
// $this->emit('success', 'Successfully connected to the database.');
// } catch (\Exception $e) {
// } catch (\Throwable $e) {
// return general_error_handler($e, $this);
// }
// }

View File

@ -77,6 +77,11 @@ class All extends Component
$environment->save();
}
}
if ($isPreview) {
$this->emit('success', 'Preview environment variables updated successfully.');
} else {
$this->emit('success', 'Environment variables updated successfully.');
}
$this->refreshEnvs();
}
public function refreshEnvs()
@ -108,7 +113,7 @@ class All extends Component
$environment->save();
$this->refreshEnvs();
$this->emit('success', 'Environment variable added successfully.');
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler(err: $e, that: $this);
}
}

View File

@ -53,7 +53,7 @@ class ResourceLimits extends Component
$this->validate();
$this->resource->save();
$this->emit('success', 'Resource limits updated successfully.');
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler(err: $e, that: $this);
}
}

View File

@ -28,7 +28,7 @@ class All extends Component
$this->resource->refresh();
$this->emit('success', 'Storage added successfully');
$this->emit('clearAddStorage');
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler(err: $e, that: $this);
}
}

View File

@ -32,7 +32,7 @@ class RunCommand extends Component
try {
$activity = remote_process([$this->command], Server::where('uuid', $this->server)->first(), ignore_errors: true);
$this->emit('newMonitorActivity', $activity->id);
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler(err: $e);
}
}

View File

@ -56,16 +56,17 @@ class Form extends Component
$this->uptime = $uptime;
$this->emit('success', 'Server is reachable!');
} else {
throw new \Exception('Server is not rachable');
$this->emit('error', 'Server is not rachable');
return;
}
if ($dockerVersion) {
$this->dockerVersion = $dockerVersion;
$this->emit('proxyStatusUpdated');
$this->emit('success', 'Docker Engine 23+ is installed!');
} else {
throw new \Exception('Old Docker version detected (lower than 23).');
$this->emit('error', 'Old (lower than 23) or no Docker version detected. Install Docker Engine on the General tab.');
}
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler($e, that: $this);
}
}
@ -80,7 +81,7 @@ class Form extends Component
}
$this->server->delete();
return redirect()->route('server.all');
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler(err: $e, that: $this);
}
}

View File

@ -78,7 +78,7 @@ class ByIp extends Component
$server->settings->is_part_of_swarm = $this->is_part_of_swarm;
$server->settings->save();
return redirect()->route('server.show', $server->uuid);
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler(err: $e);
}
}

View File

@ -14,14 +14,14 @@ class Proxy extends Component
public ?string $selectedProxy = null;
public $proxy_settings = null;
public string|null $redirect_url = null;
public ?string $redirect_url = null;
protected $listeners = ['proxyStatusUpdated', 'saveConfiguration' => 'submit'];
public function mount()
{
$this->selectedProxy = $this->server->proxy->type;
$this->redirect_url = $this->server->proxy->redirect_url;
$this->selectedProxy = data_get($this->server, 'proxy.type');
$this->redirect_url = data_get($this->server, 'proxy.redirect_url');
}
public function proxyStatusUpdated()
@ -55,7 +55,7 @@ class Proxy extends Component
setup_default_redirect_404(redirect_url: $this->server->proxy->redirect_url, server: $this->server);
$this->emit('success', 'Proxy configuration saved.');
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler(err: $e);
}
}
@ -64,16 +64,17 @@ class Proxy extends Component
{
try {
$this->proxy_settings = resolve(CheckConfigurationSync::class)($this->server, true);
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler(err: $e);
}
}
public function load_proxy_configuration()
public function loadProxyConfiguration()
{
try {
ray('loadProxyConfiguration');
$this->proxy_settings = resolve(CheckConfigurationSync::class)($this->server);
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler(err: $e);
}
}

View File

@ -10,15 +10,20 @@ class Deploy extends Component
{
public Server $server;
public $proxy_settings = null;
protected $listeners = ['proxyStatusUpdated'];
public function start_proxy()
public function proxyStatusUpdated() {
$this->server->refresh();
}
public function startProxy()
{
if (
$this->server->proxy->last_applied_settings &&
$this->server->proxy->last_saved_settings !== $this->server->proxy->last_applied_settings
) {
$this->emit('saveConfiguration', $this->server);
resolve(SaveConfigurationSync::class)($this->server, $this->proxy_settings);
}
$activity = resolve(StartProxy::class)($this->server);
$this->emit('newMonitorActivity', $activity->id);
}

View File

@ -2,7 +2,6 @@
namespace App\Http\Livewire\Server\Proxy;
use App\Jobs\ProxyContainerStatusJob;
use App\Models\Server;
use Livewire\Component;
@ -10,14 +9,27 @@ class Status extends Component
{
public Server $server;
public function get_status()
protected $listeners = ['proxyStatusUpdated'];
public function proxyStatusUpdated()
{
if (data_get($this->server,'settings.is_usable')) {
dispatch_sync(new ProxyContainerStatusJob(
server: $this->server
));
$this->server->refresh();
$this->emit('proxyStatusUpdated');
$this->server->refresh();
}
public function getProxyStatus()
{
try {
if (data_get($this->server, 'settings.is_usable') && data_get($this->server, 'settings.is_reachable')) {
$container = getContainerStatus(server: $this->server, container_id: 'coolify-proxy');
$this->server->proxy->status = $container;
$this->server->save();
$this->emit('proxyStatusUpdated');
}
} catch (\Throwable $e) {
return general_error_handler(err: $e);
}
}
public function getProxyStatusWithNoti()
{
$this->emit('success', 'Refreshed proxy status.');
$this->getProxyStatus();
}
}

View File

@ -21,7 +21,7 @@ class ShowPrivateKey extends Component
$this->server->refresh();
refresh_server_connection($this->server->privateKey);
$this->checkConnection();
} catch (\Exception $e) {
} catch (\Throwable $e) {
$this->server->update([
'private_key_id' => $oldPrivateKeyId
]);
@ -38,14 +38,15 @@ class ShowPrivateKey extends Component
if ($uptime) {
$this->emit('success', 'Server is reachable with this private key.');
} else {
throw new \Exception('Server is not reachable with this private key.');
$this->emit('error', 'Server is not reachable with this private key.');
return;
}
if ($dockerVersion) {
$this->emit('success', 'Server is usable for Coolify.');
} else {
throw new \Exception('Old Docker version detected (lower than 23).');
$this->emit('error', 'Old (lower than 23) or no Docker version detected. Install Docker Engine on the General tab.');
}
} catch (\Exception $e) {
} catch (\Throwable $e) {
throw new \Exception($e->getMessage());
}
}

View File

@ -2,7 +2,7 @@
namespace App\Http\Livewire\Settings;
use App\Jobs\ProxyStartJob;
use App\Jobs\ProxyContainerStatusJob;
use App\Models\InstanceSettings as ModelsInstanceSettings;
use App\Models\Server;
use Livewire\Component;
@ -124,7 +124,7 @@ class Configuration extends Component
];
}
$this->save_configuration_to_disk($traefik_dynamic_conf, $file);
dispatch(new ProxyStartJob($this->server));
dispatch(new ProxyContainerStatusJob($this->server));
}
}

View File

@ -50,7 +50,7 @@ class Email extends Component
]);
$this->settings->save();
$this->emit('success', 'Settings saved successfully.');
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler($e, $this);
}
}
@ -62,7 +62,7 @@ class Email extends Component
]);
$this->settings->save();
$this->emit('success', 'Settings saved successfully.');
} catch (\Exception $e) {
} catch (\Throwable $e) {
$this->settings->resend_enabled = false;
return general_error_handler($e, $this);
}
@ -71,7 +71,7 @@ class Email extends Component
try {
$this->settings->smtp_enabled = false;
$this->submitResend();
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler($e, $this);
}
}
@ -80,7 +80,7 @@ class Email extends Component
try {
$this->settings->resend_enabled = false;
$this->submit();
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler($e, $this);
}
}
@ -99,7 +99,7 @@ class Email extends Component
]);
$this->settings->save();
$this->emit('success', 'Settings saved successfully.');
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler($e, $this);
}
}

View File

@ -51,7 +51,7 @@ class Change extends Component
try {
$this->validate();
$this->github_app->save();
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler(err: $e, that: $this);
}
}
@ -65,7 +65,7 @@ class Change extends Component
try {
$this->github_app->delete();
redirect()->route('source.all');
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler(err: $e, that: $this);
}
}

View File

@ -49,7 +49,7 @@ class Create extends Component
session(['from' => session('from') + ['source_id' => $github_app->id]]);
}
redirect()->route('source.github.show', ['github_app_uuid' => $github_app->uuid]);
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler(err: $e, that: $this);
}
}

View File

@ -30,7 +30,7 @@ class Actions extends Component
$this->emit('success', 'Subscription cancelled successfully. Reloading in 5s.');
$this->emit('reloadWindow', 5000);
}
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler($e, $this);
}
}
@ -65,7 +65,7 @@ class Actions extends Component
$this->emit('success', 'Subscription resumed successfully. Reloading in 5s.');
$this->emit('reloadWindow', 5000);
}
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler($e, $this);
}
}

View File

@ -31,8 +31,8 @@ class Create extends Component
auth()->user()->teams()->attach($team, ['role' => 'admin']);
refreshSession();
return redirect()->route('team.index');
} catch (\Throwable $th) {
return general_error_handler($th, $this);
} catch (\Throwable $e) {
return general_error_handler($e, $this);
}
}
}

View File

@ -28,8 +28,8 @@ class Form extends Component
try {
$this->team->save();
refreshSession();
} catch (\Throwable $th) {
return general_error_handler($th, $this);
} catch (\Throwable $e) {
return general_error_handler($e, $this);
}
}
}

View File

@ -67,8 +67,8 @@ class Create extends Component
$this->emit('success', 'Connection is working. Tested with "ListObjectsV2" action.');
$this->storage->save();
return redirect()->route('team.storages.show', $this->storage->uuid);
} catch (\Throwable $th) {
return general_error_handler($th, $this);
} catch (\Throwable $e) {
return general_error_handler($e, $this);
}
}
@ -77,8 +77,8 @@ class Create extends Component
try {
$this->storage->testConnection();
return $this->emit('success', 'Connection is working. Tested with "ListObjectsV2" action.');
} catch (\Throwable $th) {
return general_error_handler($th, $this);
} catch (\Throwable $e) {
return general_error_handler($e, $this);
}
}
}

View File

@ -32,8 +32,8 @@ class Form extends Component
try {
$this->storage->testConnection();
return $this->emit('success', 'Connection is working. Tested with "ListObjectsV2" action.');
} catch (\Throwable $th) {
return general_error_handler($th, $this);
} catch (\Throwable $e) {
return general_error_handler($e, $this);
}
}
@ -42,8 +42,8 @@ class Form extends Component
try {
$this->storage->delete();
return redirect()->route('team.storages.all');
} catch (\Throwable $th) {
return general_error_handler($th, $this);
} catch (\Throwable $e) {
return general_error_handler($e, $this);
}
}
@ -55,8 +55,8 @@ class Form extends Component
$this->emit('success', 'Connection is working. Tested with "ListObjectsV2" action.');
$this->storage->save();
$this->emit('success', 'Storage settings saved.');
} catch (\Throwable $th) {
return general_error_handler($th, $this);
} catch (\Throwable $e) {
return general_error_handler($e, $this);
}
}
}

View File

@ -37,7 +37,7 @@ class Upgrade extends Component
$this->showProgress = true;
resolve(UpdateCoolify::class)(true);
Toaster::success("Upgrading to {$this->latestVersion} version...");
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler(err: $e, that: $this);
}
}

View File

@ -52,7 +52,7 @@ class Index extends Component
$this->emit('success', 'Check your email to verify your email address.');
dispatch(new SendConfirmationForWaitlistJob($this->email, $waitlist->uuid));
} catch (\Exception $e) {
} catch (\Throwable $e) {
return general_error_handler(err: $e, that: $this);
}
}

View File

@ -15,7 +15,7 @@ class IsBoardingFlow
*/
public function handle(Request $request, Closure $next): Response
{
ray()->showQueries()->color('orange');
// ray()->showQueries()->color('orange');
if (showBoarding() && !in_array($request->path(), allowedPathsForBoardingAccounts())) {
return redirect('boarding');
}

View File

@ -46,9 +46,9 @@ class ApplicationContainerStatusJob implements ShouldQueue, ShouldBeUnique
$this->application->status = $status;
$this->application->save();
}
} catch (\Exception $th) {
ray($th->getMessage());
throw $th;
} catch (\Throwable $e) {
ray($e->getMessage());
throw $e;
}
}
}

View File

@ -28,6 +28,8 @@ use Spatie\Url\Url;
use Symfony\Component\Yaml\Yaml;
use Throwable;
use Visus\Cuid2\Cuid2;
use Yosymfony\Toml\Toml;
use Yosymfony\Toml\TomlArray;
class ApplicationDeploymentJob implements ShouldQueue
{
@ -133,7 +135,7 @@ class ApplicationDeploymentJob implements ShouldQueue
$this->deploy();
}
}
if ($this->application->fqdn) dispatch(new ProxyStartJob($this->server));
if ($this->application->fqdn) dispatch(new ProxyContainerStatusJob($this->server));
$this->next(ApplicationDeploymentStatus::FINISHED->value);
} catch (Exception $e) {
ray($e);
@ -411,6 +413,7 @@ class ApplicationDeploymentJob implements ShouldQueue
private function generate_nixpacks_confs()
{
ray('nixpkgsarchive', $this->application->nixpkgsarchive);
$this->execute_remote_command(
[
"echo -n 'Generating nixpacks configuration.'",
@ -419,6 +422,13 @@ class ApplicationDeploymentJob implements ShouldQueue
[$this->execute_in_builder("cp {$this->workdir}/.nixpacks/Dockerfile {$this->workdir}/Dockerfile")],
[$this->execute_in_builder("rm -f {$this->workdir}/.nixpacks/Dockerfile")]
);
// if ($this->application->nixpkgsarchive) {
// $this->execute_remote_command([
// $this->execute_in_builder("cat {$this->workdir}/nixpacks.toml"), "hidden" => true, "save" => 'nixpacks_toml'
// ]);
// }
}
private function nixpacks_build_cmd()

View File

@ -57,7 +57,7 @@ class ApplicationPullRequestUpdateJob implements ShouldQueue
} else {
$this->create_comment();
}
} catch (\Exception $e) {
} catch (\Throwable $e) {
ray($e);
throw $e;
}

View File

@ -21,10 +21,10 @@ class CheckResaleLicenseJob implements ShouldQueue
{
try {
resolve(CheckResaleLicense::class)();
} catch (\Throwable $th) {
send_internal_notification('CheckResaleLicenseJob failed with: ' . $th->getMessage());
ray($th);
throw $th;
} catch (\Throwable $e) {
send_internal_notification('CheckResaleLicenseJob failed with: ' . $e->getMessage());
ray($e);
throw $e;
}
}
}

View File

@ -28,7 +28,7 @@ class CleanupInstanceStuffsJob implements ShouldQueue, ShouldBeUnique
{
try {
// $this->cleanup_waitlist();
} catch (\Exception $e) {
} catch (\Throwable $e) {
send_internal_notification('CleanupInstanceStuffsJob failed with error: ' . $e->getMessage());
ray($e->getMessage());
throw $e;

View File

@ -90,10 +90,10 @@ class DatabaseBackupJob implements ShouldQueue
}
$this->save_backup_logs();
// TODO: Notify user
} catch (\Throwable $th) {
ray($th->getMessage());
send_internal_notification('DatabaseBackupJob failed with: ' . $th->getMessage());
throw $th;
} catch (\Throwable $e) {
ray($e->getMessage());
send_internal_notification('DatabaseBackupJob failed with: ' . $e->getMessage());
throw $e;
}
}
@ -116,10 +116,10 @@ class DatabaseBackupJob implements ShouldQueue
$this->backup_status = 'success';
$this->team->notify(new BackupSuccess($this->backup, $this->database));
} catch (Throwable $th) {
} catch (Throwable $e) {
$this->backup_status = 'failed';
$this->add_to_backup_output($th->getMessage());
ray('Backup failed for ' . $this->container_name . ' at ' . $this->server->name . ':' . $this->backup_location . '\n\nError:' . $th->getMessage());
$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());
$this->team->notify(new BackupFailed($this->backup, $this->database, $this->backup_output));
} finally {
$this->backup_log->update([
@ -173,9 +173,9 @@ class DatabaseBackupJob implements ShouldQueue
instant_remote_process($commands, $this->server);
$this->add_to_backup_output('Uploaded to S3.');
ray('Uploaded to S3. ' . $this->backup_location . ' to s3://' . $bucket . $this->backup_dir);
} catch (\Throwable $th) {
$this->add_to_backup_output($th->getMessage());
ray($th->getMessage());
} catch (\Throwable $e) {
$this->add_to_backup_output($e->getMessage());
ray($e->getMessage());
} finally {
$command = "docker rm -f backup-of-{$this->backup->uuid}";
instant_remote_process([$command], $this->server);

View File

@ -47,7 +47,7 @@ class DatabaseContainerStatusJob implements ShouldQueue, ShouldBeUnique
$this->database->status = $status;
$this->database->save();
}
} catch (\Exception $e) {
} catch (\Throwable $e) {
send_internal_notification('DatabaseContainerStatusJob failed with: ' . $e->getMessage());
ray($e->getMessage());
throw $e;

View File

@ -75,7 +75,7 @@ class DockerCleanupJob implements ShouldQueue
ray('No need to clean up ' . $server->name)->color('orange');
}
}
} catch (\Exception $e) {
} catch (\Throwable $e) {
send_internal_notification('DockerCleanupJob failed with: ' . $e->getMessage());
ray($e->getMessage())->color('orange');
throw $e;

View File

@ -1,46 +0,0 @@
<?php
namespace App\Jobs;
use App\Actions\Proxy\StartProxy;
use App\Models\Server;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class ProxyCheckJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function __construct()
{
}
public function handle()
{
try {
$container_name = 'coolify-proxy';
$servers = Server::all();
foreach ($servers as $server) {
if (
$server->settings->is_reachable === false || $server->settings->is_usable === false
) {
continue;
}
$status = getContainerStatus(server: $server, container_id: $container_name);
if ($status === 'running') {
continue;
}
if (data_get($server, 'proxy.type')) {
resolve(StartProxy::class)($server);
}
}
} catch (\Throwable $th) {
ray($th->getMessage());
send_internal_notification('ProxyCheckJob failed with: ' . $th->getMessage());
throw $th;
}
}
}

View File

@ -2,6 +2,8 @@
namespace App\Jobs;
use App\Actions\Proxy\StartProxy;
use App\Enums\ProxyStatus;
use App\Enums\ProxyTypes;
use App\Models\Server;
use Illuminate\Bus\Queueable;
@ -11,7 +13,6 @@ use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\Middleware\WithoutOverlapping;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Str;
class ProxyContainerStatusJob implements ShouldQueue, ShouldBeUnique
{
@ -28,31 +29,51 @@ class ProxyContainerStatusJob implements ShouldQueue, ShouldBeUnique
public function middleware(): array
{
return [new WithoutOverlapping($this->server->id)];
return [new WithoutOverlapping($this->server->uuid)];
}
public function uniqueId(): int
public function uniqueId(): string
{
return $this->server->id;
ray($this->server->uuid);
return $this->server->uuid;
}
public function handle(): void
{
try {
$container = getContainerStatus(server: $this->server, all_data: true, container_id: 'coolify-proxy', throwError: false);
$status = data_get($container, 'State.Status');
if ($status && data_get($this->server, 'proxy.status') !== $status) {
$this->server->proxy->status = $status;
if ($this->server->proxy->status === 'running') {
$traefik = $container['Config']['Labels']['org.opencontainers.image.title'];
$version = $container['Config']['Labels']['org.opencontainers.image.version'];
if (isset($version) && isset($traefik) && $traefik === 'Traefik' && Str::of($version)->startsWith('v2')) {
$this->server->proxy->type = ProxyTypes::TRAEFIK_V2->value;
}
}
$this->server->save();
$proxyType = data_get($this->server, 'proxy.type');
if ($proxyType === ProxyTypes::NONE->value) {
return;
}
} catch (\Exception $e) {
if (is_null($proxyType)) {
if ($this->server->isProxyShouldRun()) {
$this->server->proxy->type = ProxyTypes::TRAEFIK_V2->value;
$this->server->proxy->status = ProxyStatus::EXITED->value;
$this->server->save();
resolve(StartProxy::class)($this->server);
return;
}
}
$container = getContainerStatus(server: $this->server, all_data: true, container_id: 'coolify-proxy', throwError: false);
$containerStatus = data_get($container, 'State.Status');
$databaseContainerStatus = data_get($this->server, 'proxy.status', 'exited');
if ($proxyType !== ProxyTypes::NONE->value) {
if ($containerStatus === 'running') {
$this->server->proxy->status = $containerStatus;
$this->server->save();
return;
}
if ((is_null($containerStatus) ||$containerStatus !== 'running' || $databaseContainerStatus !== 'running' || ($containerStatus && $databaseContainerStatus !== $containerStatus)) && $this->server->isProxyShouldRun()) {
$this->server->proxy->status = $containerStatus;
$this->server->save();
resolve(StartProxy::class)($this->server);
return;
}
}
} catch (\Throwable $e) {
if ($e->getCode() === 1) {
$this->server->proxy->status = 'exited';
$this->server->save();

View File

@ -1,44 +0,0 @@
<?php
namespace App\Jobs;
use App\Actions\Proxy\StartProxy;
use App\Enums\ProxyStatus;
use App\Enums\ProxyTypes;
use App\Models\Server;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class ProxyStartJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function __construct(protected Server $server)
{
}
public function handle()
{
try {
$container_name = 'coolify-proxy';
ray('Starting proxy for server: ' . $this->server->name);
$status = getContainerStatus(server: $this->server, container_id: $container_name);
if ($status === 'running') {
return;
}
if (is_null(data_get($this->server, 'proxy.type'))) {
$this->server->proxy->type = ProxyTypes::TRAEFIK_V2->value;
$this->server->proxy->status = ProxyStatus::EXITED->value;
$this->server->save();
}
resolve(StartProxy::class)($this->server);
} catch (\Throwable $th) {
send_internal_notification('ProxyStartJob failed with: ' . $th->getMessage());
ray($th->getMessage());
throw $th;
}
}
}

View File

@ -1,46 +0,0 @@
<?php
namespace App\Jobs;
use App\Models\Application;
use App\Models\StandalonePostgresql;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class ResourceStatusJob implements ShouldQueue, ShouldBeUnique
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $applications;
public $postgresqls;
public function __construct()
{
$this->applications = Application::all();
$this->postgresqls = StandalonePostgresql::all();
}
public function handle(): void
{
try {
foreach ($this->applications as $application) {
dispatch(new ApplicationContainerStatusJob(
application: $application,
));
}
foreach ($this->postgresqls as $postgresql) {
dispatch(new DatabaseContainerStatusJob(
database: $postgresql,
));
}
} catch (\Exception $th) {
send_internal_notification('ResourceStatusJob failed with: ' . $th->getMessage());
ray($th);
throw $th;
}
}
}

View File

@ -34,10 +34,10 @@ class SendConfirmationForWaitlistJob implements ShouldQueue
]);
$mail->subject('You are on the waitlist!');
send_user_an_email($mail, $this->email);
} catch (\Throwable $th) {
send_internal_notification("SendConfirmationForWaitlistJob failed for {$this->email} with error: " . $th->getMessage());
ray($th->getMessage());
throw $th;
} catch (\Throwable $e) {
send_internal_notification("SendConfirmationForWaitlistJob failed for {$this->email} with error: " . $e->getMessage());
ray($e->getMessage());
throw $e;
}
}
}

View File

@ -33,10 +33,10 @@ class SubscriptionInvoiceFailedJob implements ShouldQueue
send_user_an_email($mail, $member->email);
}
});
} catch (\Throwable $th) {
send_internal_notification('SubscriptionInvoiceFailedJob failed with: ' . $th->getMessage());
ray($th->getMessage());
throw $th;
} catch (\Throwable $e) {
send_internal_notification('SubscriptionInvoiceFailedJob failed with: ' . $e->getMessage());
ray($e->getMessage());
throw $e;
}
}
}

View File

@ -20,7 +20,7 @@ class EnvironmentVariable extends Model
{
static::created(function ($environment_variable) {
if ($environment_variable->application_id && !$environment_variable->is_preview) {
$found = ModelsEnvironmentVariable::where('key', $environment_variable->key)->where('application_id', $environment_variable->application_id)->where('is_preview',true)->first();
$found = ModelsEnvironmentVariable::where('key', $environment_variable->key)->where('application_id', $environment_variable->application_id)->where('is_preview', true)->first();
if (!$found) {
ModelsEnvironmentVariable::create([
'key' => $environment_variable->key,
@ -45,26 +45,22 @@ class EnvironmentVariable extends Model
private function get_environment_variables(string $environment_variable): string|null
{
// $team_id = currentTeam()->id;
if (str_contains(trim($environment_variable), '{{') && str_contains(trim($environment_variable), '}}')) {
$environment_variable = preg_replace('/\s+/', '', $environment_variable);
$environment_variable = str_replace('{{', '', $environment_variable);
$environment_variable = str_replace('}}', '', $environment_variable);
if (str_starts_with($environment_variable, 'global.')) {
$environment_variable = str_replace('global.', '', $environment_variable);
// $environment_variable = GlobalEnvironmentVariable::where('name', $environment_variable)->where('team_id', $team_id)->first()?->value;
return $environment_variable;
}
$environment_variable = trim(decrypt($environment_variable));
if (Str::startsWith($environment_variable, '{{') && Str::endsWith($environment_variable, '}}') && Str::contains($environment_variable, 'global.')) {
$variable = Str::after($environment_variable, 'global.');
$variable = Str::before($variable, '}}');
$variable = Str::of($variable)->trim()->value;
// $environment_variable = GlobalEnvironmentVariable::where('name', $environment_variable)->where('team_id', $team_id)->first()?->value;
ray('global env variable');
return $environment_variable;
}
return decrypt($environment_variable);
return $environment_variable;
}
private function set_environment_variables(string $environment_variable): string|null
{
$environment_variable = trim($environment_variable);
if (!str_contains(trim($environment_variable), '{{') && !str_contains(trim($environment_variable), '}}')) {
return encrypt($environment_variable);
}
return $environment_variable;
return encrypt($environment_variable);
}
protected function key(): Attribute

View File

@ -24,7 +24,7 @@ class PrivateKey extends BaseModel
{
try {
return PublicKeyLoader::load($this->private_key)->getPublicKey()->toString('OpenSSH',['comment' => '']);
} catch (\Exception $e) {
} catch (\Throwable $e) {
return 'Error loading private key';
}
}

View File

@ -30,7 +30,6 @@ class Server extends BaseModel
'server_id' => $server->id,
]);
}
});
static::deleting(function ($server) {
$server->destinations()->each(function ($destination) {
@ -72,7 +71,6 @@ class Server extends BaseModel
$swarmDocker = collect($server->swarmDockers->all());
return $standaloneDocker->concat($swarmDocker);
}
public function settings()
{
return $this->hasOne(ServerSetting::class);
@ -93,7 +91,8 @@ class Server extends BaseModel
return false;
}
public function databases() {
public function databases()
{
return $this->destinations()->map(function ($standaloneDocker) {
$postgresqls = $standaloneDocker->postgresqls;
return $postgresqls?->concat([]) ?? collect([]);
@ -137,4 +136,21 @@ class Server extends BaseModel
{
return $this->belongsTo(Team::class);
}
public function isProxyShouldRun()
{
$shouldRun = false;
foreach ($this->applications() as $application) {
if (data_get($application, 'fqdn')) {
$shouldRun = true;
break;
}
}
if ($this->id === 0) {
$settings = InstanceSettings::get();
if (data_get($settings, 'fqdn')) {
$shouldRun = true;
}
}
return $shouldRun;
}
}

View File

@ -13,9 +13,10 @@ class Modal extends Component
*/
public function __construct(
public string $modalId,
public string|null $modalTitle = null,
public string|null $modalBody = null,
public string|null $modalSubmit = null,
public ?string $submitWireAction = null,
public ?string $modalTitle = null,
public ?string $modalBody = null,
public ?string $modalSubmit = null,
public bool $noSubmit = false,
public bool $yesOrNo = false,
public string $action = 'delete'

View File

@ -52,7 +52,7 @@ function format_docker_envs_to_json($rawOutput)
$env = explode('=', $env);
return [$env[0] => $env[1]];
});
} catch (\Throwable $th) {
} catch (\Throwable $e) {
return collect([]);
}
}

View File

@ -203,7 +203,7 @@ function validateServer(Server $server)
"uptime" => $uptime,
"dockerVersion" => $dockerVersion,
];
} catch (\Exception $e) {
} catch (\Throwable $e) {
$server->settings->is_reachable = false;
$server->settings->is_usable = false;
throw $e;
@ -219,7 +219,7 @@ function check_server_connection(Server $server)
instant_remote_process(['uptime'], $server);
$server->unreachable_count = 0;
$server->settings->is_reachable = true;
} catch (\Exception $e) {
} catch (\Throwable $e) {
if ($server->unreachable_count == 2) {
$server->team->notify(new NotReachable($server));
$server->settings->is_reachable = false;
@ -246,7 +246,7 @@ function checkRequiredCommands(Server $server)
}
try {
instant_remote_process(["docker run --rm --privileged --net=host --pid=host --ipc=host --volume /:/host busybox chroot /host bash -c 'apt update && apt install -y {$command}'"], $server);
} catch (\Exception $e) {
} catch (\Throwable $e) {
ray('could not install ' . $command);
ray($e);
break;

View File

@ -89,18 +89,18 @@ function general_error_handler(Throwable | null $err = null, $that = null, $isJs
}
throw new Exception($customErrorMessage ?? $err->getMessage());
}
} catch (Throwable $error) {
} catch (Throwable $e) {
if ($that) {
return $that->emit('error', $customErrorMessage ?? $error->getMessage());
return $that->emit('error', $customErrorMessage ?? $e->getMessage());
} elseif ($isJson) {
return response()->json([
'code' => $error->getCode(),
'error' => $error->getMessage(),
'code' => $e->getCode(),
'error' => $e->getMessage(),
]);
} else {
ray($customErrorMessage);
ray($error);
return $customErrorMessage ?? $error->getMessage();
ray($e);
return $customErrorMessage ?? $e->getMessage();
}
}
}
@ -116,9 +116,9 @@ 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 $th) {
//throw $th;
ray($th->getMessage());
} catch (Throwable $e) {
//throw $e;
ray($e->getMessage());
return '0.0.0';
}
}
@ -258,8 +258,8 @@ function send_internal_notification(string $message): void
$baseUrl = config('app.name');
$team = Team::find(0);
$team->notify(new GeneralNotification("👀 {$baseUrl}: " . $message));
} catch (\Throwable $th) {
ray($th->getMessage());
} catch (\Throwable $e) {
ray($e->getMessage());
}
}
function send_user_an_email(MailMessage $mail, string $email): void

View File

@ -35,7 +35,8 @@
"spatie/url": "^2.2",
"stripe/stripe-php": "^12.0",
"symfony/yaml": "^6.2",
"visus/cuid2": "^2.0.0"
"visus/cuid2": "^2.0.0",
"yosymfony/toml": "^1.0"
},
"require-dev": {
"fakerphp/faker": "^v1.21.0",

112
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "0603276b60e77cd859fabacdaaf31550",
"content-hash": "cf138424c896f30b035bc8cdff63e8d1",
"packages": [
{
"name": "aws/aws-crt-php",
@ -9771,6 +9771,116 @@
},
"time": "2022-06-03T18:03:27+00:00"
},
{
"name": "yosymfony/parser-utils",
"version": "v2.0.0",
"source": {
"type": "git",
"url": "https://github.com/yosymfony/parser-utils.git",
"reference": "00bec9a12722b21f2baf7f9db35f127e90c162c9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/yosymfony/parser-utils/zipball/00bec9a12722b21f2baf7f9db35f127e90c162c9",
"reference": "00bec9a12722b21f2baf7f9db35f127e90c162c9",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"require-dev": {
"phpunit/phpunit": "^6"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"psr-4": {
"Yosymfony\\ParserUtils\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Victor Puertas",
"email": "vpgugr@gmail.com",
"homepage": "http://yosymfony.com"
}
],
"description": "Parser utilities",
"homepage": "http://github.com/yosymfony/toml",
"keywords": [
"lexer",
"parser"
],
"support": {
"issues": "https://github.com/yosymfony/parser-utils/issues",
"source": "https://github.com/yosymfony/parser-utils/tree/master"
},
"time": "2018-06-29T15:31:11+00:00"
},
{
"name": "yosymfony/toml",
"version": "v1.0.4",
"source": {
"type": "git",
"url": "https://github.com/yosymfony/toml.git",
"reference": "bdab92ad920d0e36810a3a3e4a998d23f3498f8e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/yosymfony/toml/zipball/bdab92ad920d0e36810a3a3e4a998d23f3498f8e",
"reference": "bdab92ad920d0e36810a3a3e4a998d23f3498f8e",
"shasum": ""
},
"require": {
"php": ">=7.1",
"yosymfony/parser-utils": "^2.0"
},
"require-dev": {
"phpunit/phpunit": "^7.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"psr-4": {
"Yosymfony\\Toml\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Victor Puertas",
"email": "vpgugr@gmail.com",
"homepage": "http://yosymfony.com"
}
],
"description": "A PHP parser for TOML compatible with specification 0.4.0",
"homepage": "http://github.com/yosymfony/toml",
"keywords": [
"mojombo",
"parser",
"toml"
],
"support": {
"issues": "https://github.com/yosymfony/toml/issues",
"source": "https://github.com/yosymfony/toml/tree/master"
},
"time": "2018-08-08T15:08:14+00:00"
},
{
"name": "zbateson/mail-mime-parser",
"version": "2.4.0",

View File

@ -39,7 +39,7 @@ return [
'queue' => 'long-running',
'retry_after' => 3600,
'block_for' => null,
'after_commit' => false,
'after_commit' => true,
],
'database' => [
'driver' => 'database',
@ -75,7 +75,7 @@ return [
'queue' => env('REDIS_QUEUE', 'default'),
'retry_after' => 300,
'block_for' => null,
'after_commit' => false,
'after_commit' => true,
],
],

View File

@ -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.33',
'release' => '4.0.0-beta.34',
'server_name' => env('APP_ID', 'coolify'),
// When left empty or `null` the Laravel environment will be used
'environment' => config('app.env'),

View File

@ -1,3 +1,3 @@
<?php
return '4.0.0-beta.33';
return '4.0.0-beta.34';

View File

@ -0,0 +1,22 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('applications', function (Blueprint $table) {
$table->string('nixpkgsarchive')->nullable();
});
}
public function down(): void
{
Schema::table('teams', function (Blueprint $table) {
$table->dropColumn('nixpkgsarchive');
});
}
};

View File

@ -38,7 +38,7 @@ class InstanceSettingsSeeder extends Seeder
if (is_null($settings->public_ipv6) && $ipv6) {
$settings->update(['public_ipv6' => $ipv6]);
}
} catch (\Exception $e) {
} catch (\Throwable $e) {
echo "Error: {$e->getMessage()}\n";
}
}

View File

@ -119,7 +119,7 @@ class ProductionSeeder extends Seeder
$settings->update(['public_ipv6' => $ipv6]);
}
}
} catch (\Exception $e) {
} catch (\Throwable $e) {
echo "Error: {$e->getMessage()}\n";
}
}

View File

@ -10,7 +10,7 @@ ARG DOCKER_BUILDX_VERSION=0.11.2
# https://github.com/buildpacks/pack/releases
ARG PACK_VERSION=0.30.0
# https://github.com/railwayapp/nixpacks/releases
ARG NIXPACKS_VERSION=1.13.0
ARG NIXPACKS_VERSION=1.14.0
USER root
WORKDIR /artifacts

View File

@ -10,7 +10,7 @@ ARG DOCKER_BUILDX_VERSION=0.11.2
# https://github.com/buildpacks/pack/releases
ARG PACK_VERSION=0.30.0
# https://github.com/railwayapp/nixpacks/releases
ARG NIXPACKS_VERSION=1.13.0
ARG NIXPACKS_VERSION=1.14.0
USER root
WORKDIR /root

View File

@ -34,7 +34,8 @@
</form>
@else
<form method="dialog" class="flex flex-col w-11/12 max-w-5xl gap-2 rounded modal-box"
@if(!$noSubmit) wire:submit.prevent='submit' @endif>
@if($submitWireAction) wire:submit.prevent={{$submitWireAction}} @endif
@if(!$noSubmit && !$submitWireAction) wire:submit.prevent='submit' @endif>
@isset($modalTitle)
<h3 class="text-lg font-bold">{{ $modalTitle }}</h3>
@endisset

View File

@ -20,6 +20,9 @@
}
</style>
@livewireStyles
@if (config('app.name') == 'Coolify Cloud')
<script defer data-domain="app.coolify.io" src="https://analytics.coollabs.io/js/plausible.js"></script>
@endif
</head>
@section('body')

View File

@ -26,11 +26,17 @@
@endif
@endif
</div>
<x-forms.select id="application.build_pack" label="Build Pack" required>
<option value="nixpacks">Nixpacks</option>
<option value="dockerfile">Dockerfile</option>
<option disabled value="compose">Compose</option>
</x-forms.select>
<div class="flex items-end gap-2">
<x-forms.select id="application.build_pack" label="Build Pack" required>
<option value="nixpacks">Nixpacks</option>
<option value="dockerfile">Dockerfile</option>
<option disabled value="compose">Compose</option>
</x-forms.select>
{{-- @if ($application->build_pack === 'nixpacks')
<x-forms.input id="application.nixpkgsarchive" label="NixPackages Archive (nixpkgsArchive)"
helper="You can customize the NixPackages archive to use."> </x-forms.input>
@endif --}}
</div>
@if ($application->settings->is_static)
<x-forms.select id="application.static_image" label="Static Image" required>
<option value="nginx:alpine">nginx:alpine</option>

View File

@ -52,16 +52,15 @@
</x-forms.button>
@endif
@if ($server->settings->is_reachable && !$server->settings->is_usable && $server->id !== 0)
<x-forms.button wire:poll.2000ms='validateServer' class="mt-8 mb-4 box" onclick="installDocker.showModal()" wire:click.prevent='installDocker' isHighlighted>
Install Docker Engine 24.0
<x-forms.button wire:poll.2000ms='validateServer' class="mt-8 mb-4 box" onclick="installDocker.showModal()"
wire:click.prevent='installDocker' isHighlighted>
Install Docker Engine 24.0
</x-forms.button>
@endif
@if ($server->settings->is_usable)
<h3 class="py-4">Settings</h3>
<div class="flex items-center w-64 gap-2">
<x-forms.input id="cleanup_after_percentage" label="Disk Cleanup threshold (%)" required
helper="Disk cleanup job will be executed if disk usage is more than this number." />
</div>
@endif
</form>
<h2 class="pt-4">Danger Zone</h2>

View File

@ -1,7 +1,17 @@
<div>
@if ($server->settings->is_usable)
@if ($server->proxy->type)
<div x-init="$wire.load_proxy_configuration">
@if (data_get($server,'settings.is_usable'))
@if (data_get($server,'proxy.type'))
<x-modal submitWireAction="proxyStatusUpdated" modalId="startProxy">
<x-slot:modalBody>
<livewire:activity-monitor header="Proxy Startup Logs" />
</x-slot:modalBody>
<x-slot:modalSubmit>
<x-forms.button onclick="startProxy.close()" type="submit">
Close
</x-forms.button>
</x-slot:modalSubmit>
</x-modal>
<div x-init="$wire.loadProxyConfiguration">
@if ($selectedProxy === 'TRAEFIK_V2')
<form wire:submit.prevent='submit'>
<div class="flex items-center gap-2">
@ -19,15 +29,12 @@
configurations.
</div>
@endif
<div class="container w-full pb-4 mx-auto">
<livewire:activity-monitor header="Logs" />
</div>
<x-forms.input placeholder="https://coolify.io" id="redirect_url" label="Default Redirect 404"
helper="All urls that has no service available will be redirected to this domain.<span class='text-helper'>You can set to your main marketing page or your social media link.</span>" />
<div wire:loading wire:target="load_proxy_configuration" class="pt-4">
<div wire:loading wire:target="loadProxyConfiguration" class="pt-4">
<x-loading text="Loading proxy configuration..." />
</div>
<div wire:loading.remove wire:target="load_proxy_configuration">
<div wire:loading.remove wire:target="loadProxyConfiguration">
@if ($proxy_settings)
<div class="flex flex-col gap-2 pt-2">
<x-forms.textarea label="Configuration file: traefik.conf" name="proxy_settings"

View File

@ -7,16 +7,7 @@
</p>
</x-slot:modalBody>
</x-modal>
<x-modal yesOrNo modalId="startProxy" modalTitle="Start Proxy" action="start_proxy">
<x-slot:modalBody>
<p>This will start the proxy on this server and
<x-highlighted text="stop any running process that is using port 80 and 443" />.
<br>Please think
again.
</p>
</x-slot:modalBody>
</x-modal>
@if (data_get($server, 'proxy.type'))
@if (is_null(data_get($server, 'proxy.type')) || data_get($server, 'proxy.type') !== 'NONE')
@if (data_get($server, 'proxy.status') === 'running')
<div class="flex gap-4">
<button>
@ -37,8 +28,8 @@
</x-forms.button>
</div>
@else
<x-forms.button isModal noStyle modalId="startProxy"
class="flex items-center gap-2 cursor-pointer hover:text-white">
<button wire:click='startProxy' onclick="startProxy.showModal()"
class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400">
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-warning" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
stroke-linejoin="round">
@ -46,7 +37,7 @@
<path d="M7 4v16l13 -8z" />
</svg>
Start Proxy
</x-forms.button>
</button>
@endif
@endif
</div>

View File

@ -1,4 +1,4 @@
<div wire:poll.10000ms="get_status" x-init="$wire.get_status">
<div class="flex gap-2" x-init="$wire.getProxyStatus">
@if ($server->proxy->status === 'running')
<x-status.running text="Proxy Running" />
@elseif ($server->proxy->status === 'restarting')
@ -6,4 +6,13 @@
@else
<x-status.stopped text="Proxy Stopped" />
@endif
<button wire:click.prevent='getProxyStatusWithNoti'><svg class="icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<g fill="#FCD44F">
<path
d="M12.079 3v-.75V3Zm-8.4 8.333h-.75h.75Zm0 1.667l-.527.532a.75.75 0 0 0 1.056 0L3.68 13Zm2.209-1.134A.75.75 0 1 0 4.83 10.8l1.057 1.065ZM2.528 10.8a.75.75 0 0 0-1.056 1.065L2.528 10.8Zm16.088-3.408a.75.75 0 1 0 1.277-.786l-1.277.786ZM12.079 2.25c-5.047 0-9.15 4.061-9.15 9.083h1.5c0-4.182 3.42-7.583 7.65-7.583v-1.5Zm-9.15 9.083V13h1.5v-1.667h-1.5Zm1.28 2.2l1.679-1.667L4.83 10.8l-1.68 1.667l1.057 1.064Zm0-1.065L2.528 10.8l-1.057 1.065l1.68 1.666l1.056-1.064Zm15.684-5.86A9.158 9.158 0 0 0 12.08 2.25v1.5a7.658 7.658 0 0 1 6.537 3.643l1.277-.786Z" />
<path fill="#fff"
d="M11.883 21v.75V21Zm8.43-8.333h.75h-.75Zm0-1.667l.528-.533a.75.75 0 0 0-1.055 0l.528.533ZM18.1 12.133a.75.75 0 1 0 1.055 1.067L18.1 12.133Zm3.373 1.067a.75.75 0 1 0 1.054-1.067L21.473 13.2ZM5.318 16.606a.75.75 0 1 0-1.277.788l1.277-.788Zm6.565 5.144c5.062 0 9.18-4.058 9.18-9.083h-1.5c0 4.18-3.43 7.583-7.68 7.583v1.5Zm9.18-9.083V11h-1.5v1.667h1.5Zm-1.277-2.2L18.1 12.133l1.055 1.067l1.686-1.667l-1.055-1.066Zm0 1.066l1.687 1.667l1.054-1.067l-1.686-1.666l-1.055 1.066Zm-15.745 5.86a9.197 9.197 0 0 0 7.841 4.357v-1.5a7.697 7.697 0 0 1-6.564-3.644l-1.277.788Z"
opacity=".5" />
</g>
</svg></button>
</div>

View File

@ -11,7 +11,7 @@
</form>
</dialog>
<div class="flex items-center gap-2">
<h2>Transactional/Shared Email</h2>
<h2>Transactional Email</h2>
</div>
<div class="pb-4 ">Email settings for password resets, invitations, shared with Pro+ subscribers etc.</div>
<form wire:submit.prevent='submitFromFields' class="pb-4">

View File

@ -7,7 +7,7 @@
<a :class="activeTab === 'backup' && 'text-white'"
@click.prevent="activeTab = 'backup'; window.location.hash = 'backup'" href="#">Instance Backup</a>
<a :class="activeTab === 'smtp' && 'text-white'"
@click.prevent="activeTab = 'smtp'; window.location.hash = 'smtp'" href="#">Transactional/Shared Email</a>
@click.prevent="activeTab = 'smtp'; window.location.hash = 'smtp'" href="#">Transactional Email</a>
</div>
<div class="w-full pl-8">
<div x-cloak x-show="activeTab === 'general'" class="h-full">

View File

@ -49,7 +49,7 @@ Route::post('/forgot-password', function (Request $request) {
return response()->json(['message' => 'Transactional emails are not active'], 400);
})->name('password.forgot');
Route::get('/waitlist', WaitlistIndex::class)->name('waitlist.index');
Route::middleware(['throttle:login'])->group(function() {
Route::middleware(['throttle:login'])->group(function () {
Route::get('/auth/link', [Controller::class, 'link'])->name('auth.link');
});
Route::prefix('magic')->middleware(['auth'])->group(function () {
@ -143,7 +143,11 @@ Route::middleware(['auth'])->group(function () {
]);
})->name('source.all');
Route::get('/source/github/{github_app_uuid}', function (Request $request) {
$github_app = GithubApp::where('uuid', request()->github_app_uuid)->first()->makeVisible('client_secret')->makeVisible('webhook_secret');
$github_app = GithubApp::where('uuid', request()->github_app_uuid)->first();
if (!$github_app) {
abort(404);
}
$github_app->makeVisible('client_secret')->makeVisible('webhook_secret');
$settings = InstanceSettings::get();
$name = Str::of(Str::kebab($github_app->name));
if ($settings->public_ipv4) {

View File

@ -4,7 +4,7 @@
"version": "3.12.36"
},
"v4": {
"version": "4.0.0-beta.33"
"version": "4.0.0-beta.34"
}
}
}