Merge pull request #2677 from coollabsio/next

v4.0.0-beta.305
This commit is contained in:
Andras Bacsai 2024-06-25 12:53:11 +02:00 committed by GitHub
commit cc36a0ecd1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
55 changed files with 228 additions and 199 deletions

View File

@ -3,6 +3,7 @@
namespace App\Actions\CoolifyTask; namespace App\Actions\CoolifyTask;
use App\Data\CoolifyTaskArgs; use App\Data\CoolifyTaskArgs;
use App\Enums\ActivityTypes;
use App\Jobs\CoolifyTask; use App\Jobs\CoolifyTask;
use Spatie\Activitylog\Models\Activity; use Spatie\Activitylog\Models\Activity;
@ -40,8 +41,18 @@ class PrepareCoolifyTask
public function __invoke(): Activity public function __invoke(): Activity
{ {
$job = new CoolifyTask($this->activity, ignore_errors: $this->remoteProcessArgs->ignore_errors, call_event_on_finish: $this->remoteProcessArgs->call_event_on_finish, call_event_data: $this->remoteProcessArgs->call_event_data); $job = new CoolifyTask(
activity: $this->activity,
ignore_errors: $this->remoteProcessArgs->ignore_errors,
call_event_on_finish: $this->remoteProcessArgs->call_event_on_finish,
call_event_data: $this->remoteProcessArgs->call_event_data,
);
if ($this->remoteProcessArgs->type === ActivityTypes::COMMAND->value) {
ray('Dispatching a high priority job');
dispatch($job)->onQueue('high');
} else {
dispatch($job); dispatch($job);
}
$this->activity->refresh(); $this->activity->refresh();
return $this->activity; return $this->activity;

View File

@ -39,7 +39,7 @@ class RunRemoteProcess
public function __construct(Activity $activity, bool $hide_from_output = false, bool $ignore_errors = false, $call_event_on_finish = null, $call_event_data = null) public function __construct(Activity $activity, bool $hide_from_output = false, bool $ignore_errors = false, $call_event_on_finish = null, $call_event_data = null)
{ {
if ($activity->getExtraProperty('type') !== ActivityTypes::INLINE->value) { if ($activity->getExtraProperty('type') !== ActivityTypes::INLINE->value && $activity->getExtraProperty('type') !== ActivityTypes::COMMAND->value) {
throw new \RuntimeException('Incompatible Activity to run a remote command.'); throw new \RuntimeException('Incompatible Activity to run a remote command.');
} }

View File

@ -3,7 +3,6 @@
namespace App\Actions\Database; namespace App\Actions\Database;
use App\Models\StandaloneClickhouse; use App\Models\StandaloneClickhouse;
use Illuminate\Support\Str;
use Lorisleiva\Actions\Concerns\AsAction; use Lorisleiva\Actions\Concerns\AsAction;
use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Yaml;
@ -155,11 +154,11 @@ class StartClickhouse
$environment_variables->push("$env->key=$env->real_value"); $environment_variables->push("$env->key=$env->real_value");
} }
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('CLICKHOUSE_ADMIN_USER'))->isEmpty()) { if ($environment_variables->filter(fn ($env) => str($env)->contains('CLICKHOUSE_ADMIN_USER'))->isEmpty()) {
$environment_variables->push("CLICKHOUSE_ADMIN_USER={$this->database->clickhouse_admin_user}"); $environment_variables->push("CLICKHOUSE_ADMIN_USER={$this->database->clickhouse_admin_user}");
} }
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('CLICKHOUSE_ADMIN_PASSWORD'))->isEmpty()) { if ($environment_variables->filter(fn ($env) => str($env)->contains('CLICKHOUSE_ADMIN_PASSWORD'))->isEmpty()) {
$environment_variables->push("CLICKHOUSE_ADMIN_PASSWORD={$this->database->clickhouse_admin_password}"); $environment_variables->push("CLICKHOUSE_ADMIN_PASSWORD={$this->database->clickhouse_admin_password}");
} }

View File

@ -3,7 +3,6 @@
namespace App\Actions\Database; namespace App\Actions\Database;
use App\Models\StandaloneDragonfly; use App\Models\StandaloneDragonfly;
use Illuminate\Support\Str;
use Lorisleiva\Actions\Concerns\AsAction; use Lorisleiva\Actions\Concerns\AsAction;
use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Yaml;
@ -155,7 +154,7 @@ class StartDragonfly
$environment_variables->push("$env->key=$env->real_value"); $environment_variables->push("$env->key=$env->real_value");
} }
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('REDIS_PASSWORD'))->isEmpty()) { if ($environment_variables->filter(fn ($env) => str($env)->contains('REDIS_PASSWORD'))->isEmpty()) {
$environment_variables->push("REDIS_PASSWORD={$this->database->dragonfly_password}"); $environment_variables->push("REDIS_PASSWORD={$this->database->dragonfly_password}");
} }

View File

@ -4,7 +4,6 @@ namespace App\Actions\Database;
use App\Models\StandaloneKeydb; use App\Models\StandaloneKeydb;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Lorisleiva\Actions\Concerns\AsAction; use Lorisleiva\Actions\Concerns\AsAction;
use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Yaml;
@ -163,7 +162,7 @@ class StartKeydb
$environment_variables->push("$env->key=$env->real_value"); $environment_variables->push("$env->key=$env->real_value");
} }
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('REDIS_PASSWORD'))->isEmpty()) { if ($environment_variables->filter(fn ($env) => str($env)->contains('REDIS_PASSWORD'))->isEmpty()) {
$environment_variables->push("REDIS_PASSWORD={$this->database->keydb_password}"); $environment_variables->push("REDIS_PASSWORD={$this->database->keydb_password}");
} }

View File

@ -3,7 +3,6 @@
namespace App\Actions\Database; namespace App\Actions\Database;
use App\Models\StandaloneMariadb; use App\Models\StandaloneMariadb;
use Illuminate\Support\Str;
use Lorisleiva\Actions\Concerns\AsAction; use Lorisleiva\Actions\Concerns\AsAction;
use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Yaml;
@ -157,18 +156,18 @@ class StartMariadb
$environment_variables->push("$env->key=$env->real_value"); $environment_variables->push("$env->key=$env->real_value");
} }
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('MARIADB_ROOT_PASSWORD'))->isEmpty()) { if ($environment_variables->filter(fn ($env) => str($env)->contains('MARIADB_ROOT_PASSWORD'))->isEmpty()) {
$environment_variables->push("MARIADB_ROOT_PASSWORD={$this->database->mariadb_root_password}"); $environment_variables->push("MARIADB_ROOT_PASSWORD={$this->database->mariadb_root_password}");
} }
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('MARIADB_DATABASE'))->isEmpty()) { if ($environment_variables->filter(fn ($env) => str($env)->contains('MARIADB_DATABASE'))->isEmpty()) {
$environment_variables->push("MARIADB_DATABASE={$this->database->mariadb_database}"); $environment_variables->push("MARIADB_DATABASE={$this->database->mariadb_database}");
} }
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('MARIADB_USER'))->isEmpty()) { if ($environment_variables->filter(fn ($env) => str($env)->contains('MARIADB_USER'))->isEmpty()) {
$environment_variables->push("MARIADB_USER={$this->database->mariadb_user}"); $environment_variables->push("MARIADB_USER={$this->database->mariadb_user}");
} }
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('MARIADB_PASSWORD'))->isEmpty()) { if ($environment_variables->filter(fn ($env) => str($env)->contains('MARIADB_PASSWORD'))->isEmpty()) {
$environment_variables->push("MARIADB_PASSWORD={$this->database->mariadb_password}"); $environment_variables->push("MARIADB_PASSWORD={$this->database->mariadb_password}");
} }

View File

@ -3,7 +3,6 @@
namespace App\Actions\Database; namespace App\Actions\Database;
use App\Models\StandaloneMongodb; use App\Models\StandaloneMongodb;
use Illuminate\Support\Str;
use Lorisleiva\Actions\Concerns\AsAction; use Lorisleiva\Actions\Concerns\AsAction;
use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Yaml;
@ -174,15 +173,15 @@ class StartMongodb
$environment_variables->push("$env->key=$env->real_value"); $environment_variables->push("$env->key=$env->real_value");
} }
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('MONGO_INITDB_ROOT_USERNAME'))->isEmpty()) { if ($environment_variables->filter(fn ($env) => str($env)->contains('MONGO_INITDB_ROOT_USERNAME'))->isEmpty()) {
$environment_variables->push("MONGO_INITDB_ROOT_USERNAME={$this->database->mongo_initdb_root_username}"); $environment_variables->push("MONGO_INITDB_ROOT_USERNAME={$this->database->mongo_initdb_root_username}");
} }
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('MONGO_INITDB_ROOT_PASSWORD'))->isEmpty()) { if ($environment_variables->filter(fn ($env) => str($env)->contains('MONGO_INITDB_ROOT_PASSWORD'))->isEmpty()) {
$environment_variables->push("MONGO_INITDB_ROOT_PASSWORD={$this->database->mongo_initdb_root_password}"); $environment_variables->push("MONGO_INITDB_ROOT_PASSWORD={$this->database->mongo_initdb_root_password}");
} }
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('MONGO_INITDB_DATABASE'))->isEmpty()) { if ($environment_variables->filter(fn ($env) => str($env)->contains('MONGO_INITDB_DATABASE'))->isEmpty()) {
$environment_variables->push("MONGO_INITDB_DATABASE={$this->database->mongo_initdb_database}"); $environment_variables->push("MONGO_INITDB_DATABASE={$this->database->mongo_initdb_database}");
} }

View File

@ -3,7 +3,6 @@
namespace App\Actions\Database; namespace App\Actions\Database;
use App\Models\StandaloneMysql; use App\Models\StandaloneMysql;
use Illuminate\Support\Str;
use Lorisleiva\Actions\Concerns\AsAction; use Lorisleiva\Actions\Concerns\AsAction;
use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Yaml;
@ -157,18 +156,18 @@ class StartMysql
$environment_variables->push("$env->key=$env->real_value"); $environment_variables->push("$env->key=$env->real_value");
} }
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('MYSQL_ROOT_PASSWORD'))->isEmpty()) { if ($environment_variables->filter(fn ($env) => str($env)->contains('MYSQL_ROOT_PASSWORD'))->isEmpty()) {
$environment_variables->push("MYSQL_ROOT_PASSWORD={$this->database->mysql_root_password}"); $environment_variables->push("MYSQL_ROOT_PASSWORD={$this->database->mysql_root_password}");
} }
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('MYSQL_DATABASE'))->isEmpty()) { if ($environment_variables->filter(fn ($env) => str($env)->contains('MYSQL_DATABASE'))->isEmpty()) {
$environment_variables->push("MYSQL_DATABASE={$this->database->mysql_database}"); $environment_variables->push("MYSQL_DATABASE={$this->database->mysql_database}");
} }
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('MYSQL_USER'))->isEmpty()) { if ($environment_variables->filter(fn ($env) => str($env)->contains('MYSQL_USER'))->isEmpty()) {
$environment_variables->push("MYSQL_USER={$this->database->mysql_user}"); $environment_variables->push("MYSQL_USER={$this->database->mysql_user}");
} }
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('MYSQL_PASSWORD'))->isEmpty()) { if ($environment_variables->filter(fn ($env) => str($env)->contains('MYSQL_PASSWORD'))->isEmpty()) {
$environment_variables->push("MYSQL_PASSWORD={$this->database->mysql_password}"); $environment_variables->push("MYSQL_PASSWORD={$this->database->mysql_password}");
} }

View File

@ -3,7 +3,6 @@
namespace App\Actions\Database; namespace App\Actions\Database;
use App\Models\StandalonePostgresql; use App\Models\StandalonePostgresql;
use Illuminate\Support\Str;
use Lorisleiva\Actions\Concerns\AsAction; use Lorisleiva\Actions\Concerns\AsAction;
use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Yaml;
@ -179,18 +178,18 @@ class StartPostgresql
$environment_variables->push("$env->key=$env->real_value"); $environment_variables->push("$env->key=$env->real_value");
} }
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('POSTGRES_USER'))->isEmpty()) { if ($environment_variables->filter(fn ($env) => str($env)->contains('POSTGRES_USER'))->isEmpty()) {
$environment_variables->push("POSTGRES_USER={$this->database->postgres_user}"); $environment_variables->push("POSTGRES_USER={$this->database->postgres_user}");
} }
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('PGUSER'))->isEmpty()) { if ($environment_variables->filter(fn ($env) => str($env)->contains('PGUSER'))->isEmpty()) {
$environment_variables->push("PGUSER={$this->database->postgres_user}"); $environment_variables->push("PGUSER={$this->database->postgres_user}");
} }
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('POSTGRES_PASSWORD'))->isEmpty()) { if ($environment_variables->filter(fn ($env) => str($env)->contains('POSTGRES_PASSWORD'))->isEmpty()) {
$environment_variables->push("POSTGRES_PASSWORD={$this->database->postgres_password}"); $environment_variables->push("POSTGRES_PASSWORD={$this->database->postgres_password}");
} }
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('POSTGRES_DB'))->isEmpty()) { if ($environment_variables->filter(fn ($env) => str($env)->contains('POSTGRES_DB'))->isEmpty()) {
$environment_variables->push("POSTGRES_DB={$this->database->postgres_db}"); $environment_variables->push("POSTGRES_DB={$this->database->postgres_db}");
} }

View File

@ -4,7 +4,6 @@ namespace App\Actions\Database;
use App\Models\StandaloneRedis; use App\Models\StandaloneRedis;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Lorisleiva\Actions\Concerns\AsAction; use Lorisleiva\Actions\Concerns\AsAction;
use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Yaml;
@ -167,7 +166,7 @@ class StartRedis
$environment_variables->push("$env->key=$env->real_value"); $environment_variables->push("$env->key=$env->real_value");
} }
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('REDIS_PASSWORD'))->isEmpty()) { if ($environment_variables->filter(fn ($env) => str($env)->contains('REDIS_PASSWORD'))->isEmpty()) {
$environment_variables->push("REDIS_PASSWORD={$this->database->redis_password}"); $environment_variables->push("REDIS_PASSWORD={$this->database->redis_password}");
} }

View File

@ -3,7 +3,6 @@
namespace App\Actions\Proxy; namespace App\Actions\Proxy;
use App\Models\Server; use App\Models\Server;
use Illuminate\Support\Str;
use Lorisleiva\Actions\Concerns\AsAction; use Lorisleiva\Actions\Concerns\AsAction;
class CheckConfiguration class CheckConfiguration
@ -24,7 +23,7 @@ class CheckConfiguration
$proxy_configuration = instant_remote_process($payload, $server, false); $proxy_configuration = instant_remote_process($payload, $server, false);
if ($reset || ! $proxy_configuration || is_null($proxy_configuration)) { if ($reset || ! $proxy_configuration || is_null($proxy_configuration)) {
$proxy_configuration = Str::of(generate_default_proxy_configuration($server))->trim()->value; $proxy_configuration = str(generate_default_proxy_configuration($server))->trim()->value;
} }
if (! $proxy_configuration || is_null($proxy_configuration)) { if (! $proxy_configuration || is_null($proxy_configuration)) {
throw new \Exception('Could not generate proxy configuration'); throw new \Exception('Could not generate proxy configuration');

View File

@ -3,7 +3,6 @@
namespace App\Actions\Proxy; namespace App\Actions\Proxy;
use App\Models\Server; use App\Models\Server;
use Illuminate\Support\Str;
use Lorisleiva\Actions\Concerns\AsAction; use Lorisleiva\Actions\Concerns\AsAction;
class SaveConfiguration class SaveConfiguration
@ -18,7 +17,7 @@ class SaveConfiguration
$proxy_path = $server->proxyPath(); $proxy_path = $server->proxyPath();
$docker_compose_yml_base64 = base64_encode($proxy_settings); $docker_compose_yml_base64 = base64_encode($proxy_settings);
$server->proxy->last_saved_settings = Str::of($docker_compose_yml_base64)->pipe('md5')->value; $server->proxy->last_saved_settings = str($docker_compose_yml_base64)->pipe('md5')->value;
$server->save(); $server->save();
return instant_remote_process([ return instant_remote_process([

View File

@ -4,7 +4,6 @@ namespace App\Actions\Proxy;
use App\Events\ProxyStarted; use App\Events\ProxyStarted;
use App\Models\Server; use App\Models\Server;
use Illuminate\Support\Str;
use Lorisleiva\Actions\Concerns\AsAction; use Lorisleiva\Actions\Concerns\AsAction;
use Spatie\Activitylog\Models\Activity; use Spatie\Activitylog\Models\Activity;
@ -27,7 +26,7 @@ class StartProxy
} }
SaveConfiguration::run($server, $configuration); SaveConfiguration::run($server, $configuration);
$docker_compose_yml_base64 = base64_encode($configuration); $docker_compose_yml_base64 = base64_encode($configuration);
$server->proxy->last_applied_settings = Str::of($docker_compose_yml_base64)->pipe('md5')->value; $server->proxy->last_applied_settings = str($docker_compose_yml_base64)->pipe('md5')->value;
$server->save(); $server->save();
if ($server->isSwarm()) { if ($server->isSwarm()) {
$commands = $commands->merge([ $commands = $commands->merge([

View File

@ -0,0 +1,19 @@
<?php
namespace App\Actions\Server;
use App\Enums\ActivityTypes;
use App\Models\Server;
use Lorisleiva\Actions\Concerns\AsAction;
class RunCommand
{
use AsAction;
public function handle(Server $server, $command)
{
$activity = remote_process(command: [$command], server: $server, ignore_errors: true, type: ActivityTypes::COMMAND->value);
return $activity;
}
}

View File

@ -25,7 +25,7 @@ class UpdateCoolify
if (! $this->server) { if (! $this->server) {
return; return;
} }
CleanupDocker::run($this->server, false); CleanupDocker::dispatch($this->server, false)->onQueue('high');
$this->latestVersion = get_latest_version_of_coolify(); $this->latestVersion = get_latest_version_of_coolify();
$this->currentVersion = config('version'); $this->currentVersion = config('version');
if (! $manual_update) { if (! $manual_update) {
@ -48,6 +48,7 @@ class UpdateCoolify
private function update() private function update()
{ {
if (isDev()) { if (isDev()) {
ray('Running in dev mode');
remote_process([ remote_process([
'sleep 10', 'sleep 10',
], $this->server); ], $this->server);

View File

@ -82,7 +82,7 @@ class WaitlistInvite extends Command
if (! $already_registered) { if (! $already_registered) {
$this->password = Str::password(); $this->password = Str::password();
User::create([ User::create([
'name' => Str::of($this->next_patient->email)->before('@'), 'name' => str($this->next_patient->email)->before('@'),
'email' => $this->next_patient->email, 'email' => $this->next_patient->email,
'password' => Hash::make($this->password), 'password' => Hash::make($this->password),
'force_password_reset' => true, 'force_password_reset' => true,

View File

@ -5,4 +5,5 @@ namespace App\Enums;
enum ActivityTypes: string enum ActivityTypes: string
{ {
case INLINE = 'inline'; case INLINE = 'inline';
case COMMAND = 'command';
} }

View File

@ -81,8 +81,8 @@ class Controller extends BaseController
$token = request()->get('token'); $token = request()->get('token');
if ($token) { if ($token) {
$decrypted = Crypt::decryptString($token); $decrypted = Crypt::decryptString($token);
$email = Str::of($decrypted)->before('@@@'); $email = str($decrypted)->before('@@@');
$password = Str::of($decrypted)->after('@@@'); $password = str($decrypted)->after('@@@');
$user = User::whereEmail($email)->first(); $user = User::whereEmail($email)->first();
if (! $user) { if (! $user) {
return redirect()->route('login'); return redirect()->route('login');

View File

@ -965,6 +965,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
$nixpacks_php_fallback_path = new EnvironmentVariable(); $nixpacks_php_fallback_path = new EnvironmentVariable();
$nixpacks_php_fallback_path->key = 'NIXPACKS_PHP_FALLBACK_PATH'; $nixpacks_php_fallback_path->key = 'NIXPACKS_PHP_FALLBACK_PATH';
$nixpacks_php_fallback_path->value = '/index.php'; $nixpacks_php_fallback_path->value = '/index.php';
$nixpacks_php_fallback_path->is_build_time = false;
$nixpacks_php_fallback_path->application_id = $this->application->id; $nixpacks_php_fallback_path->application_id = $this->application->id;
$nixpacks_php_fallback_path->save(); $nixpacks_php_fallback_path->save();
} }
@ -972,6 +973,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
$nixpacks_php_root_dir = new EnvironmentVariable(); $nixpacks_php_root_dir = new EnvironmentVariable();
$nixpacks_php_root_dir->key = 'NIXPACKS_PHP_ROOT_DIR'; $nixpacks_php_root_dir->key = 'NIXPACKS_PHP_ROOT_DIR';
$nixpacks_php_root_dir->value = '/app/public'; $nixpacks_php_root_dir->value = '/app/public';
$nixpacks_php_root_dir->is_build_time = false;
$nixpacks_php_root_dir->application_id = $this->application->id; $nixpacks_php_root_dir->application_id = $this->application->id;
$nixpacks_php_root_dir->save(); $nixpacks_php_root_dir->save();
} }
@ -1076,13 +1078,13 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
$this->application_deployment_queue->addLogEntry("Healthcheck logs: {$health_check_logs} | Return code: {$health_check_return_code}"); $this->application_deployment_queue->addLogEntry("Healthcheck logs: {$health_check_logs} | Return code: {$health_check_return_code}");
} }
if (Str::of($this->saved_outputs->get('health_check'))->replace('"', '')->value() === 'healthy') { if (str($this->saved_outputs->get('health_check'))->replace('"', '')->value() === 'healthy') {
$this->newVersionIsHealthy = true; $this->newVersionIsHealthy = true;
$this->application->update(['status' => 'running']); $this->application->update(['status' => 'running']);
$this->application_deployment_queue->addLogEntry('New container is healthy.'); $this->application_deployment_queue->addLogEntry('New container is healthy.');
break; break;
} }
if (Str::of($this->saved_outputs->get('health_check'))->replace('"', '')->value() === 'unhealthy') { if (str($this->saved_outputs->get('health_check'))->replace('"', '')->value() === 'unhealthy') {
$this->newVersionIsHealthy = false; $this->newVersionIsHealthy = false;
$this->query_logs(); $this->query_logs();
break; break;
@ -1094,7 +1096,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
$sleeptime++; $sleeptime++;
} }
} }
if (Str::of($this->saved_outputs->get('health_check'))->replace('"', '')->value() === 'starting') { if (str($this->saved_outputs->get('health_check'))->replace('"', '')->value() === 'starting') {
$this->query_logs(); $this->query_logs();
} }
} }
@ -1535,7 +1537,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
$this->execute_remote_command([ $this->execute_remote_command([
executeInDocker($this->deployment_uuid, "cat {$this->workdir}{$this->dockerfile_location}"), 'hidden' => true, 'save' => 'dockerfile_from_repo', 'ignore_errors' => true, executeInDocker($this->deployment_uuid, "cat {$this->workdir}{$this->dockerfile_location}"), 'hidden' => true, 'save' => 'dockerfile_from_repo', 'ignore_errors' => true,
]); ]);
$dockerfile = collect(Str::of($this->saved_outputs->get('dockerfile_from_repo'))->trim()->explode("\n")); $dockerfile = collect(str($this->saved_outputs->get('dockerfile_from_repo'))->trim()->explode("\n"));
$this->application->parseHealthcheckFromDockerfile($dockerfile); $this->application->parseHealthcheckFromDockerfile($dockerfile);
} }
$docker_compose = [ $docker_compose = [
@ -2107,7 +2109,7 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
$this->execute_remote_command([ $this->execute_remote_command([
executeInDocker($this->deployment_uuid, "cat {$this->workdir}{$this->dockerfile_location}"), 'hidden' => true, 'save' => 'dockerfile', executeInDocker($this->deployment_uuid, "cat {$this->workdir}{$this->dockerfile_location}"), 'hidden' => true, 'save' => 'dockerfile',
]); ]);
$dockerfile = collect(Str::of($this->saved_outputs->get('dockerfile'))->trim()->explode("\n")); $dockerfile = collect(str($this->saved_outputs->get('dockerfile'))->trim()->explode("\n"));
if ($this->pull_request_id === 0) { if ($this->pull_request_id === 0) {
foreach ($this->application->build_environment_variables as $env) { foreach ($this->application->build_environment_variables as $env) {
if (data_get($env, 'is_multiline') === true) { if (data_get($env, 'is_multiline') === true) {

View File

@ -20,9 +20,9 @@ class CoolifyTask implements ShouldBeEncrypted, ShouldQueue
*/ */
public function __construct( public function __construct(
public Activity $activity, public Activity $activity,
public bool $ignore_errors = false, public bool $ignore_errors,
public $call_event_on_finish = null, public $call_event_on_finish,
public $call_event_data = null public $call_event_data,
) {} ) {}
/** /**

View File

@ -98,7 +98,7 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue
return; return;
} }
$status = Str::of(data_get($this->database, 'status')); $status = str(data_get($this->database, 'status'));
if (! $status->startsWith('running') && $this->database->id !== 0) { if (! $status->startsWith('running') && $this->database->id !== 0) {
ray('database not running'); ray('database not running');
@ -236,7 +236,7 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue
return; return;
} }
} }
$this->backup_dir = backup_dir().'/databases/'.Str::of($this->team->name)->slug().'-'.$this->team->id.'/'.$this->directory_name; $this->backup_dir = backup_dir().'/databases/'.str($this->team->name)->slug().'-'.$this->team->id.'/'.$this->directory_name;
if ($this->database->name === 'coolify-db') { if ($this->database->name === 'coolify-db') {
$databasesToBackup = ['coolify']; $databasesToBackup = ['coolify'];

View File

@ -5,7 +5,6 @@ namespace App\Livewire\Project\Application;
use App\Models\Application; use App\Models\Application;
use App\Models\LocalFileVolume; use App\Models\LocalFileVolume;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Livewire\Component; use Livewire\Component;
use Visus\Cuid2\Cuid2; use Visus\Cuid2\Cuid2;
@ -199,8 +198,8 @@ class General extends Component
return str($volume)->startsWith('/data/coolify'); return str($volume)->startsWith('/data/coolify');
})->unique()->values(); })->unique()->values();
foreach ($volumes as $volume) { foreach ($volumes as $volume) {
$source = Str::of($volume)->before(':'); $source = str($volume)->before(':');
$target = Str::of($volume)->after(':')->beforeLast(':'); $target = str($volume)->after(':')->beforeLast(':');
LocalFileVolume::updateOrCreate( LocalFileVolume::updateOrCreate(
[ [

View File

@ -3,7 +3,6 @@
namespace App\Livewire\Project\Application\Preview; namespace App\Livewire\Project\Application\Preview;
use App\Models\Application; use App\Models\Application;
use Illuminate\Support\Str;
use Livewire\Component; use Livewire\Component;
use Spatie\Url\Url; use Spatie\Url\Url;
@ -32,10 +31,10 @@ class Form extends Component
public function generate_real_url() public function generate_real_url()
{ {
if (data_get($this->application, 'fqdn')) { if (data_get($this->application, 'fqdn')) {
$firstFqdn = Str::of($this->application->fqdn)->before(','); $firstFqdn = str($this->application->fqdn)->before(',');
$url = Url::fromString($firstFqdn); $url = Url::fromString($firstFqdn);
$host = $url->getHost(); $host = $url->getHost();
$this->preview_url_template = Str::of($this->application->preview_url_template)->replace('{{domain}}', $host); $this->preview_url_template = str($this->application->preview_url_template)->replace('{{domain}}', $host);
} }
} }

View File

@ -3,7 +3,6 @@
namespace App\Livewire\Project\Application; namespace App\Livewire\Project\Application;
use App\Models\Application; use App\Models\Application;
use Illuminate\Support\Str;
use Livewire\Component; use Livewire\Component;
use Visus\Cuid2\Cuid2; use Visus\Cuid2\Cuid2;
@ -50,16 +49,16 @@ class Rollback extends Component
$output = instant_remote_process([ $output = instant_remote_process([
"docker inspect --format='{{.Config.Image}}' {$this->application->uuid}", "docker inspect --format='{{.Config.Image}}' {$this->application->uuid}",
], $this->application->destination->server, throwError: false); ], $this->application->destination->server, throwError: false);
$current_tag = Str::of($output)->trim()->explode(':'); $current_tag = str($output)->trim()->explode(':');
$this->current = data_get($current_tag, 1); $this->current = data_get($current_tag, 1);
$output = instant_remote_process([ $output = instant_remote_process([
"docker images --format '{{.Repository}}#{{.Tag}}#{{.CreatedAt}}'", "docker images --format '{{.Repository}}#{{.Tag}}#{{.CreatedAt}}'",
], $this->application->destination->server); ], $this->application->destination->server);
$this->images = Str::of($output)->trim()->explode("\n")->filter(function ($item) use ($image) { $this->images = str($output)->trim()->explode("\n")->filter(function ($item) use ($image) {
return Str::of($item)->contains($image); return str($item)->contains($image);
})->map(function ($item) { })->map(function ($item) {
$item = Str::of($item)->explode('#'); $item = str($item)->explode('#');
if ($item[1] === $this->current) { if ($item[1] === $this->current) {
// $is_current = true; // $is_current = true;
} }

View File

@ -6,7 +6,6 @@ use App\Models\Application;
use App\Models\Project; use App\Models\Project;
use App\Models\StandaloneDocker; use App\Models\StandaloneDocker;
use App\Models\SwarmDocker; use App\Models\SwarmDocker;
use Illuminate\Support\Str;
use Livewire\Component; use Livewire\Component;
use Visus\Cuid2\Cuid2; use Visus\Cuid2\Cuid2;
@ -29,9 +28,9 @@ class DockerImage extends Component
$this->validate([ $this->validate([
'dockerImage' => 'required', 'dockerImage' => 'required',
]); ]);
$image = Str::of($this->dockerImage)->before(':'); $image = str($this->dockerImage)->before(':');
if (Str::of($this->dockerImage)->contains(':')) { if (str($this->dockerImage)->contains(':')) {
$tag = Str::of($this->dockerImage)->after(':'); $tag = str($this->dockerImage)->after(':');
} else { } else {
$tag = 'latest'; $tag = 'latest';
} }

View File

@ -193,7 +193,7 @@ class GithubPrivateRepositoryDeployKey extends Component
return; return;
} }
if (Str::of($this->repository_url)->startsWith('http')) { if (str($this->repository_url)->startsWith('http')) {
$this->git_host = $this->repository_url_parsed->getHost(); $this->git_host = $this->repository_url_parsed->getHost();
$this->git_repository = $this->repository_url_parsed->getSegment(1).'/'.$this->repository_url_parsed->getSegment(2); $this->git_repository = $this->repository_url_parsed->getSegment(1).'/'.$this->repository_url_parsed->getSegment(2);
$this->git_repository = Str::finish("git@$this->git_host:$this->git_repository", '.git'); $this->git_repository = Str::finish("git@$this->git_host:$this->git_repository", '.git');

View File

@ -11,7 +11,7 @@ class EditCompose extends Component
public $serviceId; public $serviceId;
protected $listeners = ['refreshEnvs' => 'mount']; protected $listeners = ['refreshEnvs', 'envsUpdated'];
protected $rules = [ protected $rules = [
'service.docker_compose_raw' => 'required', 'service.docker_compose_raw' => 'required',
@ -19,6 +19,17 @@ class EditCompose extends Component
'service.is_container_label_escape_enabled' => 'required', 'service.is_container_label_escape_enabled' => 'required',
]; ];
public function envsUpdated()
{
$this->dispatch('saveCompose', $this->service->docker_compose_raw);
$this->refreshEnvs();
}
public function refreshEnvs()
{
$this->service = Service::find($this->serviceId);
}
public function mount() public function mount()
{ {
$this->service = Service::find($this->serviceId); $this->service = Service::find($this->serviceId);

View File

@ -14,7 +14,6 @@ use App\Models\StandaloneMongodb;
use App\Models\StandaloneMysql; use App\Models\StandaloneMysql;
use App\Models\StandalonePostgresql; use App\Models\StandalonePostgresql;
use App\Models\StandaloneRedis; use App\Models\StandaloneRedis;
use Illuminate\Support\Str;
use Livewire\Component; use Livewire\Component;
class FileStorage extends Component class FileStorage extends Component
@ -37,9 +36,9 @@ class FileStorage extends Component
public function mount() public function mount()
{ {
$this->resource = $this->fileStorage->service; $this->resource = $this->fileStorage->service;
if (Str::of($this->fileStorage->fs_path)->startsWith('.')) { if (str($this->fileStorage->fs_path)->startsWith('.')) {
$this->workdir = $this->resource->service?->workdir(); $this->workdir = $this->resource->service?->workdir();
$this->fs_path = Str::of($this->fileStorage->fs_path)->after('.'); $this->fs_path = str($this->fileStorage->fs_path)->after('.');
} else { } else {
$this->workdir = null; $this->workdir = null;
$this->fs_path = $this->fileStorage->fs_path; $this->fs_path = $this->fileStorage->fs_path;

View File

@ -112,7 +112,7 @@ class Show extends Component
$this->serialize(); $this->serialize();
$this->env->save(); $this->env->save();
$this->dispatch('success', 'Environment variable updated.'); $this->dispatch('success', 'Environment variable updated.');
$this->dispatch('refreshEnvs'); $this->dispatch('envsUpdated');
} catch (\Exception $e) { } catch (\Exception $e) {
return handleError($e); return handleError($e);
} }

View File

@ -2,6 +2,7 @@
namespace App\Livewire; namespace App\Livewire;
use App\Actions\Server\RunCommand as ServerRunCommand;
use App\Models\Server; use App\Models\Server;
use Livewire\Component; use Livewire\Component;
@ -33,7 +34,7 @@ class RunCommand extends Component
{ {
$this->validate(); $this->validate();
try { try {
$activity = remote_process([$this->command], Server::where('uuid', $this->server)->first(), ignore_errors: true); $activity = ServerRunCommand::run(server: Server::where('uuid', $this->server)->first(), command: $this->command);
$this->dispatch('activityMonitor', $activity->id); $this->dispatch('activityMonitor', $activity->id);
} catch (\Throwable $e) { } catch (\Throwable $e) {
return handleError($e, $this); return handleError($e, $this);

View File

@ -6,7 +6,6 @@ use App\Actions\Proxy\CheckConfiguration;
use App\Actions\Proxy\SaveConfiguration; use App\Actions\Proxy\SaveConfiguration;
use App\Actions\Proxy\StartProxy; use App\Actions\Proxy\StartProxy;
use App\Models\Server; use App\Models\Server;
use Illuminate\Support\Str;
use Livewire\Component; use Livewire\Component;
class Proxy extends Component class Proxy extends Component
@ -79,7 +78,7 @@ class Proxy extends Component
{ {
try { try {
$this->proxy_settings = CheckConfiguration::run($this->server); $this->proxy_settings = CheckConfiguration::run($this->server);
if (Str::of($this->proxy_settings)->contains('--api.dashboard=true') && Str::of($this->proxy_settings)->contains('--api.insecure=true')) { if (str($this->proxy_settings)->contains('--api.dashboard=true') && str($this->proxy_settings)->contains('--api.insecure=true')) {
$this->dispatch('traefikDashboardAvailable', true); $this->dispatch('traefikDashboardAvailable', true);
} else { } else {
$this->dispatch('traefikDashboardAvailable', false); $this->dispatch('traefikDashboardAvailable', false);

View File

@ -52,7 +52,7 @@ class InviteLink extends Component
if (is_null($user)) { if (is_null($user)) {
$password = Str::password(); $password = Str::password();
$user = User::create([ $user = User::create([
'name' => Str::of($this->email)->before('@'), 'name' => str($this->email)->before('@'),
'email' => $this->email, 'email' => $this->email,
'password' => Hash::make($password), 'password' => Hash::make($password),
'force_password_reset' => true, 'force_password_reset' => true,

View File

@ -28,11 +28,11 @@ class Application extends BaseModel
} }
$application->forceFill([ $application->forceFill([
'fqdn' => $application->fqdn, 'fqdn' => $application->fqdn,
'install_command' => Str::of($application->install_command)->trim(), 'install_command' => str($application->install_command)->trim(),
'build_command' => Str::of($application->build_command)->trim(), 'build_command' => str($application->build_command)->trim(),
'start_command' => Str::of($application->start_command)->trim(), 'start_command' => str($application->start_command)->trim(),
'base_directory' => Str::of($application->base_directory)->trim(), 'base_directory' => str($application->base_directory)->trim(),
'publish_directory' => Str::of($application->publish_directory)->trim(), 'publish_directory' => str($application->publish_directory)->trim(),
]); ]);
}); });
static::created(function ($application) { static::created(function ($application) {
@ -902,9 +902,9 @@ class Application extends BaseModel
$type = null; $type = null;
$source = null; $source = null;
if (is_string($volume)) { if (is_string($volume)) {
$source = Str::of($volume)->before(':'); $source = str($volume)->before(':');
if ($source->startsWith('./') || $source->startsWith('/') || $source->startsWith('~')) { if ($source->startsWith('./') || $source->startsWith('/') || $source->startsWith('~')) {
$type = Str::of('bind'); $type = str('bind');
} }
} elseif (is_array($volume)) { } elseif (is_array($volume)) {
$type = data_get_str($volume, 'type'); $type = data_get_str($volume, 'type');

View File

@ -174,7 +174,7 @@ class EnvironmentVariable extends Model
if (str($environment_variable)->startsWith('{{'.$type) && str($environment_variable)->endsWith('}}')) { if (str($environment_variable)->startsWith('{{'.$type) && str($environment_variable)->endsWith('}}')) {
$variable = Str::after($environment_variable, "{$type}."); $variable = Str::after($environment_variable, "{$type}.");
$variable = Str::before($variable, '}}'); $variable = Str::before($variable, '}}');
$variable = Str::of($variable)->trim()->value; $variable = str($variable)->trim()->value;
if (! collect(SHARED_VARIABLE_TYPES)->contains($type)) { if (! collect(SHARED_VARIABLE_TYPES)->contains($type)) {
return $variable; return $variable;
} }
@ -220,7 +220,7 @@ class EnvironmentVariable extends Model
protected function key(): Attribute protected function key(): Attribute
{ {
return Attribute::make( return Attribute::make(
set: fn (string $value) => Str::of($value)->trim(), set: fn (string $value) => str($value)->trim(),
); );
} }
} }

View File

@ -4,7 +4,6 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
class LocalPersistentVolume extends Model class LocalPersistentVolume extends Model
{ {
@ -33,14 +32,14 @@ class LocalPersistentVolume extends Model
protected function name(): Attribute protected function name(): Attribute
{ {
return Attribute::make( return Attribute::make(
set: fn (string $value) => Str::of($value)->trim()->value, set: fn (string $value) => str($value)->trim()->value,
); );
} }
protected function mountPath(): Attribute protected function mountPath(): Attribute
{ {
return Attribute::make( return Attribute::make(
set: fn (string $value) => Str::of($value)->trim()->start('/')->value set: fn (string $value) => str($value)->trim()->start('/')->value
); );
} }
@ -49,7 +48,7 @@ class LocalPersistentVolume extends Model
return Attribute::make( return Attribute::make(
set: function (?string $value) { set: function (?string $value) {
if ($value) { if ($value) {
return Str::of($value)->trim()->start('/')->value; return str($value)->trim()->start('/')->value;
} else { } else {
return $value; return $value;
} }

View File

@ -11,7 +11,6 @@ use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Process; use Illuminate\Support\Facades\Process;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Illuminate\Support\Stringable; use Illuminate\Support\Stringable;
use Spatie\SchemalessAttributes\Casts\SchemalessAttributes; use Spatie\SchemalessAttributes\Casts\SchemalessAttributes;
use Spatie\SchemalessAttributes\SchemalessAttributesTrait; use Spatie\SchemalessAttributes\SchemalessAttributesTrait;
@ -29,10 +28,10 @@ class Server extends BaseModel
static::saving(function ($server) { static::saving(function ($server) {
$payload = []; $payload = [];
if ($server->user) { if ($server->user) {
$payload['user'] = Str::of($server->user)->trim(); $payload['user'] = str($server->user)->trim();
} }
if ($server->ip) { if ($server->ip) {
$payload['ip'] = Str::of($server->ip)->trim(); $payload['ip'] = str($server->ip)->trim();
} }
$server->forceFill($payload); $server->forceFill($payload);
}); });
@ -875,7 +874,7 @@ $schema://$host {
$releaseLines = collect(explode("\n", $os_release)); $releaseLines = collect(explode("\n", $os_release));
$collectedData = collect([]); $collectedData = collect([]);
foreach ($releaseLines as $line) { foreach ($releaseLines as $line) {
$item = Str::of($line)->trim(); $item = str($line)->trim();
$collectedData->put($item->before('=')->value(), $item->after('=')->lower()->replace('"', '')->value()); $collectedData->put($item->before('=')->value(), $item->after('=')->lower()->replace('"', '')->value());
} }
$ID = data_get($collectedData, 'ID'); $ID = data_get($collectedData, 'ID');

View File

@ -839,33 +839,13 @@ class Service extends BaseModel
$commands[] = "cd $workdir"; $commands[] = "cd $workdir";
$json = Yaml::parse($this->docker_compose); $json = Yaml::parse($this->docker_compose);
$envs_from_coolify = $this->environment_variables()->get();
// foreach ($json['services'] as $service => $config) {
// if (data_get($config, 'environment') === null) {
// data_set($json, "services.$service.environment", []);
// $envs = collect([]);
// } else {
// $envs = collect($config['environment']);
// }
// // $envs->put('COOLIFY_CONTAINER_NAME', "$service-{$this->uuid}");
// foreach ($envs_from_coolify as $env) {
// $envs = $envs->map(function ($value) use ($env) {
// if (str($value)->startsWith($env->key)) {
// return "{$env->key}={$env->real_value}";
// }
// return $value;
// });
// }
// $envs = $envs->unique();
// data_set($json, "services.$service.environment", $envs->toArray());
// }
$this->docker_compose = Yaml::dump($json, 10, 2, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK); $this->docker_compose = Yaml::dump($json, 10, 2, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK);
$docker_compose_base64 = base64_encode($this->docker_compose); $docker_compose_base64 = base64_encode($this->docker_compose);
$commands[] = "echo $docker_compose_base64 | base64 -d | tee docker-compose.yml > /dev/null"; $commands[] = "echo $docker_compose_base64 | base64 -d | tee docker-compose.yml > /dev/null";
$commands[] = 'rm -f .env || true'; $commands[] = 'rm -f .env || true';
$envs_from_coolify = $this->environment_variables()->get();
foreach ($envs_from_coolify as $env) { foreach ($envs_from_coolify as $env) {
$commands[] = "echo '{$env->key}={$env->real_value}' >> .env"; $commands[] = "echo '{$env->key}={$env->real_value}' >> .env";
} }
@ -884,7 +864,6 @@ class Service extends BaseModel
{ {
$networks = getTopLevelNetworks($this); $networks = getTopLevelNetworks($this);
// ray($networks);
return $networks; return $networks;
} }
} }

View File

@ -8,7 +8,6 @@ use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification; use Illuminate\Notifications\Notification;
use Illuminate\Support\Str;
class DeploymentFailed extends Notification implements ShouldQueue class DeploymentFailed extends Notification implements ShouldQueue
{ {
@ -41,8 +40,8 @@ class DeploymentFailed extends Notification implements ShouldQueue
$this->project_uuid = data_get($application, 'environment.project.uuid'); $this->project_uuid = data_get($application, 'environment.project.uuid');
$this->environment_name = data_get($application, 'environment.name'); $this->environment_name = data_get($application, 'environment.name');
$this->fqdn = data_get($application, 'fqdn'); $this->fqdn = data_get($application, 'fqdn');
if (Str::of($this->fqdn)->explode(',')->count() > 1) { if (str($this->fqdn)->explode(',')->count() > 1) {
$this->fqdn = Str::of($this->fqdn)->explode(',')->first(); $this->fqdn = str($this->fqdn)->explode(',')->first();
} }
$this->deployment_url = base_url()."/project/{$this->project_uuid}/".urlencode($this->environment_name)."/application/{$this->application->uuid}/deployment/{$this->deployment_uuid}"; $this->deployment_url = base_url()."/project/{$this->project_uuid}/".urlencode($this->environment_name)."/application/{$this->application->uuid}/deployment/{$this->deployment_uuid}";
} }

View File

@ -8,7 +8,6 @@ use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification; use Illuminate\Notifications\Notification;
use Illuminate\Support\Str;
class DeploymentSuccess extends Notification implements ShouldQueue class DeploymentSuccess extends Notification implements ShouldQueue
{ {
@ -41,8 +40,8 @@ class DeploymentSuccess extends Notification implements ShouldQueue
$this->project_uuid = data_get($application, 'environment.project.uuid'); $this->project_uuid = data_get($application, 'environment.project.uuid');
$this->environment_name = data_get($application, 'environment.name'); $this->environment_name = data_get($application, 'environment.name');
$this->fqdn = data_get($application, 'fqdn'); $this->fqdn = data_get($application, 'fqdn');
if (Str::of($this->fqdn)->explode(',')->count() > 1) { if (str($this->fqdn)->explode(',')->count() > 1) {
$this->fqdn = Str::of($this->fqdn)->explode(',')->first(); $this->fqdn = str($this->fqdn)->explode(',')->first();
} }
$this->deployment_url = base_url()."/project/{$this->project_uuid}/".urlencode($this->environment_name)."/application/{$this->application->uuid}/deployment/{$this->deployment_uuid}"; $this->deployment_url = base_url()."/project/{$this->project_uuid}/".urlencode($this->environment_name)."/application/{$this->application->uuid}/deployment/{$this->deployment_uuid}";
} }

View File

@ -7,7 +7,6 @@ use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification; use Illuminate\Notifications\Notification;
use Illuminate\Support\Str;
class StatusChanged extends Notification implements ShouldQueue class StatusChanged extends Notification implements ShouldQueue
{ {
@ -31,8 +30,8 @@ class StatusChanged extends Notification implements ShouldQueue
$this->project_uuid = data_get($resource, 'environment.project.uuid'); $this->project_uuid = data_get($resource, 'environment.project.uuid');
$this->environment_name = data_get($resource, 'environment.name'); $this->environment_name = data_get($resource, 'environment.name');
$this->fqdn = data_get($resource, 'fqdn', null); $this->fqdn = data_get($resource, 'fqdn', null);
if (Str::of($this->fqdn)->explode(',')->count() > 1) { if (str($this->fqdn)->explode(',')->count() > 1) {
$this->fqdn = Str::of($this->fqdn)->explode(',')->first(); $this->fqdn = str($this->fqdn)->explode(',')->first();
} }
$this->resource_url = base_url()."/project/{$this->project_uuid}/".urlencode($this->environment_name)."/application/{$this->resource->uuid}"; $this->resource_url = base_url()."/project/{$this->project_uuid}/".urlencode($this->environment_name)."/application/{$this->resource->uuid}";
} }

View File

@ -7,7 +7,6 @@ use App\Models\Server;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Process; use Illuminate\Support\Facades\Process;
use Illuminate\Support\Str;
trait ExecuteRemoteCommand trait ExecuteRemoteCommand
{ {
@ -45,7 +44,7 @@ trait ExecuteRemoteCommand
} }
$remote_command = generateSshCommand($this->server, $command); $remote_command = generateSshCommand($this->server, $command);
$process = Process::timeout(3600)->idleTimeout(3600)->start($remote_command, function (string $type, string $output) use ($command, $hidden, $customType, $append) { $process = Process::timeout(3600)->idleTimeout(3600)->start($remote_command, function (string $type, string $output) use ($command, $hidden, $customType, $append) {
$output = Str::of($output)->trim(); $output = str($output)->trim();
if ($output->startsWith('╔')) { if ($output->startsWith('╔')) {
$output = "\n".$output; $output = "\n".$output;
} }

View File

@ -6,7 +6,6 @@ use App\Models\Service;
use Closure; use Closure;
use Illuminate\Contracts\View\View; use Illuminate\Contracts\View\View;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Illuminate\View\Component; use Illuminate\View\Component;
class Links extends Component class Links extends Component
@ -26,16 +25,16 @@ class Links extends Component
$this->links = $this->links->merge($links); $this->links = $this->links->merge($links);
} else { } else {
if ($application->fqdn) { if ($application->fqdn) {
$fqdns = collect(Str::of($application->fqdn)->explode(',')); $fqdns = collect(str($application->fqdn)->explode(','));
$fqdns->map(function ($fqdn) { $fqdns->map(function ($fqdn) {
$this->links->push(getFqdnWithoutPort($fqdn)); $this->links->push(getFqdnWithoutPort($fqdn));
}); });
} }
if ($application->ports) { if ($application->ports) {
$portsCollection = collect(Str::of($application->ports)->explode(',')); $portsCollection = collect(str($application->ports)->explode(','));
$portsCollection->map(function ($port) { $portsCollection->map(function ($port) {
if (Str::of($port)->contains(':')) { if (str($port)->contains(':')) {
$hostPort = Str::of($port)->before(':'); $hostPort = str($port)->before(':');
} else { } else {
$hostPort = $port; $hostPort = $port;
} }

View File

@ -91,7 +91,7 @@ function format_docker_envs_to_json($rawOutput)
} }
function checkMinimumDockerEngineVersion($dockerVersion) function checkMinimumDockerEngineVersion($dockerVersion)
{ {
$majorDockerVersion = Str::of($dockerVersion)->before('.')->value(); $majorDockerVersion = str($dockerVersion)->before('.')->value();
if ($majorDockerVersion <= 22) { if ($majorDockerVersion <= 22) {
$dockerVersion = null; $dockerVersion = null;
} }
@ -152,7 +152,7 @@ function get_port_from_dockerfile($dockerfile): ?int
$dockerfile_array = explode("\n", $dockerfile); $dockerfile_array = explode("\n", $dockerfile);
$found_exposed_port = null; $found_exposed_port = null;
foreach ($dockerfile_array as $line) { foreach ($dockerfile_array as $line) {
$line_str = Str::of($line)->trim(); $line_str = str($line)->trim();
if ($line_str->startsWith('EXPOSE')) { if ($line_str->startsWith('EXPOSE')) {
$found_exposed_port = $line_str->replace('EXPOSE', '')->trim(); $found_exposed_port = $line_str->replace('EXPOSE', '')->trim();
break; break;
@ -534,7 +534,7 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview
$labels = collect([]); $labels = collect([]);
if ($pull_request_id === 0) { if ($pull_request_id === 0) {
if ($application->fqdn) { if ($application->fqdn) {
$domains = Str::of(data_get($application, 'fqdn'))->explode(','); $domains = str(data_get($application, 'fqdn'))->explode(',');
$labels = $labels->merge(fqdnLabelsForTraefik( $labels = $labels->merge(fqdnLabelsForTraefik(
uuid: $appUuid, uuid: $appUuid,
domains: $domains, domains: $domains,
@ -558,7 +558,7 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview
} }
} else { } else {
if (data_get($preview, 'fqdn')) { if (data_get($preview, 'fqdn')) {
$domains = Str::of(data_get($preview, 'fqdn'))->explode(','); $domains = str(data_get($preview, 'fqdn'))->explode(',');
} else { } else {
$domains = collect([]); $domains = collect([]);
} }

View File

@ -85,7 +85,7 @@ function githubApi(GithubApp|GitlabApp|null $source, string $endpoint, string $m
function get_installation_path(GithubApp $source) function get_installation_path(GithubApp $source)
{ {
$github = GithubApp::where('uuid', $source->uuid)->first(); $github = GithubApp::where('uuid', $source->uuid)->first();
$name = Str::of(Str::kebab($github->name)); $name = str(Str::kebab($github->name));
$installation_path = $github->html_url === 'https://github.com' ? 'apps' : 'github-apps'; $installation_path = $github->html_url === 'https://github.com' ? 'apps' : 'github-apps';
return "$github->html_url/$installation_path/$name/installations/new"; return "$github->html_url/$installation_path/$name/installations/new";
@ -93,7 +93,7 @@ function get_installation_path(GithubApp $source)
function get_permissions_path(GithubApp $source) function get_permissions_path(GithubApp $source)
{ {
$github = GithubApp::where('uuid', $source->uuid)->first(); $github = GithubApp::where('uuid', $source->uuid)->first();
$name = Str::of(Str::kebab($github->name)); $name = str(Str::kebab($github->name));
return "$github->html_url/settings/apps/$name/permissions"; return "$github->html_url/settings/apps/$name/permissions";
} }

View File

@ -4,7 +4,6 @@ use App\Models\Application;
use App\Models\EnvironmentVariable; use App\Models\EnvironmentVariable;
use App\Models\ServiceApplication; use App\Models\ServiceApplication;
use App\Models\ServiceDatabase; use App\Models\ServiceDatabase;
use Illuminate\Support\Str;
use Spatie\Url\Url; use Spatie\Url\Url;
use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Yaml;
@ -38,7 +37,7 @@ function getFilesystemVolumesFromServer(ServiceApplication|ServiceDatabase|Appli
]); ]);
instant_remote_process($commands, $server); instant_remote_process($commands, $server);
foreach ($fileVolumes as $fileVolume) { foreach ($fileVolumes as $fileVolume) {
$path = Str::of(data_get($fileVolume, 'fs_path')); $path = str(data_get($fileVolume, 'fs_path'));
$content = data_get($fileVolume, 'content'); $content = data_get($fileVolume, 'content');
if ($path->startsWith('.')) { if ($path->startsWith('.')) {
$path = $path->after('.'); $path = $path->after('.');
@ -68,7 +67,7 @@ function getFilesystemVolumesFromServer(ServiceApplication|ServiceDatabase|Appli
$fileVolume->is_directory = false; $fileVolume->is_directory = false;
$fileVolume->save(); $fileVolume->save();
$content = base64_encode($content); $content = base64_encode($content);
$dir = Str::of($fileLocation)->dirname(); $dir = str($fileLocation)->dirname();
instant_remote_process([ instant_remote_process([
"mkdir -p $dir", "mkdir -p $dir",
"echo '$content' | base64 -d | tee $fileLocation", "echo '$content' | base64 -d | tee $fileLocation",
@ -106,7 +105,7 @@ function updateCompose(ServiceApplication|ServiceDatabase $resource)
$resourceFqdns = str($resource->fqdn)->explode(','); $resourceFqdns = str($resource->fqdn)->explode(',');
if ($resourceFqdns->count() === 1) { if ($resourceFqdns->count() === 1) {
$resourceFqdns = $resourceFqdns->first(); $resourceFqdns = $resourceFqdns->first();
$variableName = 'SERVICE_FQDN_'.Str::of($resource->name)->upper()->replace('-', ''); $variableName = 'SERVICE_FQDN_'.str($resource->name)->upper()->replace('-', '');
$generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first(); $generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first();
$fqdn = Url::fromString($resourceFqdns); $fqdn = Url::fromString($resourceFqdns);
$port = $fqdn->getPort(); $port = $fqdn->getPort();
@ -125,14 +124,14 @@ function updateCompose(ServiceApplication|ServiceDatabase $resource)
$generatedEnv->save(); $generatedEnv->save();
} }
} }
$variableName = 'SERVICE_URL_'.Str::of($resource->name)->upper()->replace('-', ''); $variableName = 'SERVICE_URL_'.str($resource->name)->upper()->replace('-', '');
$generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first(); $generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first();
$url = Url::fromString($fqdn); $url = Url::fromString($fqdn);
$port = $url->getPort(); $port = $url->getPort();
$path = $url->getPath(); $path = $url->getPath();
$url = $url->getHost(); $url = $url->getHost();
if ($generatedEnv) { if ($generatedEnv) {
$url = Str::of($fqdn)->after('://'); $url = str($fqdn)->after('://');
$generatedEnv->value = $url.$path; $generatedEnv->value = $url.$path;
$generatedEnv->save(); $generatedEnv->save();
} }
@ -175,7 +174,7 @@ function updateCompose(ServiceApplication|ServiceDatabase $resource)
$port_env_url->save(); $port_env_url->save();
} }
} else { } else {
$variableName = 'SERVICE_FQDN_'.Str::of($resource->name)->upper()->replace('-', ''); $variableName = 'SERVICE_FQDN_'.str($resource->name)->upper()->replace('-', '');
$generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first(); $generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first();
$fqdn = Url::fromString($fqdn); $fqdn = Url::fromString($fqdn);
$fqdn = $fqdn->getScheme().'://'.$fqdn->getHost().$fqdn->getPath(); $fqdn = $fqdn->getScheme().'://'.$fqdn->getHost().$fqdn->getPath();
@ -183,12 +182,12 @@ function updateCompose(ServiceApplication|ServiceDatabase $resource)
$generatedEnv->value = $fqdn; $generatedEnv->value = $fqdn;
$generatedEnv->save(); $generatedEnv->save();
} }
$variableName = 'SERVICE_URL_'.Str::of($resource->name)->upper()->replace('-', ''); $variableName = 'SERVICE_URL_'.str($resource->name)->upper()->replace('-', '');
$generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first(); $generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first();
$url = Url::fromString($fqdn); $url = Url::fromString($fqdn);
$url = $url->getHost().$url->getPath(); $url = $url->getHost().$url->getPath();
if ($generatedEnv) { if ($generatedEnv) {
$url = Str::of($fqdn)->after('://'); $url = str($fqdn)->after('://');
$generatedEnv->value = $url; $generatedEnv->value = $url;
$generatedEnv->save(); $generatedEnv->save();
} }

View File

@ -469,7 +469,7 @@ function data_get_str($data, $key, $default = null): Stringable
{ {
$str = data_get($data, $key, $default) ?? $default; $str = data_get($data, $key, $default) ?? $default;
return Str::of($str); return str($str);
} }
function generateFqdn(Server $server, string $random) function generateFqdn(Server $server, string $random)
@ -933,12 +933,12 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
$content = null; $content = null;
$isDirectory = false; $isDirectory = false;
if (is_string($volume)) { if (is_string($volume)) {
$source = Str::of($volume)->before(':'); $source = str($volume)->before(':');
$target = Str::of($volume)->after(':')->beforeLast(':'); $target = str($volume)->after(':')->beforeLast(':');
if ($source->startsWith('./') || $source->startsWith('/') || $source->startsWith('~')) { if ($source->startsWith('./') || $source->startsWith('/') || $source->startsWith('~')) {
$type = Str::of('bind'); $type = str('bind');
} else { } else {
$type = Str::of('volume'); $type = str('volume');
} }
} elseif (is_array($volume)) { } elseif (is_array($volume)) {
$type = data_get_str($volume, 'type'); $type = data_get_str($volume, 'type');
@ -987,8 +987,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
$slugWithoutUuid = Str::slug($source, '-'); $slugWithoutUuid = Str::slug($source, '-');
$name = "{$savedService->service->uuid}_{$slugWithoutUuid}"; $name = "{$savedService->service->uuid}_{$slugWithoutUuid}";
if (is_string($volume)) { if (is_string($volume)) {
$source = Str::of($volume)->before(':'); $source = str($volume)->before(':');
$target = Str::of($volume)->after(':')->beforeLast(':'); $target = str($volume)->after(':')->beforeLast(':');
$source = $name; $source = $name;
$volume = "$source:$target"; $volume = "$source:$target";
} elseif (is_array($volume)) { } elseif (is_array($volume)) {
@ -1032,7 +1032,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
// Get variables from the service // Get variables from the service
foreach ($serviceVariables as $variableName => $variable) { foreach ($serviceVariables as $variableName => $variable) {
if (is_numeric($variableName)) { if (is_numeric($variableName)) {
$variable = Str::of($variable); $variable = str($variable);
if ($variable->contains('=')) { if ($variable->contains('=')) {
// - SESSION_SECRET=123 // - SESSION_SECRET=123
// - SESSION_SECRET= // - SESSION_SECRET=
@ -1046,8 +1046,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
} else { } else {
// SESSION_SECRET: 123 // SESSION_SECRET: 123
// SESSION_SECRET: // SESSION_SECRET:
$key = Str::of($variableName); $key = str($variableName);
$value = Str::of($variable); $value = str($variable);
} }
if ($key->startsWith('SERVICE_FQDN')) { if ($key->startsWith('SERVICE_FQDN')) {
if ($isNew || $savedService->fqdn === null) { if ($isNew || $savedService->fqdn === null) {
@ -1137,7 +1137,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
'key' => $key, 'key' => $key,
'service_id' => $resource->id, 'service_id' => $resource->id,
])->first(); ])->first();
$value = Str::of(replaceVariables($value)); $value = str(replaceVariables($value));
$key = $value; $key = $value;
if ($value->startsWith('SERVICE_')) { if ($value->startsWith('SERVICE_')) {
$foundEnv = EnvironmentVariable::where([ $foundEnv = EnvironmentVariable::where([
@ -1170,7 +1170,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
// } // }
} else { } else {
if ($command->value() === 'URL') { if ($command->value() === 'URL') {
$fqdn = Str::of($fqdn)->after('://')->value(); $fqdn = str($fqdn)->after('://')->value();
} }
EnvironmentVariable::create([ EnvironmentVariable::create([
'key' => $key, 'key' => $key,
@ -1254,18 +1254,6 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
]); ]);
} }
} }
$envs_from_coolify = $resource->environment_variables()->get();
$serviceVariables = $serviceVariables->map(function ($variable) use ($envs_from_coolify) {
$env_variable_key = str($variable)->before('=');
$env_variable_value = str($variable)->after('=');
$found_env = $envs_from_coolify->where('key', $env_variable_key)->first();
if ($found_env) {
$env_variable_value = $found_env->value;
}
return "$env_variable_key=$env_variable_value";
});
} }
// Add labels to the service // Add labels to the service
if ($savedService->serviceType()) { if ($savedService->serviceType()) {
@ -1333,6 +1321,41 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
data_set($service, 'environment', $serviceVariables->toArray()); data_set($service, 'environment', $serviceVariables->toArray());
updateCompose($savedService); updateCompose($savedService);
return $service;
});
$envs_from_coolify = $resource->environment_variables()->get();
$services = collect($services)->map(function ($service, $serviceName) use ($resource, $envs_from_coolify) {
$serviceVariables = collect(data_get($service, 'environment', []));
$parsedServiceVariables = collect([]);
foreach ($serviceVariables as $key => $value) {
if (is_numeric($key)) {
$value = str($value);
if ($value->contains('=')) {
$key = $value->before('=')->value();
$value = $value->after('=')->value();
} else {
$key = $value->value();
$value = null;
}
$parsedServiceVariables->put($key, $value);
} else {
$parsedServiceVariables->put($key, $value);
}
}
$parsedServiceVariables->put('COOLIFY_CONTAINER_NAME', "$serviceName-{$resource->uuid}");
$parsedServiceVariables = $parsedServiceVariables->map(function ($value, $key) use ($envs_from_coolify) {
$found_env = $envs_from_coolify->where('key', $key)->first();
if ($found_env) {
return $found_env->value;
}
return $value;
});
data_set($service, 'environment', $parsedServiceVariables->toArray());
return $service; return $service;
}); });
$finalServices = [ $finalServices = [
@ -1637,7 +1660,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
// Get variables from the service // Get variables from the service
foreach ($serviceVariables as $variableName => $variable) { foreach ($serviceVariables as $variableName => $variable) {
if (is_numeric($variableName)) { if (is_numeric($variableName)) {
$variable = Str::of($variable); $variable = str($variable);
if ($variable->contains('=')) { if ($variable->contains('=')) {
// - SESSION_SECRET=123 // - SESSION_SECRET=123
// - SESSION_SECRET= // - SESSION_SECRET=
@ -1651,8 +1674,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
} else { } else {
// SESSION_SECRET: 123 // SESSION_SECRET: 123
// SESSION_SECRET: // SESSION_SECRET:
$key = Str::of($variableName); $key = str($variableName);
$value = Str::of($variable); $value = str($variable);
} }
if ($key->startsWith('SERVICE_FQDN')) { if ($key->startsWith('SERVICE_FQDN')) {
if ($isNew) { if ($isNew) {
@ -1696,7 +1719,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
'application_id' => $resource->id, 'application_id' => $resource->id,
'is_preview' => false, 'is_preview' => false,
])->first(); ])->first();
$value = Str::of(replaceVariables($value)); $value = str(replaceVariables($value));
$key = $value; $key = $value;
if ($value->startsWith('SERVICE_')) { if ($value->startsWith('SERVICE_')) {
$foundEnv = EnvironmentVariable::where([ $foundEnv = EnvironmentVariable::where([
@ -1718,7 +1741,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
$fqdn = data_get($foundEnv, 'value'); $fqdn = data_get($foundEnv, 'value');
} else { } else {
if ($command?->value() === 'URL') { if ($command?->value() === 'URL') {
$fqdn = Str::of($fqdn)->after('://')->value(); $fqdn = str($fqdn)->after('://')->value();
} }
EnvironmentVariable::create([ EnvironmentVariable::create([
'key' => $key, 'key' => $key,

View File

@ -7,7 +7,7 @@ return [
// The release version of your application // The release version of your application
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD')) // Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
'release' => '4.0.0-beta.304', 'release' => '4.0.0-beta.305',
// When left empty or `null` the Laravel environment will be used // When left empty or `null` the Laravel environment will be used
'environment' => config('app.env'), 'environment' => config('app.env'),

View File

@ -1,3 +1,3 @@
<?php <?php
return '4.0.0-beta.304'; return '4.0.0-beta.305';

View File

@ -68,9 +68,9 @@
@foreach (data_get($application, 'previews') as $previewName => $preview) @foreach (data_get($application, 'previews') as $previewName => $preview)
<div class="flex flex-col w-full p-4 border dark:border-coolgray-200"> <div class="flex flex-col w-full p-4 border dark:border-coolgray-200">
<div class="flex gap-2">PR #{{ data_get($preview, 'pull_request_id') }} | <div class="flex gap-2">PR #{{ data_get($preview, 'pull_request_id') }} |
@if (Str::of(data_get($preview, 'status'))->startsWith('running')) @if (str(data_get($preview, 'status'))->startsWith('running'))
<x-status.running :status="data_get($preview, 'status')" /> <x-status.running :status="data_get($preview, 'status')" />
@elseif(Str::of(data_get($preview, 'status'))->startsWith('restarting')) @elseif(str(data_get($preview, 'status'))->startsWith('restarting'))
<x-status.restarting :status="data_get($preview, 'status')" /> <x-status.restarting :status="data_get($preview, 'status')" />
@else @else
<x-status.stopped :status="data_get($preview, 'status')" /> <x-status.stopped :status="data_get($preview, 'status')" />

View File

@ -27,7 +27,8 @@
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
<div class="flex gap-2"> <div class="flex gap-2">
<x-forms.input placeholder="coollabsio/coolify-example" id="application.git_repository" label="Repository" /> <x-forms.input placeholder="coollabsio/coolify-example" id="application.git_repository"
label="Repository" />
<x-forms.input placeholder="main" id="application.git_branch" label="Branch" /> <x-forms.input placeholder="main" id="application.git_branch" label="Branch" />
</div> </div>
<div class="flex items-end gap-2"> <div class="flex items-end gap-2">
@ -42,7 +43,7 @@
</div> </div>
<h4 class="py-2 ">Select another Private Key</h4> <h4 class="py-2 ">Select another Private Key</h4>
<div class="flex gap-2"> <div class="flex flex-wrap gap-2">
@foreach ($private_keys as $key) @foreach ($private_keys as $key)
<x-forms.button wire:click.defer="setPrivateKey('{{ $key->id }}')">{{ $key->name }} <x-forms.button wire:click.defer="setPrivateKey('{{ $key->id }}')">{{ $key->name }}
</x-forms.button> </x-forms.button>

View File

@ -4,7 +4,7 @@
<x-forms.button type="submit"> <x-forms.button type="submit">
Save Save
</x-forms.button> </x-forms.button>
@if (Str::of($status)->startsWith('running')) @if (str($status)->startsWith('running'))
<livewire:project.database.backup-now :backup="$backup" /> <livewire:project.database.backup-now :backup="$backup" />
@endif @endif
@if ($backup->database_id !== 0) @if ($backup->database_id !== 0)

View File

@ -54,11 +54,11 @@
<div class="grid grid-cols-1 gap-2 pt-4 xl:grid-cols-1"> <div class="grid grid-cols-1 gap-2 pt-4 xl:grid-cols-1">
@foreach ($applications as $application) @foreach ($applications as $application)
<div @class([ <div @class([
'border-l border-dashed border-red-500 ' => Str::of( 'border-l border-dashed border-red-500 ' => str(
$application->status)->contains(['exited']), $application->status)->contains(['exited']),
'border-l border-dashed border-success' => Str::of( 'border-l border-dashed border-success' => str(
$application->status)->contains(['running']), $application->status)->contains(['running']),
'border-l border-dashed border-warning' => Str::of( 'border-l border-dashed border-warning' => str(
$application->status)->contains(['starting']), $application->status)->contains(['starting']),
'flex gap-2 box-without-bg-without-border dark:bg-coolgray-100 bg-white dark:hover:text-neutral-300 group', 'flex gap-2 box-without-bg-without-border dark:bg-coolgray-100 bg-white dark:hover:text-neutral-300 group',
])> ])>
@ -123,12 +123,12 @@
@endforeach @endforeach
@foreach ($databases as $database) @foreach ($databases as $database)
<div @class([ <div @class([
'border-l border-dashed border-red-500' => Str::of( 'border-l border-dashed border-red-500' => str($database->status)->contains(
$database->status)->contains(['exited']), ['exited']),
'border-l border-dashed border-success' => Str::of( 'border-l border-dashed border-success' => str($database->status)->contains(
$database->status)->contains(['running']), ['running']),
'border-l border-dashed border-warning' => Str::of( 'border-l border-dashed border-warning' => str($database->status)->contains(
$database->status)->contains(['restarting']), ['restarting']),
'flex gap-2 box-without-bg-without-border dark:bg-coolgray-100 bg-white dark:hover:text-neutral-300 group', 'flex gap-2 box-without-bg-without-border dark:bg-coolgray-100 bg-white dark:hover:text-neutral-300 group',
])> ])>
<div class="flex flex-row w-full"> <div class="flex flex-row w-full">

View File

@ -2,7 +2,7 @@
<div> <div>
<div class="flex gap-2"> <div class="flex gap-2">
<h2>Service Stack</h2> <h2>Service Stack</h2>
<x-forms.button type="submit">Save</x-forms.button> <x-forms.button wire:target='submit' type="submit">Save</x-forms.button>
<x-modal-input buttonTitle="Edit Compose File" title="Edit Docker Compose" :closeOutside="false"> <x-modal-input buttonTitle="Edit Compose File" title="Edit Docker Compose" :closeOutside="false">
<livewire:project.service.edit-compose serviceId="{{ $service->id }}" /> <livewire:project.service.edit-compose serviceId="{{ $service->id }}" />
</x-modal-input> </x-modal-input>

View File

@ -58,25 +58,26 @@
<div class="relative w-auto pb-8"> <div class="relative w-auto pb-8">
<p>Are you sure you would like to upgrade your instance to {{ $latestVersion }}?</p> <p>Are you sure you would like to upgrade your instance to {{ $latestVersion }}?</p>
<br /> <br />
<p>You can review the changelogs <a class="font-bold underline" <p>You can review the changelogs <a class="font-bold underline dark:text-white"
href="https://github.com/coollabsio/coolify/releases" target="_blank">here</a>.</p> href="https://github.com/coollabsio/coolify/releases" target="_blank">here</a>.</p>
<br /> <br />
<p>If something goes wrong and you cannot upgrade your instance, You can check the following <p>If something goes wrong and you cannot upgrade your instance, You can check the following
<a class="font-bold underline" href="https://coolify.io/docs/upgrade" <a class="font-bold underline dark:text-white" href="https://coolify.io/docs/upgrade"
target="_blank">guide</a> on what to do. target="_blank">guide</a> on what to do.
</p> </p>
@if ($showProgress) @if ($showProgress)
<div class="flex flex-col pt-4"> <div class="flex flex-col pt-4">
<h4>Progress <x-loading /></h4> <h2>Progress <x-loading /></h2>
<div x-html="currentStatus"></div> <div x-html="currentStatus"></div>
</div> </div>
@endif @endif
</div> </div>
<div class="flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2"> <div class="flex gap-4">
@if (!$showProgress) @if (!$showProgress)
<x-forms.button @click="modalOpen=false" <x-forms.button @click="modalOpen=false"
class="w-24 dark:bg-coolgray-200 dark:hover:bg-coolgray-300">Cancel class="w-24 dark:bg-coolgray-200 dark:hover:bg-coolgray-300">Cancel
</x-forms.button> </x-forms.button>
<div class="flex-1"></div>
<x-forms.button @click="confirmed" class="w-24" isHighlighted type="button">Continue <x-forms.button @click="confirmed" class="w-24" isHighlighted type="button">Continue
</x-forms.button> </x-forms.button>
@endif @endif
@ -98,6 +99,10 @@
this.$wire.$call('upgrade') this.$wire.$call('upgrade')
this.upgrade(); this.upgrade();
this.$wire.showProgress = true; this.$wire.showProgress = true;
window.addEventListener('beforeunload', (event) => {
event.preventDefault();
event.returnValue = '';
});
}, },
revive() { revive() {
if (checkHealthInterval) return true; if (checkHealthInterval) return true;

View File

@ -1,7 +1,7 @@
{ {
"coolify": { "coolify": {
"v4": { "v4": {
"version": "4.0.0-beta.304" "version": "4.0.0-beta.305"
} }
} }
} }