testing php storm code cleanup and styling

This commit is contained in:
Andras Bacsai 2023-08-08 11:51:36 +02:00
parent a8ee779b31
commit f2228cec7b
368 changed files with 23834 additions and 2623 deletions

View File

@ -15,6 +15,7 @@ class PrepareCoolifyTask
{ {
protected Activity $activity; protected Activity $activity;
protected CoolifyTaskArgs $remoteProcessArgs; protected CoolifyTaskArgs $remoteProcessArgs;
public function __construct(CoolifyTaskArgs $remoteProcessArgs) public function __construct(CoolifyTaskArgs $remoteProcessArgs)
{ {
$this->remoteProcessArgs = $remoteProcessArgs; $this->remoteProcessArgs = $remoteProcessArgs;

View File

@ -49,6 +49,28 @@ public function __construct(Activity $activity, bool $hide_from_output = false,
$this->ignore_errors = $ignore_errors; $this->ignore_errors = $ignore_errors;
} }
public static function decodeOutput(?Activity $activity = null): string
{
if (is_null($activity)) {
return '';
}
try {
$decoded = json_decode(
data_get($activity, 'description'),
associative: true,
flags: JSON_THROW_ON_ERROR
);
} catch (\JsonException $exception) {
return '';
}
return collect($decoded)
->sortBy(fn($i) => $i['order'])
->map(fn($i) => $i['output'])
->implode("");
}
public function __invoke(): ProcessResult public function __invoke(): ProcessResult
{ {
$this->time_start = hrtime(true); $this->time_start = hrtime(true);
@ -83,15 +105,6 @@ public function __invoke(): ProcessResult
return $processResult; return $processResult;
} }
protected function getLatestCounter(): int
{
$description = json_decode($this->activity->description, associative: true, flags: JSON_THROW_ON_ERROR);
if ($description === null || count($description) === 0) {
return 1;
}
return end($description)['order'] + 1;
}
protected function getCommand(): string protected function getCommand(): string
{ {
$user = $this->activity->getExtraProperty('user'); $user = $this->activity->getExtraProperty('user');
@ -120,6 +133,13 @@ protected function handleOutput(string $type, string $output)
} }
} }
protected function elapsedTime(): int
{
$timeMs = (hrtime(true) - $this->time_start) / 1_000_000;
return intval($timeMs);
}
public function encodeOutput($type, $output) public function encodeOutput($type, $output)
{ {
$outputStack = json_decode($this->activity->description, associative: true, flags: JSON_THROW_ON_ERROR); $outputStack = json_decode($this->activity->description, associative: true, flags: JSON_THROW_ON_ERROR);
@ -135,26 +155,13 @@ public function encodeOutput($type, $output)
return json_encode($outputStack, flags: JSON_THROW_ON_ERROR); return json_encode($outputStack, flags: JSON_THROW_ON_ERROR);
} }
public static function decodeOutput(?Activity $activity = null): string protected function getLatestCounter(): int
{ {
if (is_null($activity)) { $description = json_decode($this->activity->description, associative: true, flags: JSON_THROW_ON_ERROR);
return ''; if ($description === null || count($description) === 0) {
return 1;
} }
return end($description)['order'] + 1;
try {
$decoded = json_decode(
data_get($activity, 'description'),
associative: true,
flags: JSON_THROW_ON_ERROR
);
} catch (\JsonException $exception) {
return '';
}
return collect($decoded)
->sortBy(fn ($i) => $i['order'])
->map(fn ($i) => $i['output'])
->implode("");
} }
/** /**
@ -171,11 +178,4 @@ protected function isAfterLastThrottle()
return ($this->current_time - $this->throttle_interval_ms) > $this->last_write_at; return ($this->current_time - $this->throttle_interval_ms) > $this->last_write_at;
} }
protected function elapsedTime(): int
{
$timeMs = (hrtime(true) - $this->time_start) / 1_000_000;
return intval($timeMs);
}
} }

View File

@ -3,15 +3,14 @@
namespace App\Actions\Database; namespace App\Actions\Database;
use App\Models\Server; use App\Models\Server;
use App\Models\StandaloneDocker;
use App\Models\Team;
use App\Models\StandalonePostgresql; use App\Models\StandalonePostgresql;
use Symfony\Component\Yaml\Yaml;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Symfony\Component\Yaml\Yaml;
class StartPostgresql class StartPostgresql
{ {
public $database; public $database;
public function __invoke(Server $server, StandalonePostgresql $database) public function __invoke(Server $server, StandalonePostgresql $database)
{ {
$this->database = $database; $this->database = $database;
@ -83,28 +82,7 @@ public function __invoke(Server $server, StandalonePostgresql $database)
], $server); ], $server);
return $activity; return $activity;
} }
private function generate_environment_variables()
{
$environment_variables = collect();
ray('Generate Environment Variables')->green();
ray($this->database->runtime_environment_variables)->green();
foreach ($this->database->runtime_environment_variables as $env) {
$environment_variables->push("$env->key=$env->value");
}
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('POSTGRES_USER'))->isEmpty()) {
$environment_variables->push("POSTGRES_USER={$this->database->postgres_user}");
}
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('POSTGRES_PASSWORD'))->isEmpty()) {
$environment_variables->push("POSTGRES_PASSWORD={$this->database->postgres_password}");
}
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('POSTGRES_DB'))->isEmpty()) {
$environment_variables->push("POSTGRES_DB={$this->database->postgres_db}");
}
return $environment_variables->all();
}
private function generate_local_persistent_volumes() private function generate_local_persistent_volumes()
{ {
$local_persistent_volumes = []; $local_persistent_volumes = [];
@ -114,6 +92,7 @@ private function generate_local_persistent_volumes()
} }
return $local_persistent_volumes; return $local_persistent_volumes;
} }
private function generate_local_persistent_volumes_only_volume_names() private function generate_local_persistent_volumes_only_volume_names()
{ {
$local_persistent_volumes_names = []; $local_persistent_volumes_names = [];
@ -129,4 +108,27 @@ private function generate_local_persistent_volumes_only_volume_names()
} }
return $local_persistent_volumes_names; return $local_persistent_volumes_names;
} }
private function generate_environment_variables()
{
$environment_variables = collect();
ray('Generate Environment Variables')->green();
ray($this->database->runtime_environment_variables)->green();
foreach ($this->database->runtime_environment_variables as $env) {
$environment_variables->push("$env->key=$env->value");
}
if ($environment_variables->filter(fn($env) => Str::of($env)->contains('POSTGRES_USER'))->isEmpty()) {
$environment_variables->push("POSTGRES_USER={$this->database->postgres_user}");
}
if ($environment_variables->filter(fn($env) => Str::of($env)->contains('POSTGRES_PASSWORD'))->isEmpty()) {
$environment_variables->push("POSTGRES_PASSWORD={$this->database->postgres_password}");
}
if ($environment_variables->filter(fn($env) => Str::of($env)->contains('POSTGRES_DB'))->isEmpty()) {
$environment_variables->push("POSTGRES_DB={$this->database->postgres_db}");
}
return $environment_variables->all();
}
} }

View File

@ -3,11 +3,8 @@
namespace App\Actions\Fortify; namespace App\Actions\Fortify;
use App\Models\InstanceSettings; use App\Models\InstanceSettings;
use App\Models\Team;
use App\Models\User; use App\Models\User;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule; use Illuminate\Validation\Rule;
use Laravel\Fortify\Contracts\CreatesNewUsers; use Laravel\Fortify\Contracts\CreatesNewUsers;
@ -19,7 +16,7 @@ class CreateNewUser implements CreatesNewUsers
/** /**
* Validate and create a newly registered user. * Validate and create a newly registered user.
* *
* @param array<string, string> $input * @param array<string, string> $input
*/ */
public function create(array $input): User public function create(array $input): User
{ {

View File

@ -14,7 +14,7 @@ class ResetUserPassword implements ResetsUserPasswords
/** /**
* Validate and reset the user's forgotten password. * Validate and reset the user's forgotten password.
* *
* @param array<string, string> $input * @param array<string, string> $input
*/ */
public function reset(User $user, array $input): void public function reset(User $user, array $input): void
{ {

View File

@ -14,7 +14,7 @@ class UpdateUserPassword implements UpdatesUserPasswords
/** /**
* Validate and update the user's password. * Validate and update the user's password.
* *
* @param array<string, string> $input * @param array<string, string> $input
*/ */
public function update(User $user, array $input): void public function update(User $user, array $input): void
{ {

View File

@ -13,7 +13,7 @@ class UpdateUserProfileInformation implements UpdatesUserProfileInformation
/** /**
* Validate and update the given user's profile information. * Validate and update the given user's profile information.
* *
* @param array<string, string> $input * @param array<string, string> $input
*/ */
public function update(User $user, array $input): void public function update(User $user, array $input): void
{ {
@ -43,7 +43,7 @@ public function update(User $user, array $input): void
/** /**
* Update the given verified user's profile information. * Update the given verified user's profile information.
* *
* @param array<string, string> $input * @param array<string, string> $input
*/ */
protected function updateVerifiedUser(User $user, array $input): void protected function updateVerifiedUser(User $user, array $input): void
{ {

View File

@ -2,8 +2,6 @@
namespace App\Actions\Proxy; namespace App\Actions\Proxy;
use App\Actions\Proxy\SaveConfigurationSync;
use App\Enums\ProxyTypes;
use App\Models\Server; use App\Models\Server;
use Illuminate\Support\Str; use Illuminate\Support\Str;
@ -25,4 +23,4 @@ public function __invoke(Server $server, bool $reset = false)
return $proxy_configuration; return $proxy_configuration;
} }
} }

View File

@ -2,12 +2,11 @@
namespace App\Actions\Proxy; namespace App\Actions\Proxy;
use App\Actions\Proxy\CheckConfigurationSync;
use App\Enums\ProxyStatus; use App\Enums\ProxyStatus;
use App\Enums\ProxyTypes; use App\Enums\ProxyTypes;
use App\Models\Server; use App\Models\Server;
use Spatie\Activitylog\Models\Activity;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Spatie\Activitylog\Models\Activity;
class StartProxy class StartProxy
{ {
@ -54,4 +53,4 @@ public function __invoke(Server $server): Activity
return $activity; return $activity;
} }
} }

View File

@ -23,7 +23,7 @@ public function __invoke(bool $force)
$this->server = Server::where('name', $localhost_name)->firstOrFail(); $this->server = Server::where('name', $localhost_name)->firstOrFail();
$this->latest_version = get_latest_version_of_coolify(); $this->latest_version = get_latest_version_of_coolify();
$this->current_version = config('version'); $this->current_version = config('version');
ray('latest version:' . $this->latest_version . " current version: " . $this->current_version . ' force: ' . $force); ray('latest version:' . $this->latest_version . " current version: " . $this->current_version . ' force: ' . $force);
if ($settings->next_channel) { if ($settings->next_channel) {
ray('next channel enabled'); ray('next channel enabled');
$this->latest_version = 'next'; $this->latest_version = 'next';
@ -49,6 +49,7 @@ public function __invoke(bool $force)
return; return;
} }
} }
private function update() private function update()
{ {
if (isDev()) { if (isDev()) {

View File

@ -10,10 +10,12 @@ class Init extends Command
{ {
protected $signature = 'app:init'; protected $signature = 'app:init';
protected $description = 'Cleanup instance related stuffs'; protected $description = 'Cleanup instance related stuffs';
public function handle() public function handle()
{ {
$this->cleanup_in_progress_application_deployments(); $this->cleanup_in_progress_application_deployments();
} }
private function cleanup_in_progress_application_deployments() private function cleanup_in_progress_application_deployments()
{ {
// Cleanup any failed deployments // Cleanup any failed deployments

View File

@ -64,7 +64,8 @@ private function showHelp()
</ul> </ul>
</div> </div>
</div> </div>
HTML); HTML
);
ask(<<<'HTML' ask(<<<'HTML'
<div class="mr-1"> <div class="mr-1">

View File

@ -4,8 +4,8 @@
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Illuminate\Http\Client\PendingRequest; use Illuminate\Http\Client\PendingRequest;
use Illuminate\Support\Facades\Http;
use Illuminate\Http\Client\Pool; use Illuminate\Http\Client\Pool;
use Illuminate\Support\Facades\Http;
class SyncBunny extends Command class SyncBunny extends Command
{ {
@ -64,7 +64,7 @@ public function handle()
]); ]);
}); });
try { try {
Http::pool(fn (Pool $pool) => [ Http::pool(fn(Pool $pool) => [
$pool->storage(file: "$parent_dir/$compose_file")->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$compose_file"), $pool->storage(file: "$parent_dir/$compose_file")->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$compose_file"),
$pool->storage(file: "$parent_dir/$compose_file_prod")->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$compose_file_prod"), $pool->storage(file: "$parent_dir/$compose_file_prod")->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$compose_file_prod"),
$pool->storage(file: "$parent_dir/$production_env")->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$production_env"), $pool->storage(file: "$parent_dir/$production_env")->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$production_env"),
@ -73,7 +73,7 @@ public function handle()
$pool->storage(file: "$parent_dir/$versions")->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$versions"), $pool->storage(file: "$parent_dir/$versions")->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$versions"),
]); ]);
ray("{$bunny_cdn}/{$bunny_cdn_path}"); ray("{$bunny_cdn}/{$bunny_cdn_path}");
Http::pool(fn (Pool $pool) => [ Http::pool(fn(Pool $pool) => [
$pool->purge("$bunny_cdn/$bunny_cdn_path/$compose_file"), $pool->purge("$bunny_cdn/$bunny_cdn_path/$compose_file"),
$pool->purge("$bunny_cdn/$bunny_cdn_path/$compose_file_prod"), $pool->purge("$bunny_cdn/$bunny_cdn_path/$compose_file_prod"),
$pool->purge("$bunny_cdn/$bunny_cdn_path/$production_env"), $pool->purge("$bunny_cdn/$bunny_cdn_path/$production_env"),

View File

@ -2,12 +2,12 @@
namespace App\Console; namespace App\Console;
use App\Jobs\InstanceApplicationsStatusJob;
use App\Jobs\CheckResaleLicenseJob; use App\Jobs\CheckResaleLicenseJob;
use App\Jobs\CheckResaleLicenseKeys;
use App\Jobs\DockerCleanupJob;
use App\Jobs\InstanceApplicationsStatusJob;
use App\Jobs\InstanceAutoUpdateJob; use App\Jobs\InstanceAutoUpdateJob;
use App\Jobs\ProxyCheckJob; use App\Jobs\ProxyCheckJob;
use App\Jobs\DockerCleanupJob;
use App\Jobs\CheckResaleLicenseKeys;
use Illuminate\Console\Scheduling\Schedule; use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel; use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
@ -31,6 +31,7 @@ protected function schedule(Schedule $schedule): void
$schedule->job(new InstanceAutoUpdateJob)->everyTenMinutes(); $schedule->job(new InstanceAutoUpdateJob)->everyTenMinutes();
} }
} }
protected function commands(): void protected function commands(): void
{ {
$this->load(__DIR__ . '/Commands'); $this->load(__DIR__ . '/Commands');

View File

@ -22,6 +22,7 @@ public function __construct(
public ?Model $model = null, public ?Model $model = null,
public string $status = ProcessStatus::QUEUED->value, public string $status = ProcessStatus::QUEUED->value,
public bool $ignore_errors = false, public bool $ignore_errors = false,
) { )
{
} }
} }

View File

@ -9,8 +9,9 @@
class ServerMetadata extends Data class ServerMetadata extends Data
{ {
public function __construct( public function __construct(
public ?ProxyTypes $type, public ?ProxyTypes $type,
public ?ProxyStatus $status public ?ProxyStatus $status
) { )
{
} }
} }

View File

@ -8,6 +8,7 @@ enum ProxyTypes: string
case NGINX = 'NGINX'; case NGINX = 'NGINX';
case CADDY = 'CADDY'; case CADDY = 'CADDY';
} }
enum ProxyStatus: string enum ProxyStatus: string
{ {
case EXITED = 'exited'; case EXITED = 'exited';

View File

@ -4,13 +4,12 @@
use App\Models\InstanceSettings; use App\Models\InstanceSettings;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Throwable;
use Sentry\Laravel\Integration; use Sentry\Laravel\Integration;
use Throwable;
class Handler extends ExceptionHandler class Handler extends ExceptionHandler
{ {
private InstanceSettings $settings;
/** /**
* A list of exception types with their corresponding custom log levels. * A list of exception types with their corresponding custom log levels.
* *
@ -19,7 +18,6 @@ class Handler extends ExceptionHandler
protected $levels = [ protected $levels = [
// //
]; ];
/** /**
* A list of the exception types that are not reported. * A list of the exception types that are not reported.
* *
@ -28,7 +26,6 @@ class Handler extends ExceptionHandler
protected $dontReport = [ protected $dontReport = [
// //
]; ];
/** /**
* A list of the inputs that are never flashed to the session on validation exceptions. * A list of the inputs that are never flashed to the session on validation exceptions.
* *
@ -39,6 +36,7 @@ class Handler extends ExceptionHandler
'password', 'password',
'password_confirmation', 'password_confirmation',
]; ];
private InstanceSettings $settings;
/** /**
* Register the exception handling callbacks for the application. * Register the exception handling callbacks for the application.

View File

@ -5,12 +5,11 @@
use App\Models\ApplicationDeploymentQueue; use App\Models\ApplicationDeploymentQueue;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Http\Request;
use Spatie\Activitylog\Models\Activity;
class ApplicationController extends Controller class ApplicationController extends Controller
{ {
use AuthorizesRequests, ValidatesRequests; use AuthorizesRequests, ValidatesRequests;
public function configuration() public function configuration()
{ {
$project = session('currentTeam')->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first(); $project = session('currentTeam')->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
@ -28,6 +27,7 @@ public function configuration()
ray($application->persistentStorages()->get()); ray($application->persistentStorages()->get());
return view('project.application.configuration', ['application' => $application]); return view('project.application.configuration', ['application' => $application]);
} }
public function deployments() public function deployments()
{ {
$project = session('currentTeam')->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first(); $project = session('currentTeam')->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();

View File

@ -2,17 +2,15 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Http\Livewire\Team\Invitations;
use App\Models\InstanceSettings; use App\Models\InstanceSettings;
use App\Models\Project; use App\Models\Project;
use App\Models\S3Storage;
use App\Models\Server; use App\Models\Server;
use App\Models\TeamInvitation; use App\Models\TeamInvitation;
use App\Models\User; use App\Models\User;
use App\Models\S3Storage;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController; use Illuminate\Routing\Controller as BaseController;
use Illuminate\Support\Facades\DB;
class Controller extends BaseController class Controller extends BaseController
{ {
@ -27,6 +25,7 @@ public function subscription()
'settings' => InstanceSettings::get() 'settings' => InstanceSettings::get()
]); ]);
} }
public function license() public function license()
{ {
if (!isCloud()) { if (!isCloud()) {
@ -36,6 +35,7 @@ public function license()
'settings' => InstanceSettings::get() 'settings' => InstanceSettings::get()
]); ]);
} }
public function dashboard() public function dashboard()
{ {
$projects = Project::ownedByCurrentTeam()->get(); $projects = Project::ownedByCurrentTeam()->get();
@ -55,6 +55,7 @@ public function dashboard()
's3s' => $s3s, 's3s' => $s3s,
]); ]);
} }
public function settings() public function settings()
{ {
if (auth()->user()->isInstanceAdmin()) { if (auth()->user()->isInstanceAdmin()) {
@ -66,6 +67,7 @@ public function settings()
return redirect()->route('dashboard'); return redirect()->route('dashboard');
} }
} }
public function emails() public function emails()
{ {
if (auth()->user()->isInstanceAdmin()) { if (auth()->user()->isInstanceAdmin()) {
@ -77,6 +79,7 @@ public function emails()
return redirect()->route('dashboard'); return redirect()->route('dashboard');
} }
} }
public function team() public function team()
{ {
$invitations = []; $invitations = [];
@ -87,18 +90,23 @@ public function team()
'invitations' => $invitations, 'invitations' => $invitations,
]); ]);
} }
public function storages() {
public function storages()
{
$s3 = S3Storage::ownedByCurrentTeam()->get(); $s3 = S3Storage::ownedByCurrentTeam()->get();
return view('team.storages.all', [ return view('team.storages.all', [
's3' => $s3, 's3' => $s3,
]); ]);
} }
public function storages_show() {
public function storages_show()
{
$storage = S3Storage::ownedByCurrentTeam()->whereUuid(request()->storage_uuid)->firstOrFail(); $storage = S3Storage::ownedByCurrentTeam()->whereUuid(request()->storage_uuid)->firstOrFail();
return view('team.storages.show', [ return view('team.storages.show', [
'storage' => $storage, 'storage' => $storage,
]); ]);
} }
public function members() public function members()
{ {
$invitations = []; $invitations = [];
@ -109,6 +117,7 @@ public function members()
'invitations' => $invitations, 'invitations' => $invitations,
]); ]);
} }
public function acceptInvitation() public function acceptInvitation()
{ {
try { try {
@ -135,6 +144,7 @@ public function acceptInvitation()
throw $th; throw $th;
} }
} }
public function revokeInvitation() public function revokeInvitation()
{ {
try { try {
@ -152,4 +162,4 @@ public function revokeInvitation()
throw $th; throw $th;
} }
} }
} }

View File

@ -2,15 +2,13 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Models\ApplicationDeploymentQueue;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Http\Request;
use Spatie\Activitylog\Models\Activity;
class DatabaseController extends Controller class DatabaseController extends Controller
{ {
use AuthorizesRequests, ValidatesRequests; use AuthorizesRequests, ValidatesRequests;
public function configuration() public function configuration()
{ {
$project = session('currentTeam')->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first(); $project = session('currentTeam')->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();

View File

@ -2,7 +2,6 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Http\Livewire\Server\PrivateKey;
use App\Models\Environment; use App\Models\Environment;
use App\Models\Project; use App\Models\Project;
use App\Models\Server; use App\Models\Server;
@ -16,24 +15,28 @@ public function servers()
'servers' => Server::isUsable()->get() 'servers' => Server::isUsable()->get()
]); ]);
} }
public function destinations() public function destinations()
{ {
return response()->json([ return response()->json([
'destinations' => Server::destinationsByServer(request()->query('server_id'))->sortBy('name') 'destinations' => Server::destinationsByServer(request()->query('server_id'))->sortBy('name')
]); ]);
} }
public function projects() public function projects()
{ {
return response()->json([ return response()->json([
'projects' => Project::ownedByCurrentTeam()->get() 'projects' => Project::ownedByCurrentTeam()->get()
]); ]);
} }
public function environments() public function environments()
{ {
return response()->json([ return response()->json([
'environments' => Project::ownedByCurrentTeam()->whereUuid(request()->query('project_uuid'))->first()->environments 'environments' => Project::ownedByCurrentTeam()->whereUuid(request()->query('project_uuid'))->first()->environments
]); ]);
} }
public function newProject() public function newProject()
{ {
$project = Project::firstOrCreate( $project = Project::firstOrCreate(
@ -44,6 +47,7 @@ public function newProject()
'project_uuid' => $project->uuid 'project_uuid' => $project->uuid
]); ]);
} }
public function newEnvironment() public function newEnvironment()
{ {
$environment = Environment::firstOrCreate( $environment = Environment::firstOrCreate(
@ -54,6 +58,7 @@ public function newEnvironment()
'environment_name' => $environment->name, 'environment_name' => $environment->name,
]); ]);
} }
public function newTeam() public function newTeam()
{ {
$team = Team::create( $team = Team::create(

View File

@ -25,6 +25,7 @@ public function edit()
} }
return view('project.edit', ['project' => $project]); return view('project.edit', ['project' => $project]);
} }
public function show() public function show()
{ {
$projectUuid = request()->route('project_uuid'); $projectUuid = request()->route('project_uuid');
@ -55,6 +56,7 @@ public function new()
'type' => $type 'type' => $type
]); ]);
} }
public function resources() public function resources()
{ {
$project = session('currentTeam')->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first(); $project = session('currentTeam')->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();

View File

@ -15,12 +15,6 @@ class ActivityMonitor extends Component
protected $activity; protected $activity;
protected $listeners = ['newMonitorActivity']; protected $listeners = ['newMonitorActivity'];
public function hydrateActivity()
{
$this->activity = Activity::query()
->find($this->activityId);
}
public function newMonitorActivity($activityId) public function newMonitorActivity($activityId)
{ {
$this->activityId = $activityId; $this->activityId = $activityId;
@ -30,6 +24,12 @@ public function newMonitorActivity($activityId)
$this->isPollingActive = true; $this->isPollingActive = true;
} }
public function hydrateActivity()
{
$this->activity = Activity::query()
->find($this->activityId);
}
public function polling() public function polling()
{ {
$this->hydrateActivity(); $this->hydrateActivity();
@ -45,6 +45,7 @@ public function polling()
$this->emit('activityFinished'); $this->emit('activityFinished');
} }
} }
protected function setStatus($status) protected function setStatus($status)
{ {
$this->activity->properties = $this->activity->properties->merge([ $this->activity->properties = $this->activity->properties->merge([
@ -52,4 +53,4 @@ protected function setStatus($status)
]); ]);
$this->activity->save(); $this->activity->save();
} }
} }

View File

@ -19,11 +19,13 @@ class CheckLicense extends Component
'instance_id' => 'Instance Id (Do not change this)', 'instance_id' => 'Instance Id (Do not change this)',
'settings.is_resale_license_active' => 'Is License Active', 'settings.is_resale_license_active' => 'Is License Active',
]; ];
public function mount() public function mount()
{ {
$this->instance_id = config('app.id'); $this->instance_id = config('app.id');
$this->settings = InstanceSettings::get(); $this->settings = InstanceSettings::get();
} }
public function submit() public function submit()
{ {
$this->validate(); $this->validate();

View File

@ -18,11 +18,13 @@ class Form extends Component
'destination.network' => 'network', 'destination.network' => 'network',
'destination.server.ip' => 'IP Address', 'destination.server.ip' => 'IP Address',
]; ];
public function submit() public function submit()
{ {
$this->validate(); $this->validate();
$this->destination->save(); $this->destination->save();
} }
public function delete() public function delete()
{ {
try { try {

View File

@ -5,9 +5,9 @@
use App\Models\Server; use App\Models\Server;
use App\Models\StandaloneDocker as ModelsStandaloneDocker; use App\Models\StandaloneDocker as ModelsStandaloneDocker;
use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Str;
use Livewire\Component; use Livewire\Component;
use Visus\Cuid2\Cuid2; use Visus\Cuid2\Cuid2;
use Illuminate\Support\Str;
class StandaloneDocker extends Component class StandaloneDocker extends Component
{ {
@ -28,6 +28,7 @@ class StandaloneDocker extends Component
'network' => 'network', 'network' => 'network',
'server_id' => 'server' 'server_id' => 'server'
]; ];
public function mount() public function mount()
{ {
if (request()->query('server_id')) { if (request()->query('server_id')) {
@ -44,15 +45,13 @@ public function mount()
} }
$this->name = Str::kebab("{$this->servers->first()->name}-{$this->network}"); $this->name = Str::kebab("{$this->servers->first()->name}-{$this->network}");
} }
public function generate_name() {
public function generate_name()
{
$this->server = Server::find($this->server_id); $this->server = Server::find($this->server_id);
$this->name = Str::kebab("{$this->server->name}-{$this->network}"); $this->name = Str::kebab("{$this->server->name}-{$this->network}");
} }
private function createNetworkAndAttachToProxy()
{
instant_remote_process(['docker network create --attachable ' . $this->network], $this->server, throwError: false);
instant_remote_process(["docker network connect $this->network coolify-proxy"], $this->server, throwError: false);
}
public function submit() public function submit()
{ {
$this->validate(); $this->validate();
@ -77,4 +76,10 @@ public function submit()
return general_error_handler(err: $e); return general_error_handler(err: $e);
} }
} }
}
private function createNetworkAndAttachToProxy()
{
instant_remote_process(['docker network create --attachable ' . $this->network], $this->server, throwError: false);
instant_remote_process(["docker network connect $this->network coolify-proxy"], $this->server, throwError: false);
}
}

View File

@ -10,6 +10,7 @@ class Show extends Component
{ {
public Server $server; public Server $server;
public Collection|array $networks = []; public Collection|array $networks = [];
public function scan() public function scan()
{ {
$alreadyAddedNetworks = $this->server->standaloneDockers; $alreadyAddedNetworks = $this->server->standaloneDockers;

View File

@ -4,33 +4,39 @@
use App\Models\S3Storage; use App\Models\S3Storage;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Livewire\WithFileUploads;
use Livewire\Component; use Livewire\Component;
use Livewire\WithFileUploads;
class S3Test extends Component class S3Test extends Component
{ {
use WithFileUploads; use WithFileUploads;
public $s3; public $s3;
public $file; public $file;
public function mount() {
public function mount()
{
$this->s3 = S3Storage::first(); $this->s3 = S3Storage::first();
} }
public function save() {
public function save()
{
try { try {
$this->validate([ $this->validate([
'file' => 'required|max:150', // 1MB Max 'file' => 'required|max:150', // 1MB Max
]); ]);
set_s3_target($this->s3); set_s3_target($this->s3);
$this->file->storeAs('files', $this->file->getClientOriginalName(),'custom-s3'); $this->file->storeAs('files', $this->file->getClientOriginalName(), 'custom-s3');
$this->emit('success', 'File uploaded successfully.'); $this->emit('success', 'File uploaded successfully.');
} catch (\Throwable $th) { } catch (\Throwable $th) {
return general_error_handler($th, $this, false); return general_error_handler($th, $this, false);
} }
} }
public function get_files() public function get_files()
{ {
set_s3_target($this->s3); set_s3_target($this->s3);
dd(Storage::disk('custom-s3')->files('files')); dd(Storage::disk('custom-s3')->files('files'));
} }
} }

View File

@ -19,6 +19,7 @@ class DiscordSettings extends Component
protected $validationAttributes = [ protected $validationAttributes = [
'model.discord_webhook_url' => 'Discord Webhook', 'model.discord_webhook_url' => 'Discord Webhook',
]; ];
public function instantSave() public function instantSave()
{ {
try { try {
@ -29,6 +30,14 @@ public function instantSave()
$this->validate(); $this->validate();
} }
} }
public function submit()
{
$this->resetErrorBag();
$this->validate();
$this->saveModel();
}
public function saveModel() public function saveModel()
{ {
ray($this->model); ray($this->model);
@ -38,15 +47,10 @@ public function saveModel()
} }
$this->emit('success', 'Settings saved.'); $this->emit('success', 'Settings saved.');
} }
public function submit()
{
$this->resetErrorBag();
$this->validate();
$this->saveModel();
}
public function sendTestNotification() public function sendTestNotification()
{ {
$this->model->notify(new Test); $this->model->notify(new Test);
$this->emit('success', 'Test notification sent.'); $this->emit('success', 'Test notification sent.');
} }
} }

View File

@ -37,6 +37,13 @@ class EmailSettings extends Component
'model.smtp_username' => 'Username', 'model.smtp_username' => 'Username',
'model.smtp_password' => 'Password', 'model.smtp_password' => 'Password',
]; ];
public function mount()
{
$this->decrypt();
$this->emails = auth()->user()->email;
}
private function decrypt() private function decrypt()
{ {
if (data_get($this->model, 'smtp_password')) { if (data_get($this->model, 'smtp_password')) {
@ -46,11 +53,7 @@ private function decrypt()
} }
} }
} }
public function mount()
{
$this->decrypt();
$this->emails = auth()->user()->email;
}
public function copyFromInstanceSettings() public function copyFromInstanceSettings()
{ {
$settings = InstanceSettings::get(); $settings = InstanceSettings::get();
@ -78,6 +81,23 @@ public function copyFromInstanceSettings()
$this->emit('error', 'Instance SMTP settings are not enabled.'); $this->emit('error', 'Instance SMTP settings are not enabled.');
} }
} }
public function sendTestNotification()
{
$this->model->notify(new Test($this->emails));
$this->emit('success', 'Test Email sent successfully.');
}
public function instantSave()
{
try {
$this->submit();
} catch (\Exception $e) {
$this->model->smtp_enabled = false;
$this->validate();
}
}
public function submit() public function submit()
{ {
$this->resetErrorBag(); $this->resetErrorBag();
@ -92,6 +112,7 @@ public function submit()
$this->model->smtp_recipients = str_replace(' ', '', $this->model->smtp_recipients); $this->model->smtp_recipients = str_replace(' ', '', $this->model->smtp_recipients);
$this->saveModel(); $this->saveModel();
} }
public function saveModel() public function saveModel()
{ {
$this->model->save(); $this->model->save();
@ -101,18 +122,4 @@ public function saveModel()
} }
$this->emit('success', 'Settings saved.'); $this->emit('success', 'Settings saved.');
} }
public function sendTestNotification() }
{
$this->model->notify(new Test($this->emails));
$this->emit('success', 'Test Email sent successfully.');
}
public function instantSave()
{
try {
$this->submit();
} catch (\Exception $e) {
$this->model->smtp_enabled = false;
$this->validate();
}
}
}

View File

@ -20,6 +20,7 @@ class Change extends Component
'private_key.description' => 'description', 'private_key.description' => 'description',
'private_key.private_key' => 'private key' 'private_key.private_key' => 'private key'
]; ];
public function delete() public function delete()
{ {
try { try {
@ -33,6 +34,7 @@ public function delete()
return general_error_handler(err: $e, that: $this); return general_error_handler(err: $e, that: $this);
} }
} }
public function changePrivateKey() public function changePrivateKey()
{ {
try { try {

View File

@ -19,6 +19,7 @@ class Create extends Component
'name' => 'name', 'name' => 'name',
'value' => 'private Key', 'value' => 'private Key',
]; ];
public function createPrivateKey() public function createPrivateKey()
{ {
$this->validate(); $this->validate();

View File

@ -17,12 +17,14 @@ class Form extends Component
protected $validationAttributes = [ protected $validationAttributes = [
'name' => 'name', 'name' => 'name',
]; ];
public function mount() public function mount()
{ {
$this->userId = auth()->user()->id; $this->userId = auth()->user()->id;
$this->name = auth()->user()->name; $this->name = auth()->user()->name;
$this->email = auth()->user()->email; $this->email = auth()->user()->email;
} }
public function submit() public function submit()
{ {

View File

@ -17,6 +17,7 @@ class AddEmpty extends Component
'name' => 'Project Name', 'name' => 'Project Name',
'description' => 'Project Description', 'description' => 'Project Description',
]; ];
public function submit() public function submit()
{ {
try { try {

View File

@ -17,6 +17,7 @@ class AddEnvironment extends Component
protected $validationAttributes = [ protected $validationAttributes = [
'name' => 'Environment Name', 'name' => 'Environment Name',
]; ];
public function submit() public function submit()
{ {
try { try {

View File

@ -10,10 +10,12 @@ class DeploymentLogs extends Component
public ApplicationDeploymentQueue $application_deployment_queue; public ApplicationDeploymentQueue $application_deployment_queue;
public $isKeepAliveOn = true; public $isKeepAliveOn = true;
protected $listeners = ['refreshQueue']; protected $listeners = ['refreshQueue'];
public function refreshQueue() public function refreshQueue()
{ {
$this->application_deployment_queue->refresh(); $this->application_deployment_queue->refresh();
} }
public function polling() public function polling()
{ {
$this->emit('deploymentFinished'); $this->emit('deploymentFinished');

View File

@ -8,17 +8,16 @@
use App\Models\Server; use App\Models\Server;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Process; use Illuminate\Support\Facades\Process;
use Livewire\Component;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Livewire\Component;
class DeploymentNavbar extends Component class DeploymentNavbar extends Component
{ {
protected $listeners = ['deploymentFinished'];
public ApplicationDeploymentQueue $application_deployment_queue; public ApplicationDeploymentQueue $application_deployment_queue;
public Application $application; public Application $application;
public Server $server; public Server $server;
public bool $is_debug_enabled = false; public bool $is_debug_enabled = false;
protected $listeners = ['deploymentFinished'];
public function mount() public function mount()
{ {
@ -26,10 +25,12 @@ public function mount()
$this->server = $this->application->destination->server; $this->server = $this->application->destination->server;
$this->is_debug_enabled = $this->application->settings->is_debug_enabled; $this->is_debug_enabled = $this->application->settings->is_debug_enabled;
} }
public function deploymentFinished() public function deploymentFinished()
{ {
$this->application_deployment_queue->refresh(); $this->application_deployment_queue->refresh();
} }
public function show_debug() public function show_debug()
{ {
$this->application->settings->is_debug_enabled = !$this->application->settings->is_debug_enabled; $this->application->settings->is_debug_enabled = !$this->application->settings->is_debug_enabled;
@ -37,6 +38,7 @@ public function show_debug()
$this->is_debug_enabled = $this->application->settings->is_debug_enabled; $this->is_debug_enabled = $this->application->settings->is_debug_enabled;
$this->emit('refreshQueue'); $this->emit('refreshQueue');
} }
public function cancel() public function cancel()
{ {
try { try {
@ -66,4 +68,4 @@ public function cancel()
return general_error_handler(err: $e, that: $this); return general_error_handler(err: $e, that: $this);
} }
} }
} }

View File

@ -20,6 +20,7 @@ public function mount()
$this->current_url = url()->current(); $this->current_url = url()->current();
$this->show_more(); $this->show_more();
} }
private function show_more() private function show_more()
{ {
if (count($this->deployments) !== 0) { if (count($this->deployments) !== 0) {
@ -30,10 +31,12 @@ private function show_more()
return; return;
} }
} }
public function reload_deployments() public function reload_deployments()
{ {
$this->load_deployments(); $this->load_deployments();
} }
public function load_deployments(int|null $take = null) public function load_deployments(int|null $take = null)
{ {
if ($take) { if ($take) {

View File

@ -4,8 +4,8 @@
use App\Models\Application; use App\Models\Application;
use App\Models\InstanceSettings; use App\Models\InstanceSettings;
use Livewire\Component;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Livewire\Component;
use Spatie\Url\Url; use Spatie\Url\Url;
class General extends Component class General extends Component
@ -65,6 +65,7 @@ class General extends Component
'application.ports_exposes' => 'Ports exposes', 'application.ports_exposes' => 'Ports exposes',
'application.ports_mappings' => 'Ports mappings', 'application.ports_mappings' => 'Ports mappings',
]; ];
public function instantSave() public function instantSave()
{ {
// @TODO: find another way - if possible // @TODO: find another way - if possible
@ -86,6 +87,7 @@ public function instantSave()
$this->emit('success', 'Application settings updated!'); $this->emit('success', 'Application settings updated!');
$this->checkWildCardDomain(); $this->checkWildCardDomain();
} }
protected function checkWildCardDomain() protected function checkWildCardDomain()
{ {
$coolify_instance_settings = InstanceSettings::get(); $coolify_instance_settings = InstanceSettings::get();
@ -93,6 +95,7 @@ protected function checkWildCardDomain()
$this->global_wildcard_domain = data_get($coolify_instance_settings, 'wildcard_domain'); $this->global_wildcard_domain = data_get($coolify_instance_settings, 'wildcard_domain');
$this->wildcard_domain = $this->server_wildcard_domain ?? $this->global_wildcard_domain ?? null; $this->wildcard_domain = $this->server_wildcard_domain ?? $this->global_wildcard_domain ?? null;
} }
public function mount() public function mount()
{ {
$this->is_static = $this->application->settings->is_static; $this->is_static = $this->application->settings->is_static;
@ -104,6 +107,7 @@ public function mount()
$this->is_force_https_enabled = $this->application->settings->is_force_https_enabled; $this->is_force_https_enabled = $this->application->settings->is_force_https_enabled;
$this->checkWildCardDomain(); $this->checkWildCardDomain();
} }
public function generateGlobalRandomDomain() public function generateGlobalRandomDomain()
{ {
// Set wildcard domain based on Global wildcard domain // Set wildcard domain based on Global wildcard domain
@ -115,6 +119,7 @@ public function generateGlobalRandomDomain()
$this->application->save(); $this->application->save();
$this->emit('success', 'Application settings updated!'); $this->emit('success', 'Application settings updated!');
} }
public function generateServerRandomDomain() public function generateServerRandomDomain()
{ {
// Set wildcard domain based on Server wildcard domain // Set wildcard domain based on Server wildcard domain
@ -126,6 +131,7 @@ public function generateServerRandomDomain()
$this->application->save(); $this->application->save();
$this->emit('success', 'Application settings updated!'); $this->emit('success', 'Application settings updated!');
} }
public function submit() public function submit()
{ {
try { try {

View File

@ -28,6 +28,12 @@ public function check_status()
)); ));
$this->application->refresh(); $this->application->refresh();
} }
public function force_deploy_without_cache()
{
$this->deploy(force_rebuild: true);
}
public function deploy(bool $force_rebuild = false) public function deploy(bool $force_rebuild = false)
{ {
$this->setDeploymentUuid(); $this->setDeploymentUuid();
@ -43,10 +49,13 @@ public function deploy(bool $force_rebuild = false)
'environment_name' => $this->parameters['environment_name'], 'environment_name' => $this->parameters['environment_name'],
]); ]);
} }
public function force_deploy_without_cache()
protected function setDeploymentUuid()
{ {
$this->deploy(force_rebuild: true); $this->deploymentUuid = new Cuid2(7);
$this->parameters['deployment_uuid'] = $this->deploymentUuid;
} }
public function stop() public function stop()
{ {
remote_process( remote_process(
@ -57,9 +66,4 @@ public function stop()
$this->application->save(); $this->application->save();
$this->application->environment->project->team->notify(new StatusChanged($this->application)); $this->application->environment->project->team->notify(new StatusChanged($this->application));
} }
protected function setDeploymentUuid()
{
$this->deploymentUuid = new Cuid2(7);
$this->parameters['deployment_uuid'] = $this->deploymentUuid;
}
} }

View File

@ -17,6 +17,7 @@ class Form extends Component
protected $validationAttributes = [ protected $validationAttributes = [
'application.preview_url_template' => 'preview url template', 'application.preview_url_template' => 'preview url template',
]; ];
public function resetToDefault() public function resetToDefault()
{ {
$this->application->preview_url_template = '{{pr_id}}.{{domain}}'; $this->application->preview_url_template = '{{pr_id}}.{{domain}}';
@ -24,6 +25,7 @@ public function resetToDefault()
$this->application->save(); $this->application->save();
$this->generate_real_url(); $this->generate_real_url();
} }
public function generate_real_url() public function generate_real_url()
{ {
if (data_get($this->application, 'fqdn')) { if (data_get($this->application, 'fqdn')) {
@ -32,10 +34,12 @@ public function generate_real_url()
$this->preview_url_template = Str::of($this->application->preview_url_template)->replace('{{domain}}', $host); $this->preview_url_template = Str::of($this->application->preview_url_template)->replace('{{domain}}', $host);
} }
} }
public function mount() public function mount()
{ {
$this->generate_real_url(); $this->generate_real_url();
} }
public function submit() public function submit()
{ {
$this->validate(); $this->validate();

View File

@ -22,6 +22,7 @@ public function mount()
$this->pull_requests = collect(); $this->pull_requests = collect();
$this->parameters = getRouteParameters(); $this->parameters = getRouteParameters();
} }
public function loadStatus($pull_request_id) public function loadStatus($pull_request_id)
{ {
dispatch(new ContainerStatusJob( dispatch(new ContainerStatusJob(
@ -30,11 +31,7 @@ public function loadStatus($pull_request_id)
pull_request_id: $pull_request_id pull_request_id: $pull_request_id
)); ));
} }
protected function setDeploymentUuid()
{
$this->deployment_uuid = new Cuid2(7);
$this->parameters['deployment_uuid'] = $this->deployment_uuid;
}
public function load_prs() public function load_prs()
{ {
try { try {
@ -46,6 +43,7 @@ public function load_prs()
return general_error_handler(err: $e, that: $this); return general_error_handler(err: $e, that: $this);
} }
} }
public function deploy(int $pull_request_id, string|null $pull_request_html_url = null) public function deploy(int $pull_request_id, string|null $pull_request_html_url = null)
{ {
try { try {
@ -74,6 +72,13 @@ public function deploy(int $pull_request_id, string|null $pull_request_html_url
return general_error_handler(err: $e, that: $this); return general_error_handler(err: $e, that: $this);
} }
} }
protected function setDeploymentUuid()
{
$this->deployment_uuid = new Cuid2(7);
$this->parameters['deployment_uuid'] = $this->deployment_uuid;
}
public function stop(int $pull_request_id) public function stop(int $pull_request_id)
{ {
try { try {
@ -87,6 +92,7 @@ public function stop(int $pull_request_id)
return general_error_handler(err: $e, that: $this); return general_error_handler(err: $e, that: $this);
} }
} }
public function previewRefresh() public function previewRefresh()
{ {
$this->application->previews->each(function ($preview) { $this->application->previews->each(function ($preview) {

View File

@ -3,8 +3,8 @@
namespace App\Http\Livewire\Project\Application; namespace App\Http\Livewire\Project\Application;
use App\Models\Application; use App\Models\Application;
use Livewire\Component;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Livewire\Component;
use Visus\Cuid2\Cuid2; use Visus\Cuid2\Cuid2;
class Rollback extends Component class Rollback extends Component
@ -18,6 +18,7 @@ public function mount()
{ {
$this->parameters = getRouteParameters(); $this->parameters = getRouteParameters();
} }
public function rollbackImage($commit) public function rollbackImage($commit)
{ {
$deployment_uuid = new Cuid2(7); $deployment_uuid = new Cuid2(7);
@ -36,6 +37,7 @@ public function rollbackImage($commit)
'environment_name' => $this->parameters['environment_name'], 'environment_name' => $this->parameters['environment_name'],
]); ]);
} }
public function loadImages() public function loadImages()
{ {
try { try {

View File

@ -21,16 +21,19 @@ class Source extends Component
'application.git_branch' => 'branch', 'application.git_branch' => 'branch',
'application.git_commit_sha' => 'commit sha', 'application.git_commit_sha' => 'commit sha',
]; ];
public function mount()
{
$this->get_private_keys();
}
private function get_private_keys() private function get_private_keys()
{ {
$this->private_keys = PrivateKey::whereTeamId(session('currentTeam')->id)->get()->reject(function ($key) { $this->private_keys = PrivateKey::whereTeamId(session('currentTeam')->id)->get()->reject(function ($key) {
return $key->id == $this->application->private_key_id; return $key->id == $this->application->private_key_id;
}); });
} }
public function mount()
{
$this->get_private_keys();
}
public function setPrivateKey(int $private_key_id) public function setPrivateKey(int $private_key_id)
{ {
$this->application->private_key_id = $private_key_id; $this->application->private_key_id = $private_key_id;
@ -38,6 +41,7 @@ public function setPrivateKey(int $private_key_id)
$this->application->refresh(); $this->application->refresh();
$this->get_private_keys(); $this->get_private_keys();
} }
public function submit() public function submit()
{ {
$this->validate(); $this->validate();

View File

@ -2,10 +2,10 @@
namespace App\Http\Livewire\Project\Database; namespace App\Http\Livewire\Project\Database;
use Livewire\Component;
use App\Actions\Database\StartPostgresql; use App\Actions\Database\StartPostgresql;
use App\Jobs\ContainerStatusJob; use App\Jobs\ContainerStatusJob;
use App\Notifications\Application\StatusChanged; use App\Notifications\Application\StatusChanged;
use Livewire\Component;
class Heading extends Component class Heading extends Component
{ {
@ -13,13 +13,16 @@ class Heading extends Component
public array $parameters; public array $parameters;
protected $listeners = ['activityFinished']; protected $listeners = ['activityFinished'];
public function activityFinished() {
public function activityFinished()
{
$this->database->update([ $this->database->update([
'started_at' => now(), 'started_at' => now(),
]); ]);
$this->emit('refresh'); $this->emit('refresh');
$this->check_status(); $this->check_status();
} }
public function check_status() public function check_status()
{ {
dispatch_sync(new ContainerStatusJob( dispatch_sync(new ContainerStatusJob(
@ -28,11 +31,14 @@ public function check_status()
)); ));
$this->database->refresh(); $this->database->refresh();
} }
public function mount() public function mount()
{ {
$this->parameters = getRouteParameters(); $this->parameters = getRouteParameters();
} }
public function stop() {
public function stop()
{
remote_process( remote_process(
["docker rm -f {$this->database->uuid}"], ["docker rm -f {$this->database->uuid}"],
$this->database->destination->server $this->database->destination->server
@ -41,7 +47,9 @@ public function stop() {
$this->database->save(); $this->database->save();
$this->database->environment->project->team->notify(new StatusChanged($this->database)); $this->database->environment->project->team->notify(new StatusChanged($this->database));
} }
public function start() {
public function start()
{
if ($this->database->type() === 'standalone-postgresql') { if ($this->database->type() === 'standalone-postgresql') {
$activity = resolve(StartPostgresql::class)($this->database->destination->server, $this->database); $activity = resolve(StartPostgresql::class)($this->database->destination->server, $this->database);
$this->emit('newMonitorActivity', $activity->id); $this->emit('newMonitorActivity', $activity->id);

View File

@ -31,10 +31,14 @@ class General extends Component
'database.init_scripts' => 'Init Scripts', 'database.init_scripts' => 'Init Scripts',
'database.image' => 'Image', 'database.image' => 'Image',
]; ];
public function refresh() {
public function refresh(): void
{
$this->database->refresh(); $this->database->refresh();
} }
public function submit() {
public function submit()
{
try { try {
$this->validate(); $this->validate();
$this->database->save(); $this->database->save();

View File

@ -14,6 +14,7 @@ public function mount()
{ {
$this->parameters = getRouteParameters(); $this->parameters = getRouteParameters();
} }
public function delete() public function delete()
{ {
$this->validate([ $this->validate([

View File

@ -14,6 +14,7 @@ public function mount()
{ {
$this->parameters = getRouteParameters(); $this->parameters = getRouteParameters();
} }
public function delete() public function delete()
{ {
$this->validate([ $this->validate([

View File

@ -5,12 +5,9 @@
use App\Models\Application; use App\Models\Application;
use App\Models\GithubApp; use App\Models\GithubApp;
use App\Models\Project; use App\Models\Project;
use App\Models\Server;
use App\Models\StandaloneDocker; use App\Models\StandaloneDocker;
use App\Models\SwarmDocker; use App\Models\SwarmDocker;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Livewire\Component; use Livewire\Component;
class GithubPrivateRepository extends Component class GithubPrivateRepository extends Component
@ -30,18 +27,14 @@ class GithubPrivateRepository extends Component
public string $selected_branch_name = 'main'; public string $selected_branch_name = 'main';
public string $token; public string $token;
protected int $page = 1;
public $repositories; public $repositories;
public int $total_repositories_count = 0; public int $total_repositories_count = 0;
public $branches; public $branches;
public int $total_branches_count = 0; public int $total_branches_count = 0;
public int $port = 3000; public int $port = 3000;
public bool $is_static = false; public bool $is_static = false;
public string|null $publish_directory = null; public string|null $publish_directory = null;
protected int $page = 1;
public function mount() public function mount()
{ {
@ -50,32 +43,7 @@ public function mount()
$this->repositories = $this->branches = collect(); $this->repositories = $this->branches = collect();
$this->github_apps = GithubApp::private(); $this->github_apps = GithubApp::private();
} }
protected function loadRepositoryByPage()
{
$response = Http::withToken($this->token)->get("{$this->github_app->api_url}/installation/repositories?per_page=100&page={$this->page}");
$json = $response->json();
if ($response->status() !== 200) {
return $this->emit('error', $json['message']);
}
if ($json['total_count'] === 0) {
return;
}
$this->total_repositories_count = $json['total_count'];
$this->repositories = $this->repositories->concat(collect($json['repositories']));
}
protected function loadBranchByPage()
{
ray('Loading page ' . $this->page);
$response = Http::withToken($this->token)->get("{$this->github_app->api_url}/repos/{$this->selected_repository_owner}/{$this->selected_repository_repo}/branches?per_page=100&page={$this->page}");
$json = $response->json();
if ($response->status() !== 200) {
return $this->emit('error', $json['message']);
}
$this->total_branches_count = count($json);
$this->branches = $this->branches->concat(collect($json));
}
public function loadRepositories($github_app_id) public function loadRepositories($github_app_id)
{ {
$this->repositories = collect(); $this->repositories = collect();
@ -93,6 +61,22 @@ public function loadRepositories($github_app_id)
$this->selected_repository_id = $this->repositories[0]['id']; $this->selected_repository_id = $this->repositories[0]['id'];
$this->current_step = 'repository'; $this->current_step = 'repository';
} }
protected function loadRepositoryByPage()
{
$response = Http::withToken($this->token)->get("{$this->github_app->api_url}/installation/repositories?per_page=100&page={$this->page}");
$json = $response->json();
if ($response->status() !== 200) {
return $this->emit('error', $json['message']);
}
if ($json['total_count'] === 0) {
return;
}
$this->total_repositories_count = $json['total_count'];
$this->repositories = $this->repositories->concat(collect($json['repositories']));
}
public function loadBranches() public function loadBranches()
{ {
$this->selected_repository_owner = $this->repositories->where('id', $this->selected_repository_id)->first()['owner']['login']; $this->selected_repository_owner = $this->repositories->where('id', $this->selected_repository_id)->first()['owner']['login'];
@ -107,6 +91,20 @@ public function loadBranches()
} }
} }
} }
protected function loadBranchByPage()
{
ray('Loading page ' . $this->page);
$response = Http::withToken($this->token)->get("{$this->github_app->api_url}/repos/{$this->selected_repository_owner}/{$this->selected_repository_repo}/branches?per_page=100&page={$this->page}");
$json = $response->json();
if ($response->status() !== 200) {
return $this->emit('error', $json['message']);
}
$this->total_branches_count = count($json);
$this->branches = $this->branches->concat(collect($json));
}
public function submit() public function submit()
{ {
try { try {
@ -136,7 +134,7 @@ public function submit()
'destination_id' => $destination->id, 'destination_id' => $destination->id,
'destination_type' => $destination_class, 'destination_type' => $destination_class,
'source_id' => $this->github_app->id, 'source_id' => $this->github_app->id,
'source_type' => $this->github_app->getMorphClass() 'source_type' => $this->github_app->getMorphClass()
]); ]);
$application->settings->is_static = $this->is_static; $application->settings->is_static = $this->is_static;
$application->settings->save(); $application->settings->save();
@ -150,6 +148,7 @@ public function submit()
return general_error_handler(err: $e, that: $this); return general_error_handler(err: $e, that: $this);
} }
} }
public function instantSave() public function instantSave()
{ {
if ($this->is_static) { if ($this->is_static) {

View File

@ -27,14 +27,7 @@ class GithubPrivateRepositoryDeployKey extends Component
public null|string $publish_directory = null; public null|string $publish_directory = null;
public string $repository_url; public string $repository_url;
private object $repository_url_parsed;
public string $branch; public string $branch;
private GithubApp|GitlabApp $git_source;
private string $git_host;
private string $git_repository;
private string $git_branch;
protected $rules = [ protected $rules = [
'repository_url' => 'required|url', 'repository_url' => 'required|url',
'branch' => 'required|string', 'branch' => 'required|string',
@ -49,6 +42,12 @@ class GithubPrivateRepositoryDeployKey extends Component
'is_static' => 'Is static', 'is_static' => 'Is static',
'publish_directory' => 'Publish directory', 'publish_directory' => 'Publish directory',
]; ];
private object $repository_url_parsed;
private GithubApp|GitlabApp $git_source;
private string $git_host;
private string $git_repository;
private string $git_branch;
public function mount() public function mount()
{ {
if (isDev()) { if (isDev()) {
@ -58,6 +57,7 @@ public function mount()
$this->query = request()->query(); $this->query = request()->query();
$this->private_keys = PrivateKey::where('team_id', session('currentTeam')->id)->where('id', '!=', 0)->get(); $this->private_keys = PrivateKey::where('team_id', session('currentTeam')->id)->where('id', '!=', 0)->get();
} }
public function instantSave() public function instantSave()
{ {
if ($this->is_static) { if ($this->is_static) {
@ -68,30 +68,13 @@ public function instantSave()
$this->publish_directory = null; $this->publish_directory = null;
} }
} }
public function setPrivateKey($private_key_id) public function setPrivateKey($private_key_id)
{ {
$this->private_key_id = $private_key_id; $this->private_key_id = $private_key_id;
$this->current_step = 'repository'; $this->current_step = 'repository';
} }
private function get_git_source()
{
$this->repository_url_parsed = Url::fromString($this->repository_url);
$this->git_host = $this->repository_url_parsed->getHost();
$this->git_repository = $this->repository_url_parsed->getSegment(1) . '/' . $this->repository_url_parsed->getSegment(2);
if ($this->branch) {
$this->git_branch = $this->branch;
} else {
$this->git_branch = $this->repository_url_parsed->getSegment(4) ?? 'main';
}
if ($this->git_host == 'github.com') {
$this->git_source = GithubApp::where('name', 'Public GitHub')->first();
} elseif ($this->git_host == 'gitlab.com') {
$this->git_source = GitlabApp::where('name', 'Public GitLab')->first();
} elseif ($this->git_host == 'bitbucket.org') {
// Not supported yet
}
}
public function submit() public function submit()
{ {
$this->validate(); $this->validate();
@ -123,7 +106,7 @@ public function submit()
'destination_type' => $destination_class, 'destination_type' => $destination_class,
'private_key_id' => $this->private_key_id, 'private_key_id' => $this->private_key_id,
'source_id' => $this->git_source->id, 'source_id' => $this->git_source->id,
'source_type' => $this->git_source->getMorphClass() 'source_type' => $this->git_source->getMorphClass()
]; ];
$application = Application::create($application_init); $application = Application::create($application_init);
$application->settings->is_static = $this->is_static; $application->settings->is_static = $this->is_static;
@ -138,4 +121,24 @@ public function submit()
return general_error_handler(err: $e, that: $this); return general_error_handler(err: $e, that: $this);
} }
} }
private function get_git_source()
{
$this->repository_url_parsed = Url::fromString($this->repository_url);
$this->git_host = $this->repository_url_parsed->getHost();
$this->git_repository = $this->repository_url_parsed->getSegment(1) . '/' . $this->repository_url_parsed->getSegment(2);
if ($this->branch) {
$this->git_branch = $this->branch;
} else {
$this->git_branch = $this->repository_url_parsed->getSegment(4) ?? 'main';
}
if ($this->git_host == 'github.com') {
$this->git_source = GithubApp::where('name', 'Public GitHub')->first();
} elseif ($this->git_host == 'gitlab.com') {
$this->git_source = GitlabApp::where('name', 'Public GitLab')->first();
} elseif ($this->git_host == 'bitbucket.org') {
// Not supported yet
}
}
} }

View File

@ -15,13 +15,10 @@
class PublicGitRepository extends Component class PublicGitRepository extends Component
{ {
public string $repository_url; public string $repository_url;
private object $repository_url_parsed;
public int $port = 3000; public int $port = 3000;
public string $type; public string $type;
public $parameters; public $parameters;
public $query; public $query;
public bool $branch_found = false; public bool $branch_found = false;
public string $selected_branch = 'main'; public string $selected_branch = 'main';
public bool $is_static = false; public bool $is_static = false;
@ -29,11 +26,6 @@ class PublicGitRepository extends Component
public string $git_branch = 'main'; public string $git_branch = 'main';
public int $rate_limit_remaining = 0; public int $rate_limit_remaining = 0;
public $rate_limit_reset = 0; public $rate_limit_reset = 0;
private GithubApp|GitlabApp $git_source;
private string $git_host;
private string $git_repository;
protected $rules = [ protected $rules = [
'repository_url' => 'required|url', 'repository_url' => 'required|url',
'port' => 'required|numeric', 'port' => 'required|numeric',
@ -46,6 +38,11 @@ class PublicGitRepository extends Component
'is_static' => 'static', 'is_static' => 'static',
'publish_directory' => 'publish directory', 'publish_directory' => 'publish directory',
]; ];
private object $repository_url_parsed;
private GithubApp|GitlabApp $git_source;
private string $git_host;
private string $git_repository;
public function mount() public function mount()
{ {
if (isDev()) { if (isDev()) {
@ -67,12 +64,7 @@ public function instantSave()
} }
$this->emit('success', 'Application settings updated!'); $this->emit('success', 'Application settings updated!');
} }
private function get_branch()
{
['rate_limit_remaining' => $this->rate_limit_remaining, 'rate_limit_reset' => $this->rate_limit_reset] = git_api(source: $this->git_source, endpoint: "/repos/{$this->git_repository}/branches/{$this->git_branch}");
$this->rate_limit_reset = Carbon::parse((int)$this->rate_limit_reset)->format('Y-M-d H:i:s');
$this->branch_found = true;
}
public function load_branch() public function load_branch()
{ {
$this->branch_found = false; $this->branch_found = false;
@ -96,6 +88,7 @@ public function load_branch()
} }
} }
} }
private function get_git_source() private function get_git_source()
{ {
$this->repository_url_parsed = Url::fromString($this->repository_url); $this->repository_url_parsed = Url::fromString($this->repository_url);
@ -111,6 +104,14 @@ private function get_git_source()
// Not supported yet // Not supported yet
} }
} }
private function get_branch()
{
['rate_limit_remaining' => $this->rate_limit_remaining, 'rate_limit_reset' => $this->rate_limit_reset] = git_api(source: $this->git_source, endpoint: "/repos/{$this->git_repository}/branches/{$this->git_branch}");
$this->rate_limit_reset = Carbon::parse((int)$this->rate_limit_reset)->format('Y-M-d H:i:s');
$this->branch_found = true;
}
public function submit() public function submit()
{ {
try { try {

View File

@ -19,17 +19,20 @@ public function mount()
{ {
$this->parameters = getRouteParameters(); $this->parameters = getRouteParameters();
} }
public function set_type(string $type) public function set_type(string $type)
{ {
$this->type = $type; $this->type = $type;
$this->current_step = 'servers'; $this->current_step = 'servers';
} }
public function set_server(Server $server) public function set_server(Server $server)
{ {
$this->server_id = $server->id; $this->server_id = $server->id;
$this->destinations = $server->destinations(); $this->destinations = $server->destinations();
$this->current_step = 'destinations'; $this->current_step = 'destinations';
} }
public function set_destination(string $destination_uuid) public function set_destination(string $destination_uuid)
{ {
$this->destination_uuid = $destination_uuid; $this->destination_uuid = $destination_uuid;
@ -40,6 +43,7 @@ public function set_destination(string $destination_uuid)
'destination' => $this->destination_uuid, 'destination' => $this->destination_uuid,
]); ]);
} }
public function load_servers() public function load_servers()
{ {
$this->servers = Server::ownedByCurrentTeam()->get(); $this->servers = Server::ownedByCurrentTeam()->get();

View File

@ -16,6 +16,7 @@ public function mount()
$this->modalId = new Cuid2(7); $this->modalId = new Cuid2(7);
$this->parameters = getRouteParameters(); $this->parameters = getRouteParameters();
} }
public function delete() public function delete()
{ {
$destination = $this->resource->destination->getMorphClass()::where('id', $this->resource->destination->id)->first(); $destination = $this->resource->destination->getMorphClass()::where('id', $this->resource->destination->id)->first();

View File

@ -23,10 +23,12 @@ class Add extends Component
'value' => 'value', 'value' => 'value',
'is_build_time' => 'build', 'is_build_time' => 'build',
]; ];
public function mount() public function mount()
{ {
$this->parameters = getRouteParameters(); $this->parameters = getRouteParameters();
} }
public function submit() public function submit()
{ {
ray('submitting'); ray('submitting');
@ -39,6 +41,7 @@ public function submit()
]); ]);
$this->clear(); $this->clear();
} }
public function clear() public function clear()
{ {
$this->key = ''; $this->key = '';

View File

@ -11,14 +11,17 @@ class All extends Component
public $resource; public $resource;
public string|null $modalId = null; public string|null $modalId = null;
protected $listeners = ['refreshEnvs', 'submit']; protected $listeners = ['refreshEnvs', 'submit'];
public function mount() public function mount()
{ {
$this->modalId = new Cuid2(7); $this->modalId = new Cuid2(7);
} }
public function refreshEnvs() public function refreshEnvs()
{ {
$this->resource->refresh(); $this->resource->refresh();
} }
public function submit($data) public function submit($data)
{ {
try { try {
@ -27,16 +30,16 @@ public function submit($data)
$this->emit('error', 'Environment variable already exists.'); $this->emit('error', 'Environment variable already exists.');
return; return;
} }
$environment = new EnvironmentVariable(); $environment = new EnvironmentVariable();
$environment->key = $data['key']; $environment->key = $data['key'];
$environment->value = $data['value']; $environment->value = $data['value'];
$environment->is_build_time = $data['is_build_time']; $environment->is_build_time = $data['is_build_time'];
$environment->is_preview = $data['is_preview']; $environment->is_preview = $data['is_preview'];
if($this->resource->type() === 'application') { if ($this->resource->type() === 'application') {
$environment->application_id = $this->resource->id; $environment->application_id = $this->resource->id;
} }
if($this->resource->type() === 'standalone-postgresql') { if ($this->resource->type() === 'standalone-postgresql') {
$environment->standalone_postgresql_id = $this->resource->id; $environment->standalone_postgresql_id = $this->resource->id;
} }
$environment->save(); $environment->save();

View File

@ -21,17 +21,20 @@ class Show extends Component
'value' => 'value', 'value' => 'value',
'is_build_time' => 'build', 'is_build_time' => 'build',
]; ];
public function mount() public function mount()
{ {
$this->modalId = new Cuid2(7); $this->modalId = new Cuid2(7);
$this->parameters = getRouteParameters(); $this->parameters = getRouteParameters();
} }
public function submit() public function submit()
{ {
$this->validate(); $this->validate();
$this->env->save(); $this->env->save();
$this->emit('success', 'Environment variable updated successfully.'); $this->emit('success', 'Environment variable updated successfully.');
} }
public function delete() public function delete()
{ {
$this->env->delete(); $this->env->delete();

View File

@ -25,6 +25,7 @@ class ResourceLimits extends Component
'resource.limits_cpuset' => 'cpuset', 'resource.limits_cpuset' => 'cpuset',
'resource.limits_cpu_shares' => 'cpu shares', 'resource.limits_cpu_shares' => 'cpu shares',
]; ];
public function submit() public function submit()
{ {
try { try {

View File

@ -22,10 +22,12 @@ class Add extends Component
'mount_path' => 'mount', 'mount_path' => 'mount',
'host_path' => 'host', 'host_path' => 'host',
]; ];
public function mount() public function mount()
{ {
$this->parameters = getRouteParameters(); $this->parameters = getRouteParameters();
} }
public function submit() public function submit()
{ {
$this->validate(); $this->validate();
@ -35,6 +37,7 @@ public function submit()
'host_path' => $this->host_path, 'host_path' => $this->host_path,
]); ]);
} }
public function clear() public function clear()
{ {
$this->name = ''; $this->name = '';

View File

@ -9,10 +9,12 @@ class All extends Component
{ {
public $resource; public $resource;
protected $listeners = ['refreshStorages', 'submit']; protected $listeners = ['refreshStorages', 'submit'];
public function refreshStorages() public function refreshStorages()
{ {
$this->resource->refresh(); $this->resource->refresh();
} }
public function submit($data) public function submit($data)
{ {
try { try {

View File

@ -19,16 +19,19 @@ class Show extends Component
'mount_path' => 'mount', 'mount_path' => 'mount',
'host_path' => 'host', 'host_path' => 'host',
]; ];
public function mount() public function mount()
{ {
$this->modalId = new Cuid2(7); $this->modalId = new Cuid2(7);
} }
public function submit() public function submit()
{ {
$this->validate(); $this->validate();
$this->storage->save(); $this->storage->save();
$this->emit('success', 'Storage updated successfully'); $this->emit('success', 'Storage updated successfully');
} }
public function delete() public function delete()
{ {
$this->storage->delete(); $this->storage->delete();

View File

@ -2,7 +2,6 @@
namespace App\Http\Livewire; namespace App\Http\Livewire;
use App\Enums\ActivityTypes;
use App\Models\Server; use App\Models\Server;
use Livewire\Component; use Livewire\Component;
@ -20,6 +19,7 @@ class RunCommand extends Component
'server' => 'server', 'server' => 'server',
'command' => 'command', 'command' => 'command',
]; ];
public function mount($servers) public function mount($servers)
{ {
$this->servers = $servers; $this->servers = $servers;

View File

@ -5,7 +5,6 @@
use App\Actions\Server\InstallDocker; use App\Actions\Server\InstallDocker;
use App\Models\Server; use App\Models\Server;
use Livewire\Component; use Livewire\Component;
use Visus\Cuid2\Cuid2;
class Form extends Component class Form extends Component
{ {
@ -34,16 +33,19 @@ class Form extends Component
'server.settings.is_reachable' => 'is reachable', 'server.settings.is_reachable' => 'is reachable',
'server.settings.is_part_of_swarm' => 'is part of swarm' 'server.settings.is_part_of_swarm' => 'is part of swarm'
]; ];
public function mount() public function mount()
{ {
$this->wildcard_domain = $this->server->settings->wildcard_domain; $this->wildcard_domain = $this->server->settings->wildcard_domain;
$this->cleanup_after_percentage = $this->server->settings->cleanup_after_percentage; $this->cleanup_after_percentage = $this->server->settings->cleanup_after_percentage;
} }
public function installDocker() public function installDocker()
{ {
$activity = resolve(InstallDocker::class)($this->server, session('currentTeam')); $activity = resolve(InstallDocker::class)($this->server, session('currentTeam'));
$this->emit('newMonitorActivity', $activity->id); $this->emit('newMonitorActivity', $activity->id);
} }
public function validateServer() public function validateServer()
{ {
try { try {
@ -59,6 +61,7 @@ public function validateServer()
return general_error_handler(customErrorMessage: "Server is not reachable. Reason: {$e->getMessage()}", that: $this); return general_error_handler(customErrorMessage: "Server is not reachable. Reason: {$e->getMessage()}", that: $this);
} }
} }
public function delete() public function delete()
{ {
if (!$this->server->isEmpty()) { if (!$this->server->isEmpty()) {
@ -68,6 +71,7 @@ public function delete()
$this->server->delete(); $this->server->delete();
redirect()->route('server.all'); redirect()->route('server.all');
} }
public function submit() public function submit()
{ {
$this->validate(); $this->validate();
@ -88,4 +92,4 @@ public function submit()
$this->server->save(); $this->server->save();
$this->emit('success', 'Server updated successfully.'); $this->emit('success', 'Server updated successfully.');
} }
} }

View File

@ -2,7 +2,6 @@
namespace App\Http\Livewire\Server\New; namespace App\Http\Livewire\Server\New;
use App\Models\PrivateKey;
use App\Models\Server; use App\Models\Server;
use Livewire\Component; use Livewire\Component;
@ -35,19 +34,23 @@ class ByIp extends Component
'user' => 'user', 'user' => 'user',
'port' => 'port', 'port' => 'port',
]; ];
public function mount() public function mount()
{ {
$this->name = generate_random_name(); $this->name = generate_random_name();
$this->private_key_id = $this->private_keys->first()->id; $this->private_key_id = $this->private_keys->first()->id;
} }
public function setPrivateKey(string $private_key_id) public function setPrivateKey(string $private_key_id)
{ {
$this->private_key_id = $private_key_id; $this->private_key_id = $private_key_id;
} }
public function instantSave() public function instantSave()
{ {
$this->emit('success', 'Application settings updated!'); $this->emit('success', 'Application settings updated!');
} }
public function submit() public function submit()
{ {
$this->validate(); $this->validate();

View File

@ -3,7 +3,6 @@
namespace App\Http\Livewire\Server; namespace App\Http\Livewire\Server;
use App\Models\Server; use App\Models\Server;
use Illuminate\Support\Facades\Storage;
use Livewire\Component; use Livewire\Component;
use Masmerise\Toaster\Toaster; use Masmerise\Toaster\Toaster;
@ -13,6 +12,16 @@ class PrivateKey extends Component
public $privateKeys; public $privateKeys;
public $parameters; public $parameters;
public function setPrivateKey($private_key_id)
{
$this->server->update([
'private_key_id' => $private_key_id
]);
refreshPrivateKey($this->server->privateKey);
$this->server->refresh();
$this->checkConnection();
}
public function checkConnection() public function checkConnection()
{ {
try { try {
@ -27,15 +36,7 @@ public function checkConnection()
return general_error_handler(customErrorMessage: "Server is not reachable. Reason: {$e->getMessage()}", that: $this); return general_error_handler(customErrorMessage: "Server is not reachable. Reason: {$e->getMessage()}", that: $this);
} }
} }
public function setPrivateKey($private_key_id)
{
$this->server->update([
'private_key_id' => $private_key_id
]);
refreshPrivateKey($this->server->privateKey);
$this->server->refresh();
$this->checkConnection();
}
public function mount() public function mount()
{ {
$this->parameters = getRouteParameters(); $this->parameters = getRouteParameters();

View File

@ -5,7 +5,6 @@
use App\Actions\Proxy\CheckConfigurationSync; use App\Actions\Proxy\CheckConfigurationSync;
use App\Actions\Proxy\SaveConfigurationSync; use App\Actions\Proxy\SaveConfigurationSync;
use App\Enums\ProxyTypes; use App\Enums\ProxyTypes;
use Illuminate\Support\Str;
use App\Models\Server; use App\Models\Server;
use Livewire\Component; use Livewire\Component;
@ -17,21 +16,25 @@ class Proxy extends Component
public $proxy_settings = null; public $proxy_settings = null;
public string|null $redirect_url = null; public string|null $redirect_url = null;
protected $listeners = ['proxyStatusUpdated', 'saveConfiguration'=>'submit']; protected $listeners = ['proxyStatusUpdated', 'saveConfiguration' => 'submit'];
public function mount() public function mount()
{ {
$this->redirect_url = $this->server->proxy->redirect_url; $this->redirect_url = $this->server->proxy->redirect_url;
} }
public function proxyStatusUpdated() public function proxyStatusUpdated()
{ {
$this->server->refresh(); $this->server->refresh();
} }
public function change_proxy() public function change_proxy()
{ {
$this->server->proxy = null; $this->server->proxy = null;
$this->server->save(); $this->server->save();
$this->emit('proxyStatusUpdated'); $this->emit('proxyStatusUpdated');
} }
public function select_proxy(string $proxy_type) public function select_proxy(string $proxy_type)
{ {
$this->server->proxy->type = $proxy_type; $this->server->proxy->type = $proxy_type;
@ -39,6 +42,7 @@ public function select_proxy(string $proxy_type)
$this->server->save(); $this->server->save();
$this->emit('proxyStatusUpdated'); $this->emit('proxyStatusUpdated');
} }
public function submit() public function submit()
{ {
try { try {
@ -53,6 +57,7 @@ public function submit()
return general_error_handler(err: $e); return general_error_handler(err: $e);
} }
} }
public function reset_proxy_configuration() public function reset_proxy_configuration()
{ {
try { try {
@ -61,6 +66,7 @@ public function reset_proxy_configuration()
return general_error_handler(err: $e); return general_error_handler(err: $e);
} }
} }
public function load_proxy_configuration() public function load_proxy_configuration()
{ {
try { try {
@ -69,4 +75,4 @@ public function load_proxy_configuration()
return general_error_handler(err: $e); return general_error_handler(err: $e);
} }
} }
} }

View File

@ -5,12 +5,12 @@
use App\Actions\Proxy\StartProxy; use App\Actions\Proxy\StartProxy;
use App\Models\Server; use App\Models\Server;
use Livewire\Component; use Livewire\Component;
use Str;
class Deploy extends Component class Deploy extends Component
{ {
public Server $server; public Server $server;
public $proxy_settings = null; public $proxy_settings = null;
public function start_proxy() public function start_proxy()
{ {
if ( if (
@ -22,6 +22,7 @@ public function start_proxy()
$activity = resolve(StartProxy::class)($this->server); $activity = resolve(StartProxy::class)($this->server);
$this->emit('newMonitorActivity', $activity->id); $this->emit('newMonitorActivity', $activity->id);
} }
public function stop() public function stop()
{ {
instant_remote_process([ instant_remote_process([
@ -31,4 +32,4 @@ public function stop()
$this->server->save(); $this->server->save();
$this->emit('proxyStatusUpdated'); $this->emit('proxyStatusUpdated');
} }
} }

View File

@ -9,6 +9,7 @@
class Status extends Component class Status extends Component
{ {
public Server $server; public Server $server;
public function get_status() public function get_status()
{ {
dispatch_sync(new ProxyContainerStatusJob( dispatch_sync(new ProxyContainerStatusJob(
@ -17,4 +18,4 @@ public function get_status()
$this->server->refresh(); $this->server->refresh();
$this->emit('proxyStatusUpdated'); $this->emit('proxyStatusUpdated');
} }
} }

View File

@ -31,6 +31,7 @@ class Configuration extends Component
'settings.public_port_min' => 'Public port min', 'settings.public_port_min' => 'Public port min',
'settings.public_port_max' => 'Public port max', 'settings.public_port_max' => 'Public port max',
]; ];
public function mount() public function mount()
{ {
$this->do_not_track = $this->settings->do_not_track; $this->do_not_track = $this->settings->do_not_track;
@ -38,6 +39,7 @@ public function mount()
$this->is_registration_enabled = $this->settings->is_registration_enabled; $this->is_registration_enabled = $this->settings->is_registration_enabled;
$this->next_channel = $this->settings->next_channel; $this->next_channel = $this->settings->next_channel;
} }
public function instantSave() public function instantSave()
{ {
$this->settings->do_not_track = $this->do_not_track; $this->settings->do_not_track = $this->do_not_track;
@ -47,6 +49,21 @@ public function instantSave()
$this->settings->save(); $this->settings->save();
$this->emit('success', 'Settings updated!'); $this->emit('success', 'Settings updated!');
} }
public function submit()
{
$this->resetErrorBag();
if ($this->settings->public_port_min > $this->settings->public_port_max) {
$this->addError('settings.public_port_min', 'The minimum port must be lower than the maximum port.');
return;
}
$this->validate();
$this->settings->save();
$this->server = Server::findOrFail(0);
$this->setup_instance_fqdn();
$this->emit('success', 'Instance settings updated successfully!');
}
private function setup_instance_fqdn() private function setup_instance_fqdn()
{ {
$file = "$this->dynamic_config_path/coolify.yaml"; $file = "$this->dynamic_config_path/coolify.yaml";
@ -60,35 +77,35 @@ private function setup_instance_fqdn()
$schema = $url->getScheme(); $schema = $url->getScheme();
$traefik_dynamic_conf = [ $traefik_dynamic_conf = [
'http' => 'http' =>
[
'routers' =>
[ [
'coolify-http' => 'routers' =>
[
'entryPoints' => [
0 => 'http',
],
'service' => 'coolify',
'rule' => "Host(`{$host}`)",
],
],
'services' =>
[
'coolify' =>
[
'loadBalancer' =>
[ [
'servers' => 'coolify-http' =>
[
0 =>
[ [
'url' => 'http://coolify:80', 'entryPoints' => [
0 => 'http',
],
'service' => 'coolify',
'rule' => "Host(`{$host}`)",
],
],
'services' =>
[
'coolify' =>
[
'loadBalancer' =>
[
'servers' =>
[
0 =>
[
'url' => 'http://coolify:80',
],
],
],
], ],
],
], ],
],
], ],
],
]; ];
if ($schema === 'https') { if ($schema === 'https') {
@ -110,6 +127,7 @@ private function setup_instance_fqdn()
dispatch(new ProxyStartJob($this->server)); dispatch(new ProxyStartJob($this->server));
} }
} }
private function save_configuration_to_disk(array $traefik_dynamic_conf, string $file) private function save_configuration_to_disk(array $traefik_dynamic_conf, string $file)
{ {
$yaml = Yaml::dump($traefik_dynamic_conf, 12, 2); $yaml = Yaml::dump($traefik_dynamic_conf, 12, 2);
@ -128,17 +146,4 @@ private function save_configuration_to_disk(array $traefik_dynamic_conf, string
ray($yaml); ray($yaml);
} }
} }
public function submit()
{
$this->resetErrorBag();
if ($this->settings->public_port_min > $this->settings->public_port_max) {
$this->addError('settings.public_port_min', 'The minimum port must be lower than the maximum port.');
return;
}
$this->validate();
$this->settings->save();
$this->server = Server::findOrFail(0);
$this->setup_instance_fqdn();
$this->emit('success', 'Instance settings updated successfully!');
}
} }

View File

@ -4,7 +4,6 @@
use App\Models\InstanceSettings; use App\Models\InstanceSettings;
use App\Notifications\TransactionalEmails\Test; use App\Notifications\TransactionalEmails\Test;
use Illuminate\Support\Facades\Notification;
use Livewire\Component; use Livewire\Component;
class Email extends Component class Email extends Component
@ -32,11 +31,23 @@ class Email extends Component
'settings.smtp_username' => 'Username', 'settings.smtp_username' => 'Username',
'settings.smtp_password' => 'Password', 'settings.smtp_password' => 'Password',
]; ];
public function mount() public function mount()
{ {
$this->decrypt(); $this->decrypt();
$this->emails = auth()->user()->email; $this->emails = auth()->user()->email;
} }
private function decrypt()
{
if (data_get($this->settings, 'smtp_password')) {
try {
$this->settings->smtp_password = decrypt($this->settings->smtp_password);
} catch (\Exception $e) {
}
}
}
public function instantSave() public function instantSave()
{ {
try { try {
@ -47,20 +58,7 @@ public function instantSave()
$this->validate(); $this->validate();
} }
} }
public function sendTestNotification()
{
$this->settings->notify(new Test($this->emails));
$this->emit('success', 'Test email sent.');
}
private function decrypt()
{
if (data_get($this->settings, 'smtp_password')) {
try {
$this->settings->smtp_password = decrypt($this->settings->smtp_password);
} catch (\Exception $e) {
}
}
}
public function submit() public function submit()
{ {
$this->resetErrorBag(); $this->resetErrorBag();
@ -75,4 +73,10 @@ public function submit()
$this->emit('success', 'Transaction email settings updated successfully.'); $this->emit('success', 'Transaction email settings updated successfully.');
$this->decrypt(); $this->decrypt();
} }
}
public function sendTestNotification()
{
$this->settings->notify(new Test($this->emails));
$this->emit('success', 'Test email sent.');
}
}

View File

@ -34,12 +34,14 @@ class Change extends Component
'github_app.webhook_secret' => 'nullable', 'github_app.webhook_secret' => 'nullable',
'github_app.is_system_wide' => 'required|bool', 'github_app.is_system_wide' => 'required|bool',
]; ];
public function mount() public function mount()
{ {
$this->webhook_endpoint = $this->ipv4; $this->webhook_endpoint = $this->ipv4;
$this->parameters = getRouteParameters(); $this->parameters = getRouteParameters();
$this->is_system_wide = $this->github_app->is_system_wide; $this->is_system_wide = $this->github_app->is_system_wide;
} }
public function submit() public function submit()
{ {
try { try {
@ -49,6 +51,7 @@ public function submit()
return general_error_handler(err: $e, that: $this); return general_error_handler(err: $e, that: $this);
} }
} }
public function instantSave() public function instantSave()
{ {
} }

View File

@ -19,6 +19,7 @@ public function mount()
{ {
$this->name = generate_random_name(); $this->name = generate_random_name();
} }
public function createGitHubApp() public function createGitHubApp()
{ {
try { try {

View File

@ -8,10 +8,12 @@
class SwitchTeam extends Component class SwitchTeam extends Component
{ {
public string $selectedTeamId = 'default'; public string $selectedTeamId = 'default';
public function updatedSelectedTeamId() public function updatedSelectedTeamId()
{ {
$this->switch_to($this->selectedTeamId); $this->switch_to($this->selectedTeamId);
} }
public function switch_to($team_id) public function switch_to($team_id)
{ {
if (!auth()->user()->teams->contains($team_id)) { if (!auth()->user()->teams->contains($team_id)) {

View File

@ -18,6 +18,7 @@ class Create extends Component
'name' => 'name', 'name' => 'name',
'description' => 'description', 'description' => 'description',
]; ];
public function submit() public function submit()
{ {
$this->validate(); $this->validate();

View File

@ -4,7 +4,6 @@
use App\Models\Team; use App\Models\Team;
use Livewire\Component; use Livewire\Component;
use Masmerise\Toaster\Toaster;
class Form extends Component class Form extends Component
{ {
@ -17,10 +16,12 @@ class Form extends Component
'team.name' => 'name', 'team.name' => 'name',
'team.description' => 'description', 'team.description' => 'description',
]; ];
public function mount() public function mount()
{ {
$this->team = session('currentTeam'); $this->team = session('currentTeam');
} }
public function submit() public function submit()
{ {
$this->validate(); $this->validate();

View File

@ -9,13 +9,15 @@ class Invitations extends Component
{ {
public $invitations; public $invitations;
protected $listeners = ['refreshInvitations']; protected $listeners = ['refreshInvitations'];
public function refreshInvitations()
{
$this->invitations = TeamInvitation::whereTeamId(auth()->user()->currentTeam()->id)->get();
}
public function deleteInvitation(int $invitation_id) public function deleteInvitation(int $invitation_id)
{ {
TeamInvitation::find($invitation_id)->delete(); TeamInvitation::find($invitation_id)->delete();
$this->refreshInvitations(); $this->refreshInvitations();
} }
public function refreshInvitations()
{
$this->invitations = TeamInvitation::whereTeamId(auth()->user()->currentTeam()->id)->get();
}
} }

View File

@ -12,14 +12,17 @@ class InviteLink extends Component
{ {
public string $email; public string $email;
public string $role = 'member'; public string $role = 'member';
public function mount() public function mount()
{ {
$this->email = isDev() ? 'test3@example.com' : ''; $this->email = isDev() ? 'test3@example.com' : '';
} }
public function viaEmail() public function viaEmail()
{ {
$this->generate_invite_link(isEmail: true); $this->generate_invite_link(isEmail: true);
} }
private function generate_invite_link(bool $isEmail = false) private function generate_invite_link(bool $isEmail = false)
{ {
try { try {
@ -72,8 +75,9 @@ private function generate_invite_link(bool $isEmail = false)
return general_error_handler(err: $e, that: $this, customErrorMessage: $error_message); return general_error_handler(err: $e, that: $this, customErrorMessage: $error_message);
} }
} }
public function viaLink() public function viaLink()
{ {
$this->generate_invite_link(); $this->generate_invite_link();
} }
} }

View File

@ -8,16 +8,19 @@
class Member extends Component class Member extends Component
{ {
public User $member; public User $member;
public function makeAdmin() public function makeAdmin()
{ {
$this->member->teams()->updateExistingPivot(session('currentTeam')->id, ['role' => 'admin']); $this->member->teams()->updateExistingPivot(session('currentTeam')->id, ['role' => 'admin']);
$this->emit('reloadWindow'); $this->emit('reloadWindow');
} }
public function makeReadonly() public function makeReadonly()
{ {
$this->member->teams()->updateExistingPivot(session('currentTeam')->id, ['role' => 'member']); $this->member->teams()->updateExistingPivot(session('currentTeam')->id, ['role' => 'member']);
$this->emit('reloadWindow'); $this->emit('reloadWindow');
} }
public function remove() public function remove()
{ {
$this->member->teams()->detach(session('currentTeam')); $this->member->teams()->detach(session('currentTeam'));

View File

@ -2,8 +2,8 @@
namespace App\Http\Livewire\Team\Storage; namespace App\Http\Livewire\Team\Storage;
use Livewire\Component;
use App\Models\S3Storage; use App\Models\S3Storage;
use Livewire\Component;
class Create extends Component class Create extends Component
{ {
@ -33,7 +33,9 @@ class Create extends Component
'bucket' => 'Bucket', 'bucket' => 'Bucket',
'endpoint' => 'Endpoint', 'endpoint' => 'Endpoint',
]; ];
public function mount() {
public function mount()
{
if (isDev()) { if (isDev()) {
$this->name = 'Local MinIO'; $this->name = 'Local MinIO';
$this->description = 'Local MinIO'; $this->description = 'Local MinIO';
@ -43,15 +45,9 @@ public function mount() {
$this->endpoint = 'http://coolify-minio:9000'; $this->endpoint = 'http://coolify-minio:9000';
} }
} }
private function test_s3_connection() {
try { public function submit()
$this->storage->testConnection(); {
return $this->emit('success', 'Connection is working. Tested with "ListObjectsV2" action.');
} catch(\Throwable $th) {
return general_error_handler($th, $this);
}
}
public function submit() {
try { try {
$this->validate(); $this->validate();
$this->storage = new S3Storage(); $this->storage = new S3Storage();
@ -71,9 +67,19 @@ public function submit() {
$this->emit('success', 'Connection is working. Tested with "ListObjectsV2" action.'); $this->emit('success', 'Connection is working. Tested with "ListObjectsV2" action.');
$this->storage->save(); $this->storage->save();
return redirect()->route('team.storages.show', $this->storage->uuid); return redirect()->route('team.storages.show', $this->storage->uuid);
} catch(\Throwable $th) { } catch (\Throwable $th) {
return general_error_handler($th, $this); return general_error_handler($th, $this);
} }
} }
}
private function test_s3_connection()
{
try {
$this->storage->testConnection();
return $this->emit('success', 'Connection is working. Tested with "ListObjectsV2" action.');
} catch (\Throwable $th) {
return general_error_handler($th, $this);
}
}
}

View File

@ -2,8 +2,8 @@
namespace App\Http\Livewire\Team\Storage; namespace App\Http\Livewire\Team\Storage;
use Livewire\Component;
use App\Models\S3Storage; use App\Models\S3Storage;
use Livewire\Component;
class Form extends Component class Form extends Component
{ {
@ -26,22 +26,27 @@ class Form extends Component
'storage.bucket' => 'Bucket', 'storage.bucket' => 'Bucket',
'storage.endpoint' => 'Endpoint', 'storage.endpoint' => 'Endpoint',
]; ];
public function test_s3_connection() {
public function test_s3_connection()
{
try { try {
$this->storage->testConnection(); $this->storage->testConnection();
return $this->emit('success', 'Connection is working. Tested with "ListObjectsV2" action.'); return $this->emit('success', 'Connection is working. Tested with "ListObjectsV2" action.');
} catch(\Throwable $th) { } catch (\Throwable $th) {
return general_error_handler($th, $this); return general_error_handler($th, $this);
} }
} }
public function delete() {
public function delete()
{
try { try {
$this->storage->delete(); $this->storage->delete();
return redirect()->route('team.storages.all'); return redirect()->route('team.storages.all');
} catch(\Throwable $th) { } catch (\Throwable $th) {
return general_error_handler($th, $this); return general_error_handler($th, $this);
} }
} }
public function submit() public function submit()
{ {
$this->validate(); $this->validate();
@ -54,4 +59,4 @@ public function submit()
return general_error_handler($th, $this); return general_error_handler($th, $this);
} }
} }
} }

View File

@ -4,8 +4,8 @@
use App\Actions\Server\UpdateCoolify; use App\Actions\Server\UpdateCoolify;
use App\Models\InstanceSettings; use App\Models\InstanceSettings;
use Masmerise\Toaster\Toaster;
use Livewire\Component; use Livewire\Component;
use Masmerise\Toaster\Toaster;
class Upgrade extends Component class Upgrade extends Component
{ {
@ -27,6 +27,7 @@ public function checkUpdate()
$this->latestVersion = 'next'; $this->latestVersion = 'next';
} }
} }
public function upgrade() public function upgrade()
{ {
try { try {
@ -40,4 +41,4 @@ public function upgrade()
return general_error_handler(err: $e, that: $this); return general_error_handler(err: $e, that: $this);
} }
} }
} }

View File

@ -13,7 +13,7 @@ class RedirectIfAuthenticated
/** /**
* Handle an incoming request. * Handle an incoming request.
* *
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next * @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/ */
public function handle(Request $request, Closure $next, string ...$guards): Response public function handle(Request $request, Closure $next, string ...$guards): Response
{ {

View File

@ -20,7 +20,7 @@ class TrustProxies extends Middleware
* @var int * @var int
*/ */
protected $headers = protected $headers =
Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_FOR |
Request::HEADER_X_FORWARDED_HOST | Request::HEADER_X_FORWARDED_HOST |
Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PORT |
Request::HEADER_X_FORWARDED_PROTO | Request::HEADER_X_FORWARDED_PROTO |

View File

@ -12,8 +12,8 @@
use App\Models\Server; use App\Models\Server;
use App\Models\StandaloneDocker; use App\Models\StandaloneDocker;
use App\Models\SwarmDocker; use App\Models\SwarmDocker;
use App\Notifications\Application\DeploymentSuccess;
use App\Notifications\Application\DeploymentFailed; use App\Notifications\Application\DeploymentFailed;
use App\Notifications\Application\DeploymentSuccess;
use App\Traits\ExecuteRemoteCommand; use App\Traits\ExecuteRemoteCommand;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
@ -22,8 +22,8 @@
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Spatie\Url\Url;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Spatie\Url\Url;
use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Yaml;
use Throwable; use Throwable;
use Visus\Cuid2\Cuid2; use Visus\Cuid2\Cuid2;
@ -61,6 +61,7 @@ class ApplicationDeploymentJob implements ShouldQueue
private $log_model; private $log_model;
private Collection $saved_outputs; private Collection $saved_outputs;
public function __construct(int $application_deployment_queue_id) public function __construct(int $application_deployment_queue_id)
{ {
ray()->clearScreen(); ray()->clearScreen();
@ -137,62 +138,7 @@ public function handle(): void
// ray()->measure(); // ray()->measure();
} }
} }
public function failed(Throwable $exception): void
{
$this->execute_remote_command(
["echo 'Oops something is not okay, are you okay? 😢'"],
["echo '{$exception->getMessage()}'"]
);
$this->next(ApplicationDeploymentStatus::FAILED->value);
}
private function execute_in_builder(string $command)
{
return "docker exec {$this->deployment_uuid} bash -c '{$command}'";
// return "docker exec {$this->deployment_uuid} bash -c '{$command} |& tee -a /proc/1/fd/1; [ \$PIPESTATUS -eq 0 ] || exit \$PIPESTATUS'";
}
private function deploy()
{
$this->execute_remote_command(
[
"echo 'Starting deployment of {$this->application->git_repository}:{$this->application->git_branch}.'"
],
);
$this->prepare_builder_image();
$this->clone_repository();
$tag = Str::of("{$this->commit}-{$this->application->id}-{$this->pull_request_id}");
if (strlen($tag) > 128) {
$tag = $tag->substr(0, 128);
};
$this->build_image_name = "{$this->application->git_repository}:{$tag}-build";
$this->production_image_name = "{$this->application->uuid}:{$tag}";
ray('Build Image Name: ' . $this->build_image_name . ' & Production Image Name: ' . $this->production_image_name)->green();
if (!$this->force_rebuild) {
$this->execute_remote_command([
"docker images -q {$this->production_image_name} 2>/dev/null", "hidden" => true, "save" => "local_image_found"
]);
if (Str::of($this->saved_outputs->get('local_image_found'))->isNotEmpty()) {
$this->execute_remote_command([
"echo 'Docker Image found locally with the same Git Commit SHA {$this->application->uuid}:{$this->commit}. Build step skipped...'"
]);
$this->generate_compose_file();
$this->stop_running_container();
$this->start_by_compose_file();
return;
}
}
$this->cleanup_git();
$this->generate_buildpack();
$this->generate_compose_file();
$this->generate_build_env_variables();
$this->add_build_env_variables_to_dockerfile();
$this->build_image();
$this->stop_running_container();
$this->start_by_compose_file();
}
private function deploy_pull_request() private function deploy_pull_request()
{ {
$this->build_image_name = "{$this->application->uuid}:pr-{$this->pull_request_id}-build"; $this->build_image_name = "{$this->application->uuid}:pr-{$this->pull_request_id}-build";
@ -214,117 +160,154 @@ private function deploy_pull_request()
$this->start_by_compose_file(); $this->start_by_compose_file();
} }
private function next(string $status) private function prepare_builder_image()
{
// If the deployment is cancelled by the user, don't update the status
if ($this->application_deployment_queue->status !== ApplicationDeploymentStatus::CANCELLED_BY_USER->value) {
$this->application_deployment_queue->update([
'status' => $status,
]);
}
queue_next_deployment($this->application);
if ($status === ApplicationDeploymentStatus::FINISHED->value) {
$this->application->environment->project->team->notify(new DeploymentSuccess($this->application, $this->deployment_uuid, $this->preview));
}
if ($status === ApplicationDeploymentStatus::FAILED->value) {
$this->application->environment->project->team->notify(new DeploymentFailed($this->application, $this->deployment_uuid, $this->preview));
}
}
private function start_by_compose_file()
{ {
$this->execute_remote_command( $this->execute_remote_command(
["echo -n 'Starting new application... '"], [
[$this->execute_in_builder("docker compose --project-directory {$this->workdir} up -d >/dev/null"), "hidden" => true], "echo -n 'Pulling latest version of the builder image (ghcr.io/coollabsio/coolify-builder).'",
["echo 'Done. 🎉'"], ],
[
"docker run --pull=always -d --name {$this->deployment_uuid} --rm -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/coollabsio/coolify-builder",
"hidden" => true,
],
[
"command" => $this->execute_in_builder("mkdir -p {$this->workdir}")
],
); );
} }
private function stop_running_container()
private function execute_in_builder(string $command)
{
return "docker exec {$this->deployment_uuid} bash -c '{$command}'";
// return "docker exec {$this->deployment_uuid} bash -c '{$command} |& tee -a /proc/1/fd/1; [ \$PIPESTATUS -eq 0 ] || exit \$PIPESTATUS'";
}
private function clone_repository()
{ {
$this->execute_remote_command( $this->execute_remote_command(
["echo -n 'Removing old running application.'"], [
[$this->execute_in_builder("docker rm -f $this->container_name >/dev/null 2>&1"), "hidden" => true], "echo -n 'Importing {$this->application->git_repository}:{$this->application->git_branch} to {$this->workdir}. '"
],
[
$this->importing_git_repository()
],
[
$this->execute_in_builder("cd {$this->workdir} && git rev-parse HEAD"),
"hidden" => true,
"save" => "git_commit_sha"
],
);
$this->commit = $this->saved_outputs->get('git_commit_sha');
}
private function importing_git_repository()
{
$commands = collect([]);
$git_clone_command = "git clone -q -b {$this->application->git_branch}";
if ($this->pull_request_id !== 0) {
$pr_branch_name = "pr-{$this->pull_request_id}-coolify";
}
if ($this->application->deploymentType() === 'source') {
$source_html_url = data_get($this->application, 'source.html_url');
$url = parse_url(filter_var($source_html_url, FILTER_SANITIZE_URL));
$source_html_url_host = $url['host'];
$source_html_url_scheme = $url['scheme'];
if ($this->source->getMorphClass() == 'App\Models\GithubApp') {
if ($this->source->is_public) {
$git_clone_command = "{$git_clone_command} {$this->source->html_url}/{$this->application->git_repository} {$this->workdir}";
$git_clone_command = $this->set_git_import_settings($git_clone_command);
$commands->push($this->execute_in_builder($git_clone_command));
} else {
$github_access_token = generate_github_installation_token($this->source);
$commands->push($this->execute_in_builder("git clone -q -b {$this->application->git_branch} $source_html_url_scheme://x-access-token:$github_access_token@$source_html_url_host/{$this->application->git_repository}.git {$this->workdir}"));
}
if ($this->pull_request_id !== 0) {
$commands->push($this->execute_in_builder("cd {$this->workdir} && git fetch origin pull/{$this->pull_request_id}/head:$pr_branch_name && git checkout $pr_branch_name"));
}
return $commands->implode(' && ');
}
}
if ($this->application->deploymentType() === 'deploy_key') {
$private_key = base64_encode($this->application->private_key->private_key);
$git_clone_command = "GIT_SSH_COMMAND=\"ssh -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" {$git_clone_command} {$this->application->git_full_url} {$this->workdir}";
$git_clone_command = $this->set_git_import_settings($git_clone_command);
$commands = collect([
$this->execute_in_builder("mkdir -p /root/.ssh"),
$this->execute_in_builder("echo '{$private_key}' | base64 -d > /root/.ssh/id_rsa"),
$this->execute_in_builder("chmod 600 /root/.ssh/id_rsa"),
$this->execute_in_builder($git_clone_command)
]);
return $commands->implode(' && ');
}
}
private function set_git_import_settings($git_clone_command)
{
if ($this->application->git_commit_sha !== 'HEAD') {
$git_clone_command = "{$git_clone_command} && cd {$this->workdir} && git -c advice.detachedHead=false checkout {$this->application->git_commit_sha} >/dev/null 2>&1";
}
if ($this->application->settings->is_git_submodules_enabled) {
$git_clone_command = "{$git_clone_command} && cd {$this->workdir} && git submodule update --init --recursive";
}
if ($this->application->settings->is_git_lfs_enabled) {
$git_clone_command = "{$git_clone_command} && cd {$this->workdir} && git lfs pull";
}
return $git_clone_command;
}
private function cleanup_git()
{
$this->execute_remote_command(
[$this->execute_in_builder("rm -fr {$this->workdir}/.git")],
); );
} }
private function build_image()
private function generate_buildpack()
{ {
$this->execute_remote_command([ $this->execute_remote_command(
"echo -n 'Building docker image.'", [
]); "echo -n 'Generating nixpacks configuration.'",
],
if ($this->application->settings->is_static) { [$this->nixpacks_build_cmd()],
$this->execute_remote_command([ [$this->execute_in_builder("cp {$this->workdir}/.nixpacks/Dockerfile {$this->workdir}/Dockerfile")],
$this->execute_in_builder("docker build -f {$this->workdir}/Dockerfile {$this->build_args} --progress plain -t $this->build_image_name {$this->workdir}"), "hidden" => true [$this->execute_in_builder("rm -f {$this->workdir}/.nixpacks/Dockerfile")]
]); );
$dockerfile = base64_encode("FROM {$this->application->static_image}
WORKDIR /usr/share/nginx/html/
LABEL coolify.deploymentId={$this->deployment_uuid}
COPY --from=$this->build_image_name /app/{$this->application->publish_directory} .
COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
$nginx_config = base64_encode("server {
listen 80;
listen [::]:80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html;
try_files \$uri \$uri.html \$uri/index.html \$uri/ /index.html =404;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}");
$this->execute_remote_command(
[
$this->execute_in_builder("echo '{$dockerfile}' | base64 -d > {$this->workdir}/Dockerfile-prod")
],
[
$this->execute_in_builder("echo '{$nginx_config}' | base64 -d > {$this->workdir}/nginx.conf")
],
[
$this->execute_in_builder("docker build -f {$this->workdir}/Dockerfile-prod {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true
]
);
} else {
$this->execute_remote_command([
$this->execute_in_builder("docker build -f {$this->workdir}/Dockerfile {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true
]);
}
} }
private function add_build_env_variables_to_dockerfile()
{
$this->execute_remote_command([
$this->execute_in_builder("cat {$this->workdir}/Dockerfile"), "hidden" => true, "save" => 'dockerfile'
]);
$dockerfile = collect(Str::of($this->saved_outputs->get('dockerfile'))->trim()->explode("\n"));
foreach ($this->application->build_environment_variables as $env) { private function nixpacks_build_cmd()
$dockerfile->splice(1, 0, "ARG {$env->key}={$env->value}");
}
$dockerfile_base64 = base64_encode($dockerfile->implode("\n"));
$this->execute_remote_command([
$this->execute_in_builder("echo '{$dockerfile_base64}' | base64 -d > {$this->workdir}/Dockerfile"),
"hidden" => true
]);
}
private function generate_build_env_variables()
{ {
$this->build_args = collect(["--build-arg SOURCE_COMMIT={$this->commit}"]); $this->generate_env_variables();
$nixpacks_command = "nixpacks build -o {$this->workdir} {$this->env_args} --no-error-without-start";
if ($this->application->build_command) {
$nixpacks_command .= " --build-cmd \"{$this->application->build_command}\"";
}
if ($this->application->start_command) {
$nixpacks_command .= " --start-cmd \"{$this->application->start_command}\"";
}
if ($this->application->install_command) {
$nixpacks_command .= " --install-cmd \"{$this->application->install_command}\"";
}
$nixpacks_command .= " {$this->workdir}";
return $this->execute_in_builder($nixpacks_command);
}
private function generate_env_variables()
{
$this->env_args = collect([]);
if ($this->pull_request_id === 0) { if ($this->pull_request_id === 0) {
foreach ($this->application->build_environment_variables as $env) { foreach ($this->application->nixpacks_environment_variables as $env) {
$this->build_args->push("--build-arg {$env->key}={$env->value}"); $this->env_args->push("--env {$env->key}={$env->value}");
} }
} else { } else {
foreach ($this->application->build_environment_variables_preview as $env) { foreach ($this->application->nixpacks_environment_variables_preview as $env) {
$this->build_args->push("--build-arg {$env->key}={$env->value}"); $this->env_args->push("--env {$env->key}={$env->value}");
} }
} }
$this->build_args = $this->build_args->implode(' '); $this->env_args = $this->env_args->implode(' ');
} }
private function generate_compose_file() private function generate_compose_file()
@ -388,6 +371,7 @@ private function generate_compose_file()
$docker_compose_base64 = base64_encode($this->docker_compose); $docker_compose_base64 = base64_encode($this->docker_compose);
$this->execute_remote_command([$this->execute_in_builder("echo '{$docker_compose_base64}' | base64 -d > {$this->workdir}/docker-compose.yml"), "hidden" => true]); $this->execute_remote_command([$this->execute_in_builder("echo '{$docker_compose_base64}' | base64 -d > {$this->workdir}/docker-compose.yml"), "hidden" => true]);
} }
private function generate_local_persistent_volumes() private function generate_local_persistent_volumes()
{ {
$local_persistent_volumes = []; $local_persistent_volumes = [];
@ -400,6 +384,7 @@ private function generate_local_persistent_volumes()
} }
return $local_persistent_volumes; return $local_persistent_volumes;
} }
private function generate_local_persistent_volumes_only_volume_names() private function generate_local_persistent_volumes_only_volume_names()
{ {
$local_persistent_volumes_names = []; $local_persistent_volumes_names = [];
@ -420,6 +405,7 @@ private function generate_local_persistent_volumes_only_volume_names()
} }
return $local_persistent_volumes_names; return $local_persistent_volumes_names;
} }
private function generate_environment_variables($ports) private function generate_environment_variables($ports)
{ {
$environment_variables = collect(); $environment_variables = collect();
@ -436,27 +422,12 @@ private function generate_environment_variables($ports)
} }
} }
// Add PORT if not exists, use the first port as default // Add PORT if not exists, use the first port as default
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('PORT'))->isEmpty()) { if ($environment_variables->filter(fn($env) => Str::of($env)->contains('PORT'))->isEmpty()) {
$environment_variables->push("PORT={$ports[0]}"); $environment_variables->push("PORT={$ports[0]}");
} }
return $environment_variables->all(); return $environment_variables->all();
} }
private function generate_healthcheck_commands()
{
if (!$this->application->health_check_port) {
$this->application->health_check_port = $this->application->ports_exposes_array[0];
}
if ($this->application->health_check_path) {
$generated_healthchecks_commands = [
"curl -s -X {$this->application->health_check_method} -f {$this->application->health_check_scheme}://{$this->application->health_check_host}:{$this->application->health_check_port}{$this->application->health_check_path} > /dev/null"
];
} else {
$generated_healthchecks_commands = [
"curl -s -X {$this->application->health_check_method} -f {$this->application->health_check_scheme}://{$this->application->health_check_host}:{$this->application->health_check_port}/"
];
}
return implode(' ', $generated_healthchecks_commands);
}
private function set_labels_for_applications() private function set_labels_for_applications()
{ {
$labels = []; $labels = [];
@ -520,140 +491,192 @@ private function set_labels_for_applications()
} }
return $labels; return $labels;
} }
private function generate_buildpack()
private function generate_healthcheck_commands()
{
if (!$this->application->health_check_port) {
$this->application->health_check_port = $this->application->ports_exposes_array[0];
}
if ($this->application->health_check_path) {
$generated_healthchecks_commands = [
"curl -s -X {$this->application->health_check_method} -f {$this->application->health_check_scheme}://{$this->application->health_check_host}:{$this->application->health_check_port}{$this->application->health_check_path} > /dev/null"
];
} else {
$generated_healthchecks_commands = [
"curl -s -X {$this->application->health_check_method} -f {$this->application->health_check_scheme}://{$this->application->health_check_host}:{$this->application->health_check_port}/"
];
}
return implode(' ', $generated_healthchecks_commands);
}
private function build_image()
{
$this->execute_remote_command([
"echo -n 'Building docker image.'",
]);
if ($this->application->settings->is_static) {
$this->execute_remote_command([
$this->execute_in_builder("docker build -f {$this->workdir}/Dockerfile {$this->build_args} --progress plain -t $this->build_image_name {$this->workdir}"), "hidden" => true
]);
$dockerfile = base64_encode("FROM {$this->application->static_image}
WORKDIR /usr/share/nginx/html/
LABEL coolify.deploymentId={$this->deployment_uuid}
COPY --from=$this->build_image_name /app/{$this->application->publish_directory} .
COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
$nginx_config = base64_encode("server {
listen 80;
listen [::]:80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html;
try_files \$uri \$uri.html \$uri/index.html \$uri/ /index.html =404;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}");
$this->execute_remote_command(
[
$this->execute_in_builder("echo '{$dockerfile}' | base64 -d > {$this->workdir}/Dockerfile-prod")
],
[
$this->execute_in_builder("echo '{$nginx_config}' | base64 -d > {$this->workdir}/nginx.conf")
],
[
$this->execute_in_builder("docker build -f {$this->workdir}/Dockerfile-prod {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true
]
);
} else {
$this->execute_remote_command([
$this->execute_in_builder("docker build -f {$this->workdir}/Dockerfile {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true
]);
}
}
private function stop_running_container()
{ {
$this->execute_remote_command( $this->execute_remote_command(
[ ["echo -n 'Removing old running application.'"],
"echo -n 'Generating nixpacks configuration.'", [$this->execute_in_builder("docker rm -f $this->container_name >/dev/null 2>&1"), "hidden" => true],
],
[$this->nixpacks_build_cmd()],
[$this->execute_in_builder("cp {$this->workdir}/.nixpacks/Dockerfile {$this->workdir}/Dockerfile")],
[$this->execute_in_builder("rm -f {$this->workdir}/.nixpacks/Dockerfile")]
); );
} }
private function nixpacks_build_cmd()
private function start_by_compose_file()
{ {
$this->generate_env_variables(); $this->execute_remote_command(
$nixpacks_command = "nixpacks build -o {$this->workdir} {$this->env_args} --no-error-without-start"; ["echo -n 'Starting new application... '"],
if ($this->application->build_command) { [$this->execute_in_builder("docker compose --project-directory {$this->workdir} up -d >/dev/null"), "hidden" => true],
$nixpacks_command .= " --build-cmd \"{$this->application->build_command}\""; ["echo 'Done. 🎉'"],
} );
if ($this->application->start_command) {
$nixpacks_command .= " --start-cmd \"{$this->application->start_command}\"";
}
if ($this->application->install_command) {
$nixpacks_command .= " --install-cmd \"{$this->application->install_command}\"";
}
$nixpacks_command .= " {$this->workdir}";
return $this->execute_in_builder($nixpacks_command);
} }
private function generate_env_variables()
private function deploy()
{ {
$this->env_args = collect([]);
$this->execute_remote_command(
[
"echo 'Starting deployment of {$this->application->git_repository}:{$this->application->git_branch}.'"
],
);
$this->prepare_builder_image();
$this->clone_repository();
$tag = Str::of("{$this->commit}-{$this->application->id}-{$this->pull_request_id}");
if (strlen($tag) > 128) {
$tag = $tag->substr(0, 128);
};
$this->build_image_name = "{$this->application->git_repository}:{$tag}-build";
$this->production_image_name = "{$this->application->uuid}:{$tag}";
ray('Build Image Name: ' . $this->build_image_name . ' & Production Image Name: ' . $this->production_image_name)->green();
if (!$this->force_rebuild) {
$this->execute_remote_command([
"docker images -q {$this->production_image_name} 2>/dev/null", "hidden" => true, "save" => "local_image_found"
]);
if (Str::of($this->saved_outputs->get('local_image_found'))->isNotEmpty()) {
$this->execute_remote_command([
"echo 'Docker Image found locally with the same Git Commit SHA {$this->application->uuid}:{$this->commit}. Build step skipped...'"
]);
$this->generate_compose_file();
$this->stop_running_container();
$this->start_by_compose_file();
return;
}
}
$this->cleanup_git();
$this->generate_buildpack();
$this->generate_compose_file();
$this->generate_build_env_variables();
$this->add_build_env_variables_to_dockerfile();
$this->build_image();
$this->stop_running_container();
$this->start_by_compose_file();
}
private function generate_build_env_variables()
{
$this->build_args = collect(["--build-arg SOURCE_COMMIT={$this->commit}"]);
if ($this->pull_request_id === 0) { if ($this->pull_request_id === 0) {
foreach ($this->application->nixpacks_environment_variables as $env) { foreach ($this->application->build_environment_variables as $env) {
$this->env_args->push("--env {$env->key}={$env->value}"); $this->build_args->push("--build-arg {$env->key}={$env->value}");
} }
} else { } else {
foreach ($this->application->nixpacks_environment_variables_preview as $env) { foreach ($this->application->build_environment_variables_preview as $env) {
$this->env_args->push("--env {$env->key}={$env->value}"); $this->build_args->push("--build-arg {$env->key}={$env->value}");
} }
} }
$this->env_args = $this->env_args->implode(' '); $this->build_args = $this->build_args->implode(' ');
} }
private function cleanup_git()
{
$this->execute_remote_command(
[$this->execute_in_builder("rm -fr {$this->workdir}/.git")],
);
}
private function prepare_builder_image()
{
$this->execute_remote_command(
[
"echo -n 'Pulling latest version of the builder image (ghcr.io/coollabsio/coolify-builder).'",
],
[
"docker run --pull=always -d --name {$this->deployment_uuid} --rm -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/coollabsio/coolify-builder",
"hidden" => true,
],
[
"command" => $this->execute_in_builder("mkdir -p {$this->workdir}")
],
);
}
private function set_git_import_settings($git_clone_command)
{
if ($this->application->git_commit_sha !== 'HEAD') {
$git_clone_command = "{$git_clone_command} && cd {$this->workdir} && git -c advice.detachedHead=false checkout {$this->application->git_commit_sha} >/dev/null 2>&1";
}
if ($this->application->settings->is_git_submodules_enabled) {
$git_clone_command = "{$git_clone_command} && cd {$this->workdir} && git submodule update --init --recursive";
}
if ($this->application->settings->is_git_lfs_enabled) {
$git_clone_command = "{$git_clone_command} && cd {$this->workdir} && git lfs pull";
}
return $git_clone_command;
}
private function importing_git_repository()
{
$commands = collect([]);
$git_clone_command = "git clone -q -b {$this->application->git_branch}";
if ($this->pull_request_id !== 0) {
$pr_branch_name = "pr-{$this->pull_request_id}-coolify";
}
if ($this->application->deploymentType() === 'source') { private function add_build_env_variables_to_dockerfile()
$source_html_url = data_get($this->application, 'source.html_url'); {
$url = parse_url(filter_var($source_html_url, FILTER_SANITIZE_URL)); $this->execute_remote_command([
$source_html_url_host = $url['host']; $this->execute_in_builder("cat {$this->workdir}/Dockerfile"), "hidden" => true, "save" => 'dockerfile'
$source_html_url_scheme = $url['scheme']; ]);
$dockerfile = collect(Str::of($this->saved_outputs->get('dockerfile'))->trim()->explode("\n"));
if ($this->source->getMorphClass() == 'App\Models\GithubApp') { foreach ($this->application->build_environment_variables as $env) {
if ($this->source->is_public) { $dockerfile->splice(1, 0, "ARG {$env->key}={$env->value}");
$git_clone_command = "{$git_clone_command} {$this->source->html_url}/{$this->application->git_repository} {$this->workdir}";
$git_clone_command = $this->set_git_import_settings($git_clone_command);
$commands->push($this->execute_in_builder($git_clone_command));
} else {
$github_access_token = generate_github_installation_token($this->source);
$commands->push($this->execute_in_builder("git clone -q -b {$this->application->git_branch} $source_html_url_scheme://x-access-token:$github_access_token@$source_html_url_host/{$this->application->git_repository}.git {$this->workdir}"));
}
if ($this->pull_request_id !== 0) {
$commands->push($this->execute_in_builder("cd {$this->workdir} && git fetch origin pull/{$this->pull_request_id}/head:$pr_branch_name && git checkout $pr_branch_name"));
}
return $commands->implode(' && ');
}
} }
if ($this->application->deploymentType() === 'deploy_key') { $dockerfile_base64 = base64_encode($dockerfile->implode("\n"));
$private_key = base64_encode($this->application->private_key->private_key); $this->execute_remote_command([
$git_clone_command = "GIT_SSH_COMMAND=\"ssh -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" {$git_clone_command} {$this->application->git_full_url} {$this->workdir}"; $this->execute_in_builder("echo '{$dockerfile_base64}' | base64 -d > {$this->workdir}/Dockerfile"),
$git_clone_command = $this->set_git_import_settings($git_clone_command); "hidden" => true
$commands = collect([ ]);
$this->execute_in_builder("mkdir -p /root/.ssh"), }
$this->execute_in_builder("echo '{$private_key}' | base64 -d > /root/.ssh/id_rsa"),
$this->execute_in_builder("chmod 600 /root/.ssh/id_rsa"), private function next(string $status)
$this->execute_in_builder($git_clone_command) {
// If the deployment is cancelled by the user, don't update the status
if ($this->application_deployment_queue->status !== ApplicationDeploymentStatus::CANCELLED_BY_USER->value) {
$this->application_deployment_queue->update([
'status' => $status,
]); ]);
return $commands->implode(' && '); }
queue_next_deployment($this->application);
if ($status === ApplicationDeploymentStatus::FINISHED->value) {
$this->application->environment->project->team->notify(new DeploymentSuccess($this->application, $this->deployment_uuid, $this->preview));
}
if ($status === ApplicationDeploymentStatus::FAILED->value) {
$this->application->environment->project->team->notify(new DeploymentFailed($this->application, $this->deployment_uuid, $this->preview));
} }
} }
private function clone_repository()
public function failed(Throwable $exception): void
{ {
$this->execute_remote_command( $this->execute_remote_command(
[ ["echo 'Oops something is not okay, are you okay? 😢'"],
"echo -n 'Importing {$this->application->git_repository}:{$this->application->git_branch} to {$this->workdir}. '" ["echo '{$exception->getMessage()}'"]
],
[
$this->importing_git_repository()
],
[
$this->execute_in_builder("cd {$this->workdir} && git rev-parse HEAD"),
"hidden" => true,
"save" => "git_commit_sha"
],
); );
$this->commit = $this->saved_outputs->get('git_commit_sha'); $this->next(ApplicationDeploymentStatus::FAILED->value);
} }
} }

View File

@ -22,11 +22,13 @@ class ApplicationPullRequestUpdateJob implements ShouldQueue
public function __construct( public function __construct(
public string $application_id, public string $application_id,
public int $pull_request_id, public int $pull_request_id,
public string $deployment_uuid, public string $deployment_uuid,
public string $status public string $status
) { )
{
} }
public function handle() public function handle()
{ {
try { try {
@ -61,6 +63,7 @@ public function handle()
throw $e; throw $e;
} }
} }
private function update_comment() private function update_comment()
{ {
['data' => $data] = git_api(source: $this->application->source, endpoint: "/repos/{$this->application->git_repository}/issues/comments/{$this->preview->pull_request_issue_comment_id}", method: 'patch', data: [ ['data' => $data] = git_api(source: $this->application->source, endpoint: "/repos/{$this->application->git_repository}/issues/comments/{$this->preview->pull_request_issue_comment_id}", method: 'patch', data: [
@ -71,6 +74,7 @@ private function update_comment()
$this->create_comment(); $this->create_comment();
} }
} }
private function create_comment() private function create_comment()
{ {
['data' => $data] = git_api(source: $this->application->source, endpoint: "/repos/{$this->application->git_repository}/issues/{$this->pull_request_id}/comments", method: 'post', data: [ ['data' => $data] = git_api(source: $this->application->source, endpoint: "/repos/{$this->application->git_repository}/issues/{$this->pull_request_id}/comments", method: 'post', data: [

View File

@ -3,15 +3,11 @@
namespace App\Jobs; namespace App\Jobs;
use App\Actions\License\CheckResaleLicense; use App\Actions\License\CheckResaleLicense;
use App\Models\InstanceSettings;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Http;
use Visus\Cuid2\Cuid2;
class CheckResaleLicenseJob implements ShouldQueue class CheckResaleLicenseJob implements ShouldQueue
{ {

View File

@ -2,7 +2,6 @@
namespace App\Jobs; namespace App\Jobs;
use App\Models\Application;
use App\Models\ApplicationPreview; use App\Models\ApplicationPreview;
use App\Notifications\Application\StatusChanged; use App\Notifications\Application\StatusChanged;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
@ -11,7 +10,6 @@
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
class ContainerStatusJob implements ShouldQueue, ShouldBeUnique class ContainerStatusJob implements ShouldQueue, ShouldBeUnique
{ {
@ -27,10 +25,12 @@ public function __construct($resource, string $container_name, string|null $pull
$this->container_name = $container_name; $this->container_name = $container_name;
$this->pull_request_id = $pull_request_id; $this->pull_request_id = $pull_request_id;
} }
public function uniqueId(): string public function uniqueId(): string
{ {
return $this->container_name; return $this->container_name;
} }
public function handle(): void public function handle(): void
{ {
try { try {

View File

@ -19,8 +19,9 @@ class CoolifyTask implements ShouldQueue
*/ */
public function __construct( public function __construct(
public Activity $activity, public Activity $activity,
public bool $ignore_errors = false, public bool $ignore_errors = false,
) { )
{
} }
/** /**

View File

@ -8,13 +8,14 @@
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str; use Illuminate\Support\Str;
class DockerCleanupJob implements ShouldQueue class DockerCleanupJob implements ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $timeout = 500; public $timeout = 500;
/** /**
* Create a new job instance. * Create a new job instance.
*/ */

View File

@ -15,10 +15,12 @@ class InstanceApplicationsStatusJob implements ShouldQueue, ShouldBeUnique
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $applications; public $applications;
public function __construct() public function __construct()
{ {
$this->applications = Application::all(); $this->applications = Application::all();
} }
public function handle(): void public function handle(): void
{ {
try { try {

View File

@ -3,9 +3,6 @@
namespace App\Jobs; namespace App\Jobs;
use App\Actions\Server\UpdateCoolify; use App\Actions\Server\UpdateCoolify;
use App\Models\InstanceSettings;
use App\Models\Server;
use Exception;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique; use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
@ -22,6 +19,7 @@ class InstanceAutoUpdateJob implements ShouldQueue, ShouldBeUnique
public function __construct(private bool $force = false) public function __construct(private bool $force = false)
{ {
} }
public function handle(): void public function handle(): void
{ {
resolve(UpdateCoolify::class)($this->force); resolve(UpdateCoolify::class)($this->force);

View File

@ -3,7 +3,6 @@
namespace App\Jobs; namespace App\Jobs;
use App\Actions\Proxy\StartProxy; use App\Actions\Proxy\StartProxy;
use App\Enums\ProxyTypes;
use App\Models\Server; use App\Models\Server;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
@ -18,6 +17,7 @@ class ProxyCheckJob implements ShouldQueue
public function __construct() public function __construct()
{ {
} }
public function handle() public function handle()
{ {
try { try {

View File

@ -9,8 +9,8 @@
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\Middleware\WithoutOverlapping; use Illuminate\Queue\Middleware\WithoutOverlapping;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Str; use Illuminate\Support\Str;
class ProxyContainerStatusJob implements ShouldQueue, ShouldBeUnique class ProxyContainerStatusJob implements ShouldQueue, ShouldBeUnique
@ -20,18 +20,22 @@ class ProxyContainerStatusJob implements ShouldQueue, ShouldBeUnique
public Server $server; public Server $server;
public $tries = 1; public $tries = 1;
public $timeout = 120; public $timeout = 120;
public function middleware(): array
{
return [new WithoutOverlapping($this->server->id)];
}
public function __construct(Server $server) public function __construct(Server $server)
{ {
$this->server = $server; $this->server = $server;
} }
public function middleware(): array
{
return [new WithoutOverlapping($this->server->id)];
}
public function uniqueId(): int public function uniqueId(): int
{ {
return $this->server->id; return $this->server->id;
} }
public function handle(): void public function handle(): void
{ {
try { try {

View File

@ -17,6 +17,7 @@ class ProxyStartJob implements ShouldQueue
public function __construct(protected Server $server) public function __construct(protected Server $server)
{ {
} }
public function handle() public function handle()
{ {
try { try {

View File

@ -3,7 +3,6 @@
namespace App\Jobs; namespace App\Jobs;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
@ -29,7 +28,8 @@ class SendMessageToDiscordJob implements ShouldQueue
public function __construct( public function __construct(
public string $text, public string $text,
public string $webhookUrl public string $webhookUrl
) { )
{
} }
/** /**

View File

@ -2,28 +2,12 @@
namespace App\Models; namespace App\Models;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Casts\Attribute;
use Spatie\Activitylog\Models\Activity;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
use Masmerise\Toaster\Toastable; use Spatie\Activitylog\Models\Activity;
use Masmerise\Toaster\Toaster;
use Spatie\SchemalessAttributes\Casts\SchemalessAttributes;
class Application extends BaseModel class Application extends BaseModel
{ {
protected static function booted()
{
static::created(function ($application) {
ApplicationSetting::create([
'application_id' => $application->id,
]);
});
static::deleting(function ($application) {
$application->settings()->delete();
$application->persistentStorages()->delete();
});
}
protected $fillable = [ protected $fillable = [
'name', 'name',
'repository_project_id', 'repository_project_id',
@ -43,15 +27,42 @@ protected static function booted()
'publish_directory', 'publish_directory',
'private_key_id' 'private_key_id'
]; ];
public function type() {
protected static function booted()
{
static::created(function ($application) {
ApplicationSetting::create([
'application_id' => $application->id,
]);
});
static::deleting(function ($application) {
$application->settings()->delete();
$application->persistentStorages()->delete();
});
}
public function settings()
{
return $this->hasOne(ApplicationSetting::class);
}
public function persistentStorages()
{
return $this->morphMany(LocalPersistentVolume::class, 'resource');
}
public function type()
{
return 'application'; return 'application';
} }
public function publishDirectory(): Attribute public function publishDirectory(): Attribute
{ {
return Attribute::make( return Attribute::make(
set: fn ($value) => $value ? '/' . ltrim($value, '/') : null, set: fn($value) => $value ? '/' . ltrim($value, '/') : null,
); );
} }
public function gitBranchLocation(): Attribute public function gitBranchLocation(): Attribute
{ {
return Attribute::make( return Attribute::make(
@ -63,6 +74,7 @@ public function gitBranchLocation(): Attribute
); );
} }
public function gitCommits(): Attribute public function gitCommits(): Attribute
{ {
return Attribute::make( return Attribute::make(
@ -73,99 +85,108 @@ public function gitCommits(): Attribute
} }
); );
} }
public function baseDirectory(): Attribute public function baseDirectory(): Attribute
{ {
return Attribute::make( return Attribute::make(
set: fn ($value) => '/' . ltrim($value, '/'), set: fn($value) => '/' . ltrim($value, '/'),
); );
} }
public function portsMappings(): Attribute public function portsMappings(): Attribute
{ {
return Attribute::make( return Attribute::make(
set: fn ($value) => $value === "" ? null : $value, set: fn($value) => $value === "" ? null : $value,
); );
} }
// Normal Deployments
public function portsMappingsArray(): Attribute public function portsMappingsArray(): Attribute
{ {
return Attribute::make( return Attribute::make(
get: fn () => get: fn() => is_null($this->ports_mappings)
is_null($this->ports_mappings)
? [] ? []
: explode(',', $this->ports_mappings), : explode(',', $this->ports_mappings),
); );
} }
public function portsExposesArray(): Attribute public function portsExposesArray(): Attribute
{ {
return Attribute::make( return Attribute::make(
get: fn () => get: fn() => is_null($this->ports_exposes)
is_null($this->ports_exposes)
? [] ? []
: explode(',', $this->ports_exposes) : explode(',', $this->ports_exposes)
); );
} }
// Normal Deployments
public function environment_variables(): HasMany public function environment_variables(): HasMany
{ {
return $this->hasMany(EnvironmentVariable::class)->where('is_preview', false); return $this->hasMany(EnvironmentVariable::class)->where('is_preview', false);
} }
public function runtime_environment_variables(): HasMany public function runtime_environment_variables(): HasMany
{ {
return $this->hasMany(EnvironmentVariable::class)->where('is_preview', false)->where('key', 'not like', 'NIXPACKS_%'); return $this->hasMany(EnvironmentVariable::class)->where('is_preview', false)->where('key', 'not like', 'NIXPACKS_%');
} }
// Preview Deployments
public function build_environment_variables(): HasMany public function build_environment_variables(): HasMany
{ {
return $this->hasMany(EnvironmentVariable::class)->where('is_preview', false)->where('is_build_time', true)->where('key', 'not like', 'NIXPACKS_%'); return $this->hasMany(EnvironmentVariable::class)->where('is_preview', false)->where('is_build_time', true)->where('key', 'not like', 'NIXPACKS_%');
} }
public function nixpacks_environment_variables(): HasMany public function nixpacks_environment_variables(): HasMany
{ {
return $this->hasMany(EnvironmentVariable::class)->where('is_preview', false)->where('key', 'like', 'NIXPACKS_%'); return $this->hasMany(EnvironmentVariable::class)->where('is_preview', false)->where('key', 'like', 'NIXPACKS_%');
} }
// Preview Deployments
public function environment_variables_preview(): HasMany public function environment_variables_preview(): HasMany
{ {
return $this->hasMany(EnvironmentVariable::class)->where('is_preview', true); return $this->hasMany(EnvironmentVariable::class)->where('is_preview', true);
} }
public function runtime_environment_variables_preview(): HasMany public function runtime_environment_variables_preview(): HasMany
{ {
return $this->hasMany(EnvironmentVariable::class)->where('is_preview', true)->where('key', 'not like', 'NIXPACKS_%'); return $this->hasMany(EnvironmentVariable::class)->where('is_preview', true)->where('key', 'not like', 'NIXPACKS_%');
} }
public function build_environment_variables_preview(): HasMany public function build_environment_variables_preview(): HasMany
{ {
return $this->hasMany(EnvironmentVariable::class)->where('is_preview', true)->where('is_build_time', true)->where('key', 'not like', 'NIXPACKS_%'); return $this->hasMany(EnvironmentVariable::class)->where('is_preview', true)->where('is_build_time', true)->where('key', 'not like', 'NIXPACKS_%');
} }
public function nixpacks_environment_variables_preview(): HasMany public function nixpacks_environment_variables_preview(): HasMany
{ {
return $this->hasMany(EnvironmentVariable::class)->where('is_preview', true)->where('key', 'like', 'NIXPACKS_%'); return $this->hasMany(EnvironmentVariable::class)->where('is_preview', true)->where('key', 'like', 'NIXPACKS_%');
} }
public function private_key() public function private_key()
{ {
return $this->belongsTo(PrivateKey::class); return $this->belongsTo(PrivateKey::class);
} }
public function environment() public function environment()
{ {
return $this->belongsTo(Environment::class); return $this->belongsTo(Environment::class);
} }
public function previews() public function previews()
{ {
return $this->hasMany(ApplicationPreview::class); return $this->hasMany(ApplicationPreview::class);
} }
public function settings()
{
return $this->hasOne(ApplicationSetting::class);
}
public function destination() public function destination()
{ {
return $this->morphTo(); return $this->morphTo();
} }
public function source() public function source()
{ {
return $this->morphTo(); return $this->morphTo();
} }
public function persistentStorages()
{
return $this->morphMany(LocalPersistentVolume::class, 'resource');
}
public function deployments(int $skip = 0, int $take = 10) public function deployments(int $skip = 0, int $take = 10)
{ {
@ -177,10 +198,12 @@ public function deployments(int $skip = 0, int $take = 10)
'deployments' => $deployments 'deployments' => $deployments
]; ];
} }
public function get_deployment(string $deployment_uuid) public function get_deployment(string $deployment_uuid)
{ {
return Activity::where('subject_id', $this->id)->where('properties->type_uuid', '=', $deployment_uuid)->first(); return Activity::where('subject_id', $this->id)->where('properties->type_uuid', '=', $deployment_uuid)->first();
} }
public function isDeployable(): bool public function isDeployable(): bool
{ {
if ($this->settings->is_auto_deploy_enabled) { if ($this->settings->is_auto_deploy_enabled) {
@ -188,6 +211,7 @@ public function isDeployable(): bool
} }
return false; return false;
} }
public function isPRDeployable(): bool public function isPRDeployable(): bool
{ {
if ($this->settings->is_preview_deployments_enabled) { if ($this->settings->is_preview_deployments_enabled) {
@ -195,6 +219,7 @@ public function isPRDeployable(): bool
} }
return false; return false;
} }
public function deploymentType() public function deploymentType()
{ {
if (data_get($this, 'private_key_id')) { if (data_get($this, 'private_key_id')) {

View File

@ -13,12 +13,14 @@ class ApplicationPreview extends BaseModel
'status', 'status',
'application_id', 'application_id',
]; ];
public function application()
{
return $this->belongsTo(Application::class);
}
static function findPreviewByApplicationAndPullId(int $application_id, int $pull_request_id) static function findPreviewByApplicationAndPullId(int $application_id, int $pull_request_id)
{ {
return self::where('application_id', $application_id)->where('pull_request_id', $pull_request_id)->firstOrFail(); return self::where('application_id', $application_id)->where('pull_request_id', $pull_request_id)->firstOrFail();
} }
public function application()
{
return $this->belongsTo(Application::class);
}
} }

View File

@ -26,6 +26,7 @@ class ApplicationSetting extends Model
'is_git_submodules_enabled', 'is_git_submodules_enabled',
'is_git_lfs_enabled', 'is_git_lfs_enabled',
]; ];
public function isStatic(): Attribute public function isStatic(): Attribute
{ {
return Attribute::make( return Attribute::make(
@ -42,6 +43,7 @@ public function isStatic(): Attribute
} }
); );
} }
public function application() public function application()
{ {
return $this->belongsTo(Application::class); return $this->belongsTo(Application::class);

View File

@ -14,7 +14,7 @@ protected static function boot()
static::creating(function (Model $model) { static::creating(function (Model $model) {
// Generate a UUID if one isn't set // Generate a UUID if one isn't set
if (!$model->uuid) { if (!$model->uuid) {
$model->uuid = (string) new Cuid2(7); $model->uuid = (string)new Cuid2(7);
} }
}); });
} }

View File

@ -8,6 +8,7 @@ public function environment()
{ {
return $this->belongsTo(Environment::class); return $this->belongsTo(Environment::class);
} }
public function destination() public function destination()
{ {
return $this->morphTo(); return $this->morphTo();

Some files were not shown because too many files have changed in this diff Show More