diff --git a/app/Actions/Server/CleanupDocker.php b/app/Actions/Server/CleanupDocker.php new file mode 100644 index 000000000..4faeccf1a --- /dev/null +++ b/app/Actions/Server/CleanupDocker.php @@ -0,0 +1,23 @@ +server) { return; } + CleanupDocker::run($this->server, false); $this->latestVersion = get_latest_version_of_coolify(); $this->currentVersion = config('version'); ray('latest version:' . $this->latestVersion . " current version: " . $this->currentVersion . ' force: ' . $force); diff --git a/app/Console/Commands/ServicesDelete.php b/app/Console/Commands/ServicesDelete.php index 31ccfa9a9..bc30bd842 100644 --- a/app/Console/Commands/ServicesDelete.php +++ b/app/Console/Commands/ServicesDelete.php @@ -2,6 +2,7 @@ namespace App\Console\Commands; +use App\Jobs\DeleteResourceJob; use App\Models\Application; use App\Models\Server; use App\Models\Service; @@ -91,7 +92,7 @@ class ServicesDelete extends Command if (!$confirmed) { break; } - $toDelete->delete(); + DeleteResourceJob::dispatch($toDelete); } } } @@ -115,7 +116,7 @@ class ServicesDelete extends Command if (!$confirmed) { return; } - $toDelete->delete(); + DeleteResourceJob::dispatch($toDelete); } } } @@ -139,7 +140,7 @@ class ServicesDelete extends Command if (!$confirmed) { return; } - $toDelete->delete(); + DeleteResourceJob::dispatch($toDelete); } } } diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 267572b39..7dbead831 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -72,7 +72,7 @@ class Kernel extends ConsoleKernel } } foreach ($servers as $server) { - $schedule->job(new ServerStatusJob($server))->everyTenMinutes()->onOneServer(); + $schedule->job(new ServerStatusJob($server))->everyFiveMinutes()->onOneServer(); } } private function instance_auto_update($schedule) diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index b7534952c..e846f9f61 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -203,7 +203,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted dispatch(new ContainerStatusJob($this->server)); } $this->next(ApplicationDeploymentStatus::FINISHED->value); - $this->application->isConfigurationChanged(true); + $this->application->isConfigurationChanged(false); return; } else if ($this->application->dockerfile) { $this->deploy_simple_dockerfile(); @@ -738,13 +738,15 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted $this->generate_nixpacks_confs(); } $this->generate_compose_file(); + // Needs separate preview variables $this->generate_build_env_variables(); - $this->add_build_env_variables_to_dockerfile(); + if ($this->application->build_pack !== 'nixpacks') { + $this->add_build_env_variables_to_dockerfile(); + } $this->build_image(); $this->stop_running_container(); if ($this->application->destination->server->isSwarm()) { - ray("{$this->workdir}{$this->docker_compose_location}"); $this->push_to_docker_registry(); $this->execute_remote_command( [ @@ -911,10 +913,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted if ($this->nixpacks_plan) { $parsed = Toml::Parse($this->nixpacks_plan); // Do any modifications here - // $cmds = collect(data_get($parsed, 'phases.setup.cmds', [])); $this->generate_env_variables(); - // data_set($parsed, 'phases.setup.cmds', $cmds); - ray($this->env_args->toArray()); $merged_envs = $this->env_args->merge(collect(data_get($parsed, 'variables', []))); data_set($parsed, 'variables', $merged_envs->toArray()); $this->nixpacks_plan = json_encode($parsed, JSON_PRETTY_PRINT); diff --git a/app/Jobs/DockerCleanupJob.php b/app/Jobs/DockerCleanupJob.php index a48ddd248..69c445801 100644 --- a/app/Jobs/DockerCleanupJob.php +++ b/app/Jobs/DockerCleanupJob.php @@ -2,6 +2,7 @@ namespace App\Jobs; +use App\Actions\Server\CleanupDocker; use App\Models\Server; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldBeEncrypted; @@ -43,9 +44,7 @@ class DockerCleanupJob implements ShouldQueue, ShouldBeEncrypted ray('Usage before: ' . $this->usageBefore); if ($this->usageBefore >= $this->server->settings->cleanup_after_percentage) { ray('Cleaning up ' . $this->server->name); - instant_remote_process(['docker image prune -af'], $this->server, false); - instant_remote_process(['docker container prune -f --filter "label=coolify.managed=true"'], $this->server, false); - instant_remote_process(['docker builder prune -af'], $this->server, false); + CleanupDocker::run($this->server); $usageAfter = $this->server->getDiskUsage(); if ($usageAfter < $this->usageBefore) { ray('Saved ' . ($this->usageBefore - $usageAfter) . '% disk space on ' . $this->server->name); diff --git a/app/Jobs/ScheduledTaskJob.php b/app/Jobs/ScheduledTaskJob.php index 104b5f7e3..49511ad95 100644 --- a/app/Jobs/ScheduledTaskJob.php +++ b/app/Jobs/ScheduledTaskJob.php @@ -108,7 +108,7 @@ class ScheduledTaskJob implements ShouldQueue 'message' => $this->task_output ?? $e->getMessage(), ]); } - send_internal_notification('ScheduledTaskJob failed with: ' . $e->getMessage()); + // send_internal_notification('ScheduledTaskJob failed with: ' . $e->getMessage()); throw $e; } } diff --git a/app/Livewire/Project/Resource/Index.php b/app/Livewire/Project/Resource/Index.php index 2a7570c9d..718b5003c 100644 --- a/app/Livewire/Project/Resource/Index.php +++ b/app/Livewire/Project/Resource/Index.php @@ -10,7 +10,15 @@ class Index extends Component { public Project $project; public Environment $environment; - public function mount () { + public $applications = []; + public $postgresqls = []; + public $redis = []; + public $mongodbs = []; + public $mysqls = []; + public $mariadbs = []; + public $services = []; + public function mount() + { $project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first(); if (!$project) { return redirect()->route('dashboard'); @@ -21,6 +29,84 @@ class Index extends Component } $this->project = $project; $this->environment = $environment; + $this->applications = $environment->applications->sortBy('name'); + $this->applications = $this->applications->map(function ($application) { + if (data_get($application, 'environment.project.uuid')) { + $application->hrefLink = route('project.application.configuration', [ + 'project_uuid' => data_get($application, 'environment.project.uuid'), + 'environment_name' => data_get($application, 'environment.name'), + 'application_uuid' => data_get($application, 'uuid') + ]); + } + return $application; + }); + $this->postgresqls = $environment->postgresqls->sortBy('name'); + $this->postgresqls = $this->postgresqls->map(function ($postgresql) { + if (data_get($postgresql, 'environment.project.uuid')) { + $postgresql->hrefLink = route('project.database.configuration', [ + 'project_uuid' => data_get($postgresql, 'environment.project.uuid'), + 'environment_name' => data_get($postgresql, 'environment.name'), + 'database_uuid' => data_get($postgresql, 'uuid') + ]); + } + return $postgresql; + }); + $this->redis = $environment->redis->sortBy('name'); + $this->redis = $this->redis->map(function ($redis) { + if (data_get($redis, 'environment.project.uuid')) { + $redis->hrefLink = route('project.database.configuration', [ + 'project_uuid' => data_get($redis, 'environment.project.uuid'), + 'environment_name' => data_get($redis, 'environment.name'), + 'database_uuid' => data_get($redis, 'uuid') + ]); + } + return $redis; + }); + $this->mongodbs = $environment->mongodbs->sortBy('name'); + $this->mongodbs = $this->mongodbs->map(function ($mongodb) { + if (data_get($mongodb, 'environment.project.uuid')) { + $mongodb->hrefLink = route('project.database.configuration', [ + 'project_uuid' => data_get($mongodb, 'environment.project.uuid'), + 'environment_name' => data_get($mongodb, 'environment.name'), + 'database_uuid' => data_get($mongodb, 'uuid') + ]); + } + return $mongodb; + }); + $this->mysqls = $environment->mysqls->sortBy('name'); + $this->mysqls = $this->mysqls->map(function ($mysql) { + if (data_get($mysql, 'environment.project.uuid')) { + $mysql->hrefLink = route('project.database.configuration', [ + 'project_uuid' => data_get($mysql, 'environment.project.uuid'), + 'environment_name' => data_get($mysql, 'environment.name'), + 'database_uuid' => data_get($mysql, 'uuid') + ]); + } + return $mysql; + }); + $this->mariadbs = $environment->mariadbs->sortBy('name'); + $this->mariadbs = $this->mariadbs->map(function ($mariadb) { + if (data_get($mariadb, 'environment.project.uuid')) { + $mariadb->hrefLink = route('project.database.configuration', [ + 'project_uuid' => data_get($mariadb, 'environment.project.uuid'), + 'environment_name' => data_get($mariadb, 'environment.name'), + 'database_uuid' => data_get($mariadb, 'uuid') + ]); + } + return $mariadb; + }); + $this->services = $environment->services->sortBy('name'); + $this->services = $this->services->map(function ($service) { + if (data_get($service, 'environment.project.uuid')) { + $service->hrefLink = route('project.service.configuration', [ + 'project_uuid' => data_get($service, 'environment.project.uuid'), + 'environment_name' => data_get($service, 'environment.name'), + 'service_uuid' => data_get($service, 'uuid') + ]); + $service->status = serviceStatus($service); + } + return $service; + }); } public function render() { diff --git a/app/Livewire/Project/Shared/ExecuteContainerCommand.php b/app/Livewire/Project/Shared/ExecuteContainerCommand.php index f06f7784d..1ffcd810b 100644 --- a/app/Livewire/Project/Shared/ExecuteContainerCommand.php +++ b/app/Livewire/Project/Shared/ExecuteContainerCommand.php @@ -108,8 +108,7 @@ class ExecuteContainerCommand extends Component $this->validate(); try { // Wrap command to prevent escaped execution in the host. - $cmd = 'sh -c "' . str_replace('"', '\"', $this->command) . '"'; - + $cmd = 'sh -c "if [ -f ~/.profile ]; then . ~/.profile; fi; ' . str_replace('"', '\"', $this->command) . '"'; if (!empty($this->workDir)) { $exec = "docker exec -w {$this->workDir} {$this->container} {$cmd}"; } else { diff --git a/bootstrap/helpers/remoteProcess.php b/bootstrap/helpers/remoteProcess.php index f49c7cafc..da6705e4c 100644 --- a/bootstrap/helpers/remoteProcess.php +++ b/bootstrap/helpers/remoteProcess.php @@ -126,7 +126,7 @@ function generateSshCommand(Server $server, string $command, bool $isMux = true) if (data_get($server, 'settings.is_cloudflare_tunnel')) { $ssh_command .= '-o ProxyCommand="/usr/local/bin/cloudflared access ssh --hostname %h" '; } - $command = "PATH=\$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/host/usr/local/sbin:/host/usr/local/bin:/host/usr/sbin:/host/usr/bin:/host/sbin:/host/bin && $command"; + $command = "test -f ~/.profile && . ~/.profile; PATH=\$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/host/usr/local/sbin:/host/usr/local/bin:/host/usr/sbin:/host/usr/bin:/host/sbin:/host/bin && $command"; $ssh_command .= "-i {$privateKeyLocation} " . '-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ' . '-o PasswordAuthentication=no ' diff --git a/config/sentry.php b/config/sentry.php index e793c9f2b..2d526fb85 100644 --- a/config/sentry.php +++ b/config/sentry.php @@ -7,7 +7,7 @@ return [ // The release version of your application // Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD')) - 'release' => '4.0.0-beta.188', + 'release' => '4.0.0-beta.189', // When left empty or `null` the Laravel environment will be used 'environment' => config('app.env'), diff --git a/config/version.php b/config/version.php index d91322b99..dec4e2c54 100644 --- a/config/version.php +++ b/config/version.php @@ -1,3 +1,3 @@ -

Command Center

-
Execute commands on your servers without leaving the browser.
- @if ($servers->count() > 0) - - @else -
-
No servers found. Without a server, you won't be able to do much.
- -
- @endif - diff --git a/resources/views/livewire/project/resource/index.blade.php b/resources/views/livewire/project/resource/index.blade.php index a1ff05693..921e9c360 100644 --- a/resources/views/livewire/project/resource/index.blade.php +++ b/resources/views/livewire/project/resource/index.blade.php @@ -44,54 +44,216 @@ + Add New Resource @endif -
- @foreach ($environment->applications->sortBy('name') as $application) - -
-
{{ $application->name }}
-
{{ $application->description }}
-
- @if (Str::of(data_get($application, 'status'))->startsWith('running')) -
- @elseif (Str::of(data_get($application, 'status'))->startsWith('exited')) -
- @elseif (Str::of(data_get($application, 'status'))->startsWith('restarting')) -
- @endif -
- @endforeach - @foreach ($environment->databases()->sortBy('name') as $database) - -
-
{{ $database->name }}
-
{{ $database->description }}
-
- @if (Str::of(data_get($database, 'status'))->startsWith('running')) -
- @elseif (Str::of(data_get($database, 'status'))->startsWith('exited')) -
- @elseif (Str::of(data_get($database, 'status'))->startsWith('restaring')) -
- @endif -
- @endforeach - @foreach ($environment->services->sortBy('name') as $service) - -
-
{{ $service->name }}
-
{{ $service->description }}
-
- @if (Str::of(serviceStatus($service))->startsWith('running')) -
- @elseif (Str::of(serviceStatus($service))->startsWith('degraded')) -
- @elseif (Str::of(serviceStatus($service))->startsWith('exited')) -
- @endif -
- @endforeach +
+ +
+ + + + + + + +
+ + diff --git a/resources/views/profile.blade.php b/resources/views/profile.blade.php deleted file mode 100644 index 9ad4d347f..000000000 --- a/resources/views/profile.blade.php +++ /dev/null @@ -1,83 +0,0 @@ - -

Profile

-
Your user profile settings.
- -

Subscription

- Check in Team Settings -

Two-factor Authentication

- @if (session('status') == 'two-factor-authentication-enabled') -
- Please finish configuring two factor authentication below. Read the QR code or enter the secret key - manually. -
-
-
- @csrf - - Validate 2FA - -
-
{!! $request->user()->twoFactorQrCodeSvg() !!}
-
- - Show secret key to manually - enter -
-
-
- @elseif(session('status') == 'two-factor-authentication-confirmed') -
- Two factor authentication confirmed and enabled successfully. -
-
-
Here are the recovery codes for your account. Please store them in a secure - location. -
-
- @foreach ($request->user()->recoveryCodes() as $code) -
{{ $code }}
- @endforeach -
-
- @else - @if ($request->user()->two_factor_confirmed_at) -
Two factor authentication is enabled.
-
-
- @csrf - @method ('DELETE') - Disable -
-
- @csrf - Regenerate Recovery Codes -
-
- @if (session('status') == 'recovery-codes-generated') -
-
Here are the recovery codes for your account. Please store them in a - secure - location. -
-
- @foreach ($request->user()->recoveryCodes() as $code) -
{{ $code }}
- @endforeach -
-
- @endif - @else -
- @csrf - Configure 2FA -
- @endif - @endif - @if (session()->has('errors')) -
- Something went wrong. Please try again. -
- @endif -
diff --git a/versions.json b/versions.json index cdbe57934..a8d4bd649 100644 --- a/versions.json +++ b/versions.json @@ -4,7 +4,7 @@ "version": "3.12.36" }, "v4": { - "version": "4.0.0-beta.188" + "version": "4.0.0-beta.189" } } }