mirror of
https://github.com/ershisan99/coolify.git
synced 2025-12-18 12:33:06 +00:00
Compare commits
90 Commits
v4.0.0-bet
...
v4.0.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0e99f27108 | ||
|
|
f445a8c312 | ||
|
|
845fc191d4 | ||
|
|
95d0d72e0d | ||
|
|
76f695036c | ||
|
|
225bf06736 | ||
|
|
3a287ae974 | ||
|
|
e5c61b9f9f | ||
|
|
32bc876dfc | ||
|
|
c9b3d2a43d | ||
|
|
f343210e7c | ||
|
|
4a42bff0dc | ||
|
|
36931b5b18 | ||
|
|
3b080abada | ||
|
|
7feba4bbaa | ||
|
|
eef8c756df | ||
|
|
9ed30cb0dc | ||
|
|
6bc43bd999 | ||
|
|
e7683ee9a5 | ||
|
|
ee71aeaa36 | ||
|
|
404c664500 | ||
|
|
aa80392b46 | ||
|
|
c9509ef658 | ||
|
|
31e08a24c9 | ||
|
|
b6745c691b | ||
|
|
b69584fe26 | ||
|
|
4c3907c296 | ||
|
|
bf44b4b949 | ||
|
|
bee7a2357b | ||
|
|
98704fc3c2 | ||
|
|
e286e78ddc | ||
|
|
3c99f24b5a | ||
|
|
963c519c38 | ||
|
|
d04513d817 | ||
|
|
64a7f27e37 | ||
|
|
65652142b2 | ||
|
|
7691319c59 | ||
|
|
206bd50d00 | ||
|
|
6159783a73 | ||
|
|
ed5f831c86 | ||
|
|
65be83e75d | ||
|
|
25a471b045 | ||
|
|
60c7a29aa8 | ||
|
|
11ab6669a0 | ||
|
|
53965ab8ed | ||
|
|
ea271ca079 | ||
|
|
f16d0f650f | ||
|
|
cb80341a78 | ||
|
|
83d96c8d11 | ||
|
|
a8ca57d095 | ||
|
|
2d936a4b22 | ||
|
|
0653eb8511 | ||
|
|
cc64132627 | ||
|
|
e0391e5abd | ||
|
|
025135bd2a | ||
|
|
5e5873a08d | ||
|
|
14652c2878 | ||
|
|
a7ef5c456d | ||
|
|
117f1d4155 | ||
|
|
075f3ce930 | ||
|
|
d5b3e88fc4 | ||
|
|
ba55e0c1bb | ||
|
|
54671354f0 | ||
|
|
a2c7e8d455 | ||
|
|
32dbdf5204 | ||
|
|
019887739c | ||
|
|
5596e41f2b | ||
|
|
6a73a00a1f | ||
|
|
4121c9dd8b | ||
|
|
e4781dc129 | ||
|
|
1c90f46f2a | ||
|
|
e78d851c85 | ||
|
|
52d05005ed | ||
|
|
f03aa57758 | ||
|
|
8c20c833ba | ||
|
|
2fe6766b7f | ||
|
|
d9599da4a8 | ||
|
|
3f453ba7c0 | ||
|
|
bd02c3055a | ||
|
|
7ea7d85d15 | ||
|
|
d38350c282 | ||
|
|
a83c70004c | ||
|
|
49e1404a2c | ||
|
|
76f23e7dbf | ||
|
|
ad8653f54d | ||
|
|
8939d77051 | ||
|
|
37be4a1796 | ||
|
|
e4c923e358 | ||
|
|
62ca3ffaa5 | ||
|
|
9af3ce4be5 |
62
README.md
62
README.md
@@ -17,6 +17,40 @@ https://coolify.io/sponsorships
|
||||
|
||||
Thank you so much!
|
||||
|
||||
Special thanks to our biggest sponsors, [CCCareers](https://cccareers.org/) and [Appwrite](https://appwrite.io)!
|
||||
|
||||
<a href="https://cccareers.org/" target="_blank"><img src="./other/logos/ccc-logo.webp" alt="cccareers logo" width="200"/></a>
|
||||
<a href="https://appwrite.io" target="_blank"><img src="./other/logos/appwrite.svg" alt="appwrite logo" width="200"/></a>
|
||||
|
||||
## Github Sponsors ($15+)
|
||||
<a href="https://bc.direct"><img width="60px" alt="BC Direct" src="https://github.com/coollabsio/coolify/assets/5845193/a4063c41-95ed-4a32-8814-cd1475572e37"/></a>
|
||||
<a href="https://github.com/automazeio"><img src="https://github.com/automazeio.png" width="60px" alt="Corentin Clichy" /></a>
|
||||
<a href="https://github.com/corentinclichy"><img src="https://github.com/corentinclichy.png" width="60px" alt="Corentin Clichy" /></a>
|
||||
<a href="https://github.com/Niki2k1"><img src="https://github.com/Niki2k1.png" width="60px" alt="Niklas Lausch" /></a>
|
||||
<a href="https://github.com/pixelinfinito"><img src="https://github.com/pixelinfinito.png" width="60px" alt="Pixel Infinito" /></a>
|
||||
<a href="https://github.com/whitesidest"><img src="https://avatars.githubusercontent.com/u/12365916?s=52&v=4" width="60px" alt="Tyler Whitesides" /></a>
|
||||
<a href="https://github.com/aniftyco"><img src="https://github.com/aniftyco.png" width="60px" alt="NiftyCo" /></a>
|
||||
<a href="https://github.com/iujlaki"><img src="https://github.com/iujlaki.png" width="60px" alt="Imre Ujlaki" /></a>
|
||||
<a href="https://github.com/Illyism"><img src="https://github.com/Illyism.png" width="60px" alt="Ilias Ism" /></a>
|
||||
<a href="https://github.com/urtho"><img src="https://github.com/urtho.png" width="60px" alt="Paweł Pierścionek" /></a>
|
||||
<a href="https://github.com/monocursive"><img src="https://github.com/monocursive.png" width="60px" alt="Michael Mazurczak" /></a>
|
||||
|
||||
## Organizations
|
||||
<a href="https://opencollective.com/coollabsio/organization/0/website"><img src="https://opencollective.com/coollabsio/organization/0/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/coollabsio/organization/1/website"><img src="https://opencollective.com/coollabsio/organization/1/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/coollabsio/organization/2/website"><img src="https://opencollective.com/coollabsio/organization/2/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/coollabsio/organization/3/website"><img src="https://opencollective.com/coollabsio/organization/3/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/coollabsio/organization/4/website"><img src="https://opencollective.com/coollabsio/organization/4/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/coollabsio/organization/5/website"><img src="https://opencollective.com/coollabsio/organization/5/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/coollabsio/organization/6/website"><img src="https://opencollective.com/coollabsio/organization/6/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/coollabsio/organization/7/website"><img src="https://opencollective.com/coollabsio/organization/7/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/coollabsio/organization/8/website"><img src="https://opencollective.com/coollabsio/organization/8/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/coollabsio/organization/9/website"><img src="https://opencollective.com/coollabsio/organization/9/avatar.svg"></a>
|
||||
|
||||
## Individuals
|
||||
|
||||
<a href="https://opencollective.com/coollabsio"><img src="https://opencollective.com/coollabsio/individuals.svg?width=890"></a>
|
||||
|
||||
# Cloud
|
||||
|
||||
If you do not want to self-host Coolify, there is a paid cloud version available: https://app.coolify.io
|
||||
@@ -59,34 +93,6 @@ Contact us [here](https://coolify.io/docs/contact).
|
||||
|
||||
<a href="https://trendshift.io/repositories/634" target="_blank"><img src="https://trendshift.io/api/badge/repositories/634" alt="coollabsio%2Fcoolify | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
||||
|
||||
# 💰 Financial Contributors
|
||||
|
||||
Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/coollabsio/contribute)]
|
||||
|
||||
## Organizations
|
||||
|
||||
Special thanks to our biggest sponsors, [CCCareers](https://cccareers.org/) and [Appwrite](https://appwrite.io)!
|
||||
|
||||
<a href="https://cccareers.org/" target="_blank"><img src="./other/logos/ccc-logo.webp" alt="appwrite logo" width="200"/></a>
|
||||
<a href="https://appwrite.io" target="_blank"><img src="./other/logos/appwrite.svg" alt="appwrite logo" width="200"/></a>
|
||||
|
||||
Support this project with your organization. Your logo will show up here with a link to your website.
|
||||
|
||||
<a href="https://opencollective.com/coollabsio/organization/0/website"><img src="https://opencollective.com/coollabsio/organization/0/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/coollabsio/organization/1/website"><img src="https://opencollective.com/coollabsio/organization/1/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/coollabsio/organization/2/website"><img src="https://opencollective.com/coollabsio/organization/2/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/coollabsio/organization/3/website"><img src="https://opencollective.com/coollabsio/organization/3/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/coollabsio/organization/4/website"><img src="https://opencollective.com/coollabsio/organization/4/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/coollabsio/organization/5/website"><img src="https://opencollective.com/coollabsio/organization/5/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/coollabsio/organization/6/website"><img src="https://opencollective.com/coollabsio/organization/6/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/coollabsio/organization/7/website"><img src="https://opencollective.com/coollabsio/organization/7/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/coollabsio/organization/8/website"><img src="https://opencollective.com/coollabsio/organization/8/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/coollabsio/organization/9/website"><img src="https://opencollective.com/coollabsio/organization/9/avatar.svg"></a>
|
||||
|
||||
## Individuals
|
||||
|
||||
<a href="https://opencollective.com/coollabsio"><img src="https://opencollective.com/coollabsio/individuals.svg?width=890"></a>
|
||||
|
||||
# Star History
|
||||
|
||||
[](https://star-history.com/#coollabsio/coolify&Date)
|
||||
|
||||
@@ -56,7 +56,7 @@ class StartMariadb
|
||||
'memswap_limit' => $this->database->limits_memory_swap,
|
||||
'mem_swappiness' => $this->database->limits_memory_swappiness,
|
||||
'mem_reservation' => $this->database->limits_memory_reservation,
|
||||
'cpus' => (int) $this->database->limits_cpus,
|
||||
'cpus' => (float) $this->database->limits_cpus,
|
||||
'cpuset' => $this->database->limits_cpuset,
|
||||
'cpu_shares' => $this->database->limits_cpu_shares,
|
||||
]
|
||||
|
||||
@@ -63,7 +63,7 @@ class StartMongodb
|
||||
'memswap_limit' => $this->database->limits_memory_swap,
|
||||
'mem_swappiness' => $this->database->limits_memory_swappiness,
|
||||
'mem_reservation' => $this->database->limits_memory_reservation,
|
||||
'cpus' => (int) $this->database->limits_cpus,
|
||||
'cpus' => (float) $this->database->limits_cpus,
|
||||
'cpuset' => $this->database->limits_cpuset,
|
||||
'cpu_shares' => $this->database->limits_cpu_shares,
|
||||
]
|
||||
|
||||
@@ -56,7 +56,7 @@ class StartMysql
|
||||
'memswap_limit' => $this->database->limits_memory_swap,
|
||||
'mem_swappiness' => $this->database->limits_memory_swappiness,
|
||||
'mem_reservation' => $this->database->limits_memory_reservation,
|
||||
'cpus' => (int) $this->database->limits_cpus,
|
||||
'cpus' => (float) $this->database->limits_cpus,
|
||||
'cpuset' => $this->database->limits_cpuset,
|
||||
'cpu_shares' => $this->database->limits_cpu_shares,
|
||||
]
|
||||
|
||||
@@ -66,7 +66,7 @@ class StartPostgresql
|
||||
'memswap_limit' => $this->database->limits_memory_swap,
|
||||
'mem_swappiness' => $this->database->limits_memory_swappiness,
|
||||
'mem_reservation' => $this->database->limits_memory_reservation,
|
||||
'cpus' => (int) $this->database->limits_cpus,
|
||||
'cpus' => (float) $this->database->limits_cpus,
|
||||
'cpuset' => $this->database->limits_cpuset,
|
||||
'cpu_shares' => $this->database->limits_cpu_shares,
|
||||
]
|
||||
|
||||
@@ -65,7 +65,7 @@ class StartRedis
|
||||
'memswap_limit' => $this->database->limits_memory_swap,
|
||||
'mem_swappiness' => $this->database->limits_memory_swappiness,
|
||||
'mem_reservation' => $this->database->limits_memory_reservation,
|
||||
'cpus' => (int) $this->database->limits_cpus,
|
||||
'cpus' => (float) $this->database->limits_cpus,
|
||||
'cpuset' => $this->database->limits_cpuset,
|
||||
'cpu_shares' => $this->database->limits_cpu_shares,
|
||||
]
|
||||
|
||||
@@ -21,14 +21,14 @@ class DeleteService
|
||||
foreach ($storages as $storage) {
|
||||
$storagesToDelete->push($storage);
|
||||
}
|
||||
$application->delete();
|
||||
$application->forceDelete();
|
||||
}
|
||||
foreach ($service->databases()->get() as $database) {
|
||||
$storages = $database->persistentStorages()->get();
|
||||
foreach ($storages as $storage) {
|
||||
$storagesToDelete->push($storage);
|
||||
}
|
||||
$database->delete();
|
||||
$database->forceDelete();
|
||||
}
|
||||
foreach ($storagesToDelete as $storage) {
|
||||
$commands[] = "docker volume rm -f $storage->name";
|
||||
|
||||
@@ -7,6 +7,7 @@ use App\Jobs\CleanupHelperContainersJob;
|
||||
use App\Models\Application;
|
||||
use App\Models\ApplicationDeploymentQueue;
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\ScheduledDatabaseBackup;
|
||||
use App\Models\Server;
|
||||
use App\Models\Service;
|
||||
use App\Models\ServiceApplication;
|
||||
@@ -31,6 +32,9 @@ class Init extends Command
|
||||
if ($cleanup) {
|
||||
echo "Running cleanup\n";
|
||||
$this->cleanup_stucked_resources();
|
||||
// Required for falsely deleted coolify db
|
||||
$this->restore_coolify_db_backup();
|
||||
|
||||
// $this->cleanup_ssh();
|
||||
}
|
||||
$this->cleanup_in_progress_application_deployments();
|
||||
@@ -51,6 +55,30 @@ class Init extends Command
|
||||
}
|
||||
}
|
||||
}
|
||||
private function restore_coolify_db_backup()
|
||||
{
|
||||
try {
|
||||
$database = StandalonePostgresql::withTrashed()->find(0);
|
||||
if ($database && $database->trashed()) {
|
||||
echo "Restoring coolify db backup\n";
|
||||
$database->restore();
|
||||
$scheduledBackup = ScheduledDatabaseBackup::find(0);
|
||||
if (!$scheduledBackup) {
|
||||
ScheduledDatabaseBackup::create([
|
||||
'id' => 0,
|
||||
'enabled' => true,
|
||||
'save_s3' => false,
|
||||
'frequency' => '0 0 * * *',
|
||||
'database_id' => $database->id,
|
||||
'database_type' => 'App\Models\StandalonePostgresql',
|
||||
'team_id' => 0,
|
||||
]);
|
||||
}
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
echo "Error in restoring coolify db backup: {$e->getMessage()}\n";
|
||||
}
|
||||
}
|
||||
private function cleanup_stucked_helper_containers()
|
||||
{
|
||||
$servers = Server::all();
|
||||
@@ -71,7 +99,7 @@ class Init extends Command
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Http::get("https://get.coollabs.io/coolify/v4/alive?appId=$id&version=$version");
|
||||
Http::get("https://undead.coollabs.io/coolify/v4/alive?appId=$id&version=$version");
|
||||
echo "I am alive!\n";
|
||||
} catch (\Throwable $e) {
|
||||
echo "Error in alive: {$e->getMessage()}\n";
|
||||
@@ -110,6 +138,89 @@ class Init extends Command
|
||||
}
|
||||
private function cleanup_stucked_resources()
|
||||
{
|
||||
|
||||
try {
|
||||
$applications = Application::withTrashed()->whereNotNull('deleted_at')->get();
|
||||
foreach ($applications as $application) {
|
||||
echo "Deleting stucked application: {$application->name}\n";
|
||||
$application->forceDelete();
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
echo "Error in cleaning stucked application: {$e->getMessage()}\n";
|
||||
}
|
||||
try {
|
||||
$postgresqls = StandalonePostgresql::withTrashed()->whereNotNull('deleted_at')->get();
|
||||
foreach ($postgresqls as $postgresql) {
|
||||
echo "Deleting stucked postgresql: {$postgresql->name}\n";
|
||||
$postgresql->forceDelete();
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
echo "Error in cleaning stucked postgresql: {$e->getMessage()}\n";
|
||||
}
|
||||
try {
|
||||
$redis = StandaloneRedis::withTrashed()->whereNotNull('deleted_at')->get();
|
||||
foreach ($redis as $redis) {
|
||||
echo "Deleting stucked redis: {$redis->name}\n";
|
||||
$redis->forceDelete();
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
echo "Error in cleaning stucked redis: {$e->getMessage()}\n";
|
||||
}
|
||||
try {
|
||||
$mongodbs = StandaloneMongodb::withTrashed()->whereNotNull('deleted_at')->get();
|
||||
foreach ($mongodbs as $mongodb) {
|
||||
echo "Deleting stucked mongodb: {$mongodb->name}\n";
|
||||
$mongodb->forceDelete();
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
echo "Error in cleaning stucked mongodb: {$e->getMessage()}\n";
|
||||
}
|
||||
try {
|
||||
$mysqls = StandaloneMysql::withTrashed()->whereNotNull('deleted_at')->get();
|
||||
foreach ($mysqls as $mysql) {
|
||||
echo "Deleting stucked mysql: {$mysql->name}\n";
|
||||
$mysql->forceDelete();
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
echo "Error in cleaning stucked mysql: {$e->getMessage()}\n";
|
||||
}
|
||||
try {
|
||||
$mariadbs = StandaloneMariadb::withTrashed()->whereNotNull('deleted_at')->get();
|
||||
foreach ($mariadbs as $mariadb) {
|
||||
echo "Deleting stucked mariadb: {$mariadb->name}\n";
|
||||
$mariadb->forceDelete();
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
echo "Error in cleaning stucked mariadb: {$e->getMessage()}\n";
|
||||
}
|
||||
try {
|
||||
$services = Service::withTrashed()->whereNotNull('deleted_at')->get();
|
||||
foreach ($services as $service) {
|
||||
echo "Deleting stucked service: {$service->name}\n";
|
||||
$service->forceDelete();
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
echo "Error in cleaning stucked service: {$e->getMessage()}\n";
|
||||
}
|
||||
try {
|
||||
$serviceApps = ServiceApplication::withTrashed()->whereNotNull('deleted_at')->get();
|
||||
foreach ($serviceApps as $serviceApp) {
|
||||
echo "Deleting stucked serviceapp: {$serviceApp->name}\n";
|
||||
$serviceApp->forceDelete();
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
echo "Error in cleaning stucked serviceapp: {$e->getMessage()}\n";
|
||||
}
|
||||
try {
|
||||
$serviceDbs = ServiceDatabase::withTrashed()->whereNotNull('deleted_at')->get();
|
||||
foreach ($serviceDbs as $serviceDb) {
|
||||
echo "Deleting stucked serviceapp: {$serviceDb->name}\n";
|
||||
$serviceDb->forceDelete();
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
echo "Error in cleaning stucked serviceapp: {$e->getMessage()}\n";
|
||||
}
|
||||
|
||||
// Cleanup any resources that are not attached to any environment or destination or server
|
||||
try {
|
||||
$applications = Application::all();
|
||||
@@ -134,7 +245,7 @@ class Init extends Command
|
||||
echo "Error in application: {$e->getMessage()}\n";
|
||||
}
|
||||
try {
|
||||
$postgresqls = StandalonePostgresql::all();
|
||||
$postgresqls = StandalonePostgresql::all()->where('id', '!=', 0);
|
||||
foreach ($postgresqls as $postgresql) {
|
||||
if (!data_get($postgresql, 'environment')) {
|
||||
echo 'Postgresql without environment: ' . $postgresql->name . ' soft deleting\n';
|
||||
|
||||
@@ -47,7 +47,7 @@ class Handler extends ExceptionHandler
|
||||
if ($request->is('api/*') || $request->expectsJson() || $this->shouldReturnJson($request, $exception)) {
|
||||
return response()->json(['message' => $exception->getMessage()], 401);
|
||||
}
|
||||
return redirect()->guest($exception->redirectTo() ?? route('login'));
|
||||
return redirect()->guest($exception->redirectTo() ?? route('login'));
|
||||
}
|
||||
/**
|
||||
* Register the exception handling callbacks for the application.
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Events\TestEvent;
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\S3Storage;
|
||||
use App\Models\StandalonePostgresql;
|
||||
use App\Models\TeamInvitation;
|
||||
use App\Models\User;
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
@@ -14,11 +16,55 @@ use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Str;
|
||||
use Laravel\Fortify\Fortify;
|
||||
use Laravel\Fortify\Contracts\FailedPasswordResetLinkRequestResponse;
|
||||
use Laravel\Fortify\Contracts\SuccessfulPasswordResetLinkRequestResponse;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
|
||||
class Controller extends BaseController
|
||||
{
|
||||
use AuthorizesRequests, ValidatesRequests;
|
||||
|
||||
public function realtime_test() {
|
||||
if (auth()->user()?->currentTeam()->id !== 0) {
|
||||
return redirect(RouteServiceProvider::HOME);
|
||||
}
|
||||
TestEvent::dispatch();
|
||||
return 'Look at your other tab.';
|
||||
}
|
||||
public function verify() {
|
||||
return view('auth.verify-email');
|
||||
}
|
||||
public function email_verify() {
|
||||
request()->fulfill();
|
||||
$name = request()->user()?->name;
|
||||
send_internal_notification("User {$name} verified their email address.");
|
||||
return redirect(RouteServiceProvider::HOME);
|
||||
}
|
||||
public function forgot_password() {
|
||||
if (is_transactional_emails_active()) {
|
||||
$arrayOfRequest = request()->only(Fortify::email());
|
||||
request()->merge([
|
||||
'email' => Str::lower($arrayOfRequest['email']),
|
||||
]);
|
||||
$type = set_transanctional_email_settings();
|
||||
if (!$type) {
|
||||
return response()->json(['message' => 'Transactional emails are not active'], 400);
|
||||
}
|
||||
request()->validate([Fortify::email() => 'required|email']);
|
||||
$status = Password::broker(config('fortify.passwords'))->sendResetLink(
|
||||
request()->only(Fortify::email())
|
||||
);
|
||||
if ($status == Password::RESET_LINK_SENT) {
|
||||
return app(SuccessfulPasswordResetLinkRequestResponse::class, ['status' => $status]);
|
||||
}
|
||||
if ($status == Password::RESET_THROTTLED) {
|
||||
return response('Already requested a password reset in the past minutes.', 400);
|
||||
}
|
||||
return app(FailedPasswordResetLinkRequestResponse::class, ['status' => $status]);
|
||||
}
|
||||
return response()->json(['message' => 'Transactional emails are not active'], 400);
|
||||
}
|
||||
public function link()
|
||||
{
|
||||
$token = request()->get('token');
|
||||
@@ -51,90 +97,7 @@ class Controller extends BaseController
|
||||
return redirect()->route('login')->with('error', 'Invalid credentials.');
|
||||
}
|
||||
|
||||
public function license()
|
||||
{
|
||||
if (!isCloud()) {
|
||||
abort(404);
|
||||
}
|
||||
return view('settings.license', [
|
||||
'settings' => InstanceSettings::get(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function force_passoword_reset()
|
||||
{
|
||||
return view('auth.force-password-reset');
|
||||
}
|
||||
public function boarding()
|
||||
{
|
||||
if (currentTeam()->boarding || isDev()) {
|
||||
return view('boarding');
|
||||
} else {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
}
|
||||
|
||||
public function settings()
|
||||
{
|
||||
if (isInstanceAdmin()) {
|
||||
$settings = InstanceSettings::get();
|
||||
$database = StandalonePostgresql::whereName('coolify-db')->first();
|
||||
if ($database) {
|
||||
if ($database->status !== 'running') {
|
||||
$database->status = 'running';
|
||||
$database->save();
|
||||
}
|
||||
$s3s = S3Storage::whereTeamId(0)->get();
|
||||
}
|
||||
return view('settings.configuration', [
|
||||
'settings' => $settings,
|
||||
'database' => $database,
|
||||
's3s' => $s3s ?? [],
|
||||
]);
|
||||
} else {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
}
|
||||
|
||||
public function team()
|
||||
{
|
||||
$invitations = [];
|
||||
if (auth()->user()->isAdminFromSession()) {
|
||||
$invitations = TeamInvitation::whereTeamId(currentTeam()->id)->get();
|
||||
}
|
||||
return view('team.index', [
|
||||
'invitations' => $invitations,
|
||||
]);
|
||||
}
|
||||
|
||||
public function storages()
|
||||
{
|
||||
$s3 = S3Storage::ownedByCurrentTeam()->get();
|
||||
return view('team.storages.all', [
|
||||
's3' => $s3,
|
||||
]);
|
||||
}
|
||||
|
||||
public function storages_show()
|
||||
{
|
||||
$storage = S3Storage::ownedByCurrentTeam()->whereUuid(request()->storage_uuid)->firstOrFail();
|
||||
return view('team.storages.show', [
|
||||
'storage' => $storage,
|
||||
]);
|
||||
}
|
||||
|
||||
public function members()
|
||||
{
|
||||
$invitations = [];
|
||||
if (auth()->user()->isAdminFromSession()) {
|
||||
$invitations = TeamInvitation::whereTeamId(currentTeam()->id)->get();
|
||||
}
|
||||
return view('team.members', [
|
||||
'invitations' => $invitations,
|
||||
]);
|
||||
}
|
||||
|
||||
public function acceptInvitation()
|
||||
public function accept_invitation()
|
||||
{
|
||||
try {
|
||||
$resetPassword = request()->query('reset-password');
|
||||
@@ -169,7 +132,7 @@ class Controller extends BaseController
|
||||
}
|
||||
}
|
||||
|
||||
public function revokeInvitation()
|
||||
public function revoke_invitation()
|
||||
{
|
||||
try {
|
||||
$invitation = TeamInvitation::whereUuid(request()->route('uuid'))->firstOrFail();
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
|
||||
class DatabaseController extends Controller
|
||||
{
|
||||
use AuthorizesRequests, ValidatesRequests;
|
||||
|
||||
public function configuration()
|
||||
{
|
||||
$project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
|
||||
if (!$project) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$environment = $project->load(['environments'])->environments->where('name', request()->route('environment_name'))->first()->load(['applications']);
|
||||
if (!$environment) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$database = $environment->databases()->where('uuid', request()->route('database_uuid'))->first();
|
||||
if (!$database) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
return view('project.database.configuration', ['database' => $database]);
|
||||
}
|
||||
|
||||
public function executions()
|
||||
{
|
||||
$backup_uuid = request()->route('backup_uuid');
|
||||
$project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
|
||||
if (!$project) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$environment = $project->load(['environments'])->environments->where('name', request()->route('environment_name'))->first()->load(['applications']);
|
||||
if (!$environment) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$database = $environment->databases()->where('uuid', request()->route('database_uuid'))->first();
|
||||
if (!$database) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$backup = $database->scheduledBackups->where('uuid', $backup_uuid)->first();
|
||||
if (!$backup) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$executions = collect($backup->executions)->sortByDesc('created_at');
|
||||
return view('project.database.backups.executions', [
|
||||
'database' => $database,
|
||||
'backup' => $backup,
|
||||
'executions' => $executions,
|
||||
's3s' => currentTeam()->s3s,
|
||||
]);
|
||||
}
|
||||
|
||||
public function backups()
|
||||
{
|
||||
$project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
|
||||
if (!$project) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$environment = $project->load(['environments'])->environments->where('name', request()->route('environment_name'))->first()->load(['applications']);
|
||||
if (!$environment) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$database = $environment->databases()->where('uuid', request()->route('database_uuid'))->first();
|
||||
if (!$database) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
// No backups for redis
|
||||
if ($database->getMorphClass() === 'App\Models\StandaloneRedis') {
|
||||
return redirect()->route('project.database.configuration', [
|
||||
'project_uuid' => $project->uuid,
|
||||
'environment_name' => $environment->name,
|
||||
'database_uuid' => $database->uuid,
|
||||
]);
|
||||
}
|
||||
return view('project.database.backups.all', [
|
||||
'database' => $database,
|
||||
's3s' => currentTeam()->s3s,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
@@ -16,7 +17,7 @@ class DecideWhatToDoWithUser
|
||||
}
|
||||
if (!auth()->user() || !isCloud() || isInstanceAdmin()) {
|
||||
if (!isCloud() && showBoarding() && !in_array($request->path(), allowedPathsForBoardingAccounts())) {
|
||||
return redirect('boarding');
|
||||
return redirect()->route('boarding');
|
||||
}
|
||||
return $next($request);
|
||||
}
|
||||
@@ -24,27 +25,27 @@ class DecideWhatToDoWithUser
|
||||
if ($request->path() === 'verify' || in_array($request->path(), allowedPathsForInvalidAccounts()) || $request->routeIs('verify.verify')) {
|
||||
return $next($request);
|
||||
}
|
||||
return redirect('/verify');
|
||||
return redirect()->route('verify.email');
|
||||
}
|
||||
if (!isSubscriptionActive() && !isSubscriptionOnGracePeriod()) {
|
||||
if (!in_array($request->path(), allowedPathsForUnsubscribedAccounts())) {
|
||||
if (Str::startsWith($request->path(), 'invitations')) {
|
||||
return $next($request);
|
||||
}
|
||||
return redirect('subscription');
|
||||
return redirect()->route('subscription.index');
|
||||
}
|
||||
}
|
||||
if (showBoarding() && !in_array($request->path(), allowedPathsForBoardingAccounts())) {
|
||||
if (Str::startsWith($request->path(), 'invitations')) {
|
||||
return $next($request);
|
||||
}
|
||||
return redirect('boarding');
|
||||
return redirect()->route('boarding');
|
||||
}
|
||||
if (auth()->user()->hasVerifiedEmail() && $request->path() === 'verify') {
|
||||
return redirect('/');
|
||||
return redirect(RouteServiceProvider::HOME);
|
||||
}
|
||||
if (isSubscriptionActive() && $request->path() === 'subscription') {
|
||||
return redirect('/');
|
||||
return redirect(RouteServiceProvider::HOME);
|
||||
}
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ use Spatie\Url\Url;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
use Throwable;
|
||||
use Visus\Cuid2\Cuid2;
|
||||
use Yosymfony\Toml\Toml;
|
||||
|
||||
class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
||||
{
|
||||
@@ -73,6 +74,8 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
||||
private $env_args;
|
||||
private $docker_compose;
|
||||
private $docker_compose_base64;
|
||||
private ?string $nixpacks_plan = null;
|
||||
private ?string $nixpacks_type = null;
|
||||
private string $dockerfile_location = '/Dockerfile';
|
||||
private string $docker_compose_location = '/docker-compose.yml';
|
||||
private ?string $docker_compose_custom_start_command = null;
|
||||
@@ -164,11 +167,15 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
||||
$ips = collect([]);
|
||||
if (count($allContainers) > 0) {
|
||||
$allContainers = $allContainers[0];
|
||||
$allContainers = collect($allContainers)->sort()->values();
|
||||
foreach ($allContainers as $container) {
|
||||
$containerName = data_get($container, 'Name');
|
||||
if ($containerName === 'coolify-proxy') {
|
||||
continue;
|
||||
}
|
||||
if (preg_match('/-(\d{12})/', $containerName)) {
|
||||
continue;
|
||||
}
|
||||
$containerIp = data_get($container, 'IPv4Address');
|
||||
if ($containerName && $containerIp) {
|
||||
$containerIp = str($containerIp)->before('/');
|
||||
@@ -343,6 +350,9 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
||||
$this->generate_image_names();
|
||||
$this->check_image_locally_or_remotely();
|
||||
if (str($this->saved_outputs->get('local_image_found'))->isNotEmpty()) {
|
||||
$this->execute_remote_command([
|
||||
"echo 'Image found ({$this->production_image_name}) with the same Git Commit SHA. Restarting container.'",
|
||||
]);
|
||||
$this->create_workdir();
|
||||
$this->generate_compose_file();
|
||||
$this->rolling_update();
|
||||
@@ -446,8 +456,12 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
||||
$this->generate_image_names();
|
||||
$this->cleanup_git();
|
||||
$this->application->loadComposeFile(isInit: false);
|
||||
$composeFile = $this->application->parseCompose(pull_request_id: $this->pull_request_id);
|
||||
$yaml = Yaml::dump($composeFile->toArray(), 10);
|
||||
if ($this->application->settings->is_raw_compose_deployment_enabled) {
|
||||
$yaml = $composeFile = $this->application->docker_compose_raw;
|
||||
} else {
|
||||
$composeFile = $this->application->parseCompose(pull_request_id: $this->pull_request_id);
|
||||
$yaml = Yaml::dump($composeFile->toArray(), 10);
|
||||
}
|
||||
$this->docker_compose_base64 = base64_encode($yaml);
|
||||
$this->execute_remote_command([
|
||||
executeInDocker($this->deployment_uuid, "echo '{$this->docker_compose_base64}' | base64 -d > {$this->workdir}{$this->docker_compose_location}"), "hidden" => true
|
||||
@@ -571,7 +585,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
||||
$this->generate_nixpacks_confs();
|
||||
$this->generate_compose_file();
|
||||
$this->generate_build_env_variables();
|
||||
$this->add_build_env_variables_to_dockerfile();
|
||||
// $this->add_build_env_variables_to_dockerfile();
|
||||
$this->build_image();
|
||||
$this->rolling_update();
|
||||
}
|
||||
@@ -593,6 +607,24 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
||||
$this->rolling_update();
|
||||
}
|
||||
|
||||
private function framework_based_notification()
|
||||
{
|
||||
// Laravel old env variables
|
||||
if ($this->pull_request_id === 0) {
|
||||
$nixpacks_php_fallback_path = $this->application->environment_variables->where('key', 'NIXPACKS_PHP_FALLBACK_PATH')->first();
|
||||
$nixpacks_php_root_dir = $this->application->environment_variables->where('key', 'NIXPACKS_PHP_ROOT_DIR')->first();
|
||||
} else {
|
||||
$nixpacks_php_fallback_path = $this->application->environment_variables_preview->where('key', 'NIXPACKS_PHP_FALLBACK_PATH')->first();
|
||||
$nixpacks_php_root_dir = $this->application->environment_variables_preview->where('key', 'NIXPACKS_PHP_ROOT_DIR')->first();
|
||||
}
|
||||
if ($nixpacks_php_fallback_path?->value === '/index.php' && $nixpacks_php_root_dir?->value === '/app/public' && $this->newVersionIsHealthy === false) {
|
||||
$this->execute_remote_command(
|
||||
[
|
||||
"echo 'There was a change in how Laravel is deployed. Please update your environment variables to match the new deployment method. More details here: https://coolify.io/docs/frameworks/laravel#requirements'", 'type' => 'err'
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
private function rolling_update()
|
||||
{
|
||||
if ($this->server->isSwarm()) {
|
||||
@@ -629,6 +661,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
||||
$this->application_deployment_queue->addLogEntry("Rolling update completed.");
|
||||
}
|
||||
}
|
||||
$this->framework_based_notification();
|
||||
}
|
||||
private function health_check()
|
||||
{
|
||||
@@ -668,7 +701,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
||||
"echo 'Attempt {$counter} of {$this->application->health_check_retries} | Healthcheck status: {$this->saved_outputs->get('health_check')}'"
|
||||
],
|
||||
);
|
||||
if (Str::of($this->saved_outputs->get('health_check'))->contains('healthy')) {
|
||||
if (Str::of($this->saved_outputs->get('health_check'))->replace('"', '')->value() === 'healthy') {
|
||||
$this->newVersionIsHealthy = true;
|
||||
$this->application->update(['status' => 'running']);
|
||||
$this->execute_remote_command(
|
||||
@@ -678,6 +711,10 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
||||
);
|
||||
break;
|
||||
}
|
||||
if (Str::of($this->saved_outputs->get('health_check'))->replace('"', '')->value() === 'unhealthy') {
|
||||
$this->newVersionIsHealthy = false;
|
||||
break;
|
||||
}
|
||||
$counter++;
|
||||
sleep($this->application->health_check_interval);
|
||||
}
|
||||
@@ -862,20 +899,28 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
||||
[
|
||||
"echo -n 'Generating nixpacks configuration with: $nixpacks_command'",
|
||||
],
|
||||
[executeInDocker($this->deployment_uuid, $nixpacks_command)],
|
||||
[executeInDocker($this->deployment_uuid, "cp {$this->workdir}/.nixpacks/Dockerfile {$this->workdir}/Dockerfile")],
|
||||
[executeInDocker($this->deployment_uuid, "rm -f {$this->workdir}/.nixpacks/Dockerfile")]
|
||||
[executeInDocker($this->deployment_uuid, $nixpacks_command), "save" => "nixpacks_plan", "hidden" => true],
|
||||
[executeInDocker($this->deployment_uuid, "nixpacks detect {$this->workdir}"), "save" => "nixpacks_type", "hidden" => true],
|
||||
);
|
||||
if ($this->saved_outputs->get('nixpacks_type')) {
|
||||
$this->nixpacks_type = $this->saved_outputs->get('nixpacks_type');
|
||||
}
|
||||
if ($this->saved_outputs->get('nixpacks_plan')) {
|
||||
$this->nixpacks_plan = $this->saved_outputs->get('nixpacks_plan');
|
||||
if ($this->nixpacks_plan) {
|
||||
$parsed = Toml::Parse($this->nixpacks_plan);
|
||||
// Do any modifications here
|
||||
$cmds = collect(data_get($parsed, 'phases.setup.cmds', []));
|
||||
data_set($parsed, 'phases.setup.cmds', $cmds);
|
||||
$this->nixpacks_plan = json_encode($parsed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function nixpacks_build_cmd()
|
||||
{
|
||||
$this->generate_env_variables();
|
||||
$cacheKey = $this->application->uuid;
|
||||
if ($this->pull_request_id !== 0) {
|
||||
$cacheKey = "{$this->application->uuid}-pr-{$this->pull_request_id}";
|
||||
}
|
||||
$nixpacks_command = "nixpacks build --cache-key '{$cacheKey}' -o {$this->workdir} {$this->env_args} --no-error-without-start";
|
||||
$nixpacks_command = "nixpacks plan -f toml {$this->env_args}";
|
||||
if ($this->application->build_command) {
|
||||
$nixpacks_command .= " --build-cmd \"{$this->application->build_command}\"";
|
||||
}
|
||||
@@ -896,10 +941,16 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
||||
foreach ($this->application->nixpacks_environment_variables as $env) {
|
||||
$this->env_args->push("--env {$env->key}={$env->value}");
|
||||
}
|
||||
foreach ($this->application->build_environment_variables as $env) {
|
||||
$this->env_args->push("--env {$env->key}={$env->value}");
|
||||
}
|
||||
} else {
|
||||
foreach ($this->application->nixpacks_environment_variables_preview as $env) {
|
||||
$this->env_args->push("--env {$env->key}={$env->value}");
|
||||
}
|
||||
foreach ($this->application->build_environment_variables_preview as $env) {
|
||||
$this->env_args->push("--env {$env->key}={$env->value}");
|
||||
}
|
||||
}
|
||||
|
||||
$this->env_args = $this->env_args->implode(' ');
|
||||
@@ -954,7 +1005,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
||||
'memswap_limit' => $this->application->limits_memory_swap,
|
||||
'mem_swappiness' => $this->application->limits_memory_swappiness,
|
||||
'mem_reservation' => $this->application->limits_memory_reservation,
|
||||
'cpus' => (int) $this->application->limits_cpus,
|
||||
'cpus' => (float) $this->application->limits_cpus,
|
||||
'cpuset' => $this->application->limits_cpuset,
|
||||
'cpu_shares' => $this->application->limits_cpu_shares,
|
||||
]
|
||||
@@ -1130,6 +1181,11 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
||||
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('PORT'))->isEmpty()) {
|
||||
$environment_variables->push("PORT={$ports[0]}");
|
||||
}
|
||||
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('SOURCE_COMMIT'))->isEmpty()) {
|
||||
if (!is_null($this->commit)) {
|
||||
$environment_variables->push("SOURCE_COMMIT={$this->commit}");
|
||||
}
|
||||
}
|
||||
return $environment_variables->all();
|
||||
}
|
||||
|
||||
@@ -1188,6 +1244,9 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
||||
if ($this->application->settings->is_static || $this->application->build_pack === 'static') {
|
||||
if ($this->application->static_image) {
|
||||
$this->pull_latest_image($this->application->static_image);
|
||||
$this->execute_remote_command(
|
||||
["echo -n 'Continue with the building process.'"],
|
||||
);
|
||||
}
|
||||
if ($this->application->build_pack === 'static') {
|
||||
$dockerfile = base64_encode("FROM {$this->application->static_image}
|
||||
@@ -1214,9 +1273,29 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
|
||||
}
|
||||
}");
|
||||
} else {
|
||||
$this->execute_remote_command([
|
||||
executeInDocker($this->deployment_uuid, "docker build $this->buildTarget $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->build_image_name {$this->workdir}"), "hidden" => true
|
||||
]);
|
||||
if ($this->application->build_pack === 'nixpacks') {
|
||||
$this->nixpacks_plan = base64_encode($this->nixpacks_plan);
|
||||
$this->execute_remote_command([executeInDocker($this->deployment_uuid, "echo '{$this->nixpacks_plan}' | base64 -d > {$this->workdir}/thegameplan.json"), "hidden" => true]);
|
||||
if ($this->force_rebuild) {
|
||||
$this->execute_remote_command([
|
||||
executeInDocker($this->deployment_uuid, "nixpacks build -c thegameplan.json --no-cache --no-error-without-start -n {$this->build_image_name} {$this->workdir}"), "hidden" => true
|
||||
]);
|
||||
} else {
|
||||
$this->execute_remote_command([
|
||||
executeInDocker($this->deployment_uuid, "nixpacks build -c thegameplan.json --cache-key '{$this->application->uuid}' --no-error-without-start -n {$this->build_image_name} {$this->workdir}"), "hidden" => true
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
if ($this->force_rebuild) {
|
||||
$this->execute_remote_command([
|
||||
executeInDocker($this->deployment_uuid, "docker build --no-cache {$this->buildTarget} --network {$this->destination->network} -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->build_image_name {$this->workdir}"), "hidden" => true
|
||||
]);
|
||||
} else {
|
||||
$this->execute_remote_command([
|
||||
executeInDocker($this->deployment_uuid, "docker build {$this->buildTarget} --network {$this->destination->network} -f {$this->workdir}{$this->dockerfile_location} {$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/
|
||||
@@ -1249,19 +1328,39 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
|
||||
executeInDocker($this->deployment_uuid, "echo '{$nginx_config}' | base64 -d > {$this->workdir}/nginx.conf")
|
||||
],
|
||||
[
|
||||
executeInDocker($this->deployment_uuid, "docker build $this->addHosts --network host -f {$this->workdir}/Dockerfile {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true
|
||||
executeInDocker($this->deployment_uuid, "docker build {$this->addHosts} --network host -f {$this->workdir}/Dockerfile {$this->build_args} --progress plain -t {$this->production_image_name} {$this->workdir}"), "hidden" => true
|
||||
]
|
||||
);
|
||||
} else {
|
||||
// Pure Dockerfile based deployment
|
||||
if ($this->application->dockerfile) {
|
||||
$this->execute_remote_command([
|
||||
executeInDocker($this->deployment_uuid, "docker build --pull $this->buildTarget $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true
|
||||
executeInDocker($this->deployment_uuid, "docker build --pull {$this->buildTarget} {$this->addHosts} --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t {$this->production_image_name} {$this->workdir}"), "hidden" => true
|
||||
]);
|
||||
} else {
|
||||
$this->execute_remote_command([
|
||||
executeInDocker($this->deployment_uuid, "docker build $this->buildTarget $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true
|
||||
]);
|
||||
if ($this->application->build_pack === 'nixpacks') {
|
||||
$this->nixpacks_plan = base64_encode($this->nixpacks_plan);
|
||||
$this->execute_remote_command([executeInDocker($this->deployment_uuid, "echo '{$this->nixpacks_plan}' | base64 -d > {$this->workdir}/thegameplan.json"), "hidden" => true]);
|
||||
if ($this->force_rebuild) {
|
||||
$this->execute_remote_command([
|
||||
executeInDocker($this->deployment_uuid, "nixpacks build -c thegameplan.json --no-cache --no-error-without-start -n {$this->production_image_name} {$this->workdir}"), "hidden" => true
|
||||
]);
|
||||
} else {
|
||||
$this->execute_remote_command([
|
||||
executeInDocker($this->deployment_uuid, "nixpacks build -c thegameplan.json --cache-key '{$this->application->uuid}' --no-error-without-start -n {$this->production_image_name} {$this->workdir}"), "hidden" => true
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
if ($this->force_rebuild) {
|
||||
$this->execute_remote_command([
|
||||
executeInDocker($this->deployment_uuid, "docker build --no-cache {$this->buildTarget} {$this->addHosts} --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t {$this->production_image_name} {$this->workdir}"), "hidden" => true
|
||||
]);
|
||||
} else {
|
||||
$this->execute_remote_command([
|
||||
executeInDocker($this->deployment_uuid, "docker build {$this->buildTarget} {$this->addHosts} --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t {$this->production_image_name} {$this->workdir}"), "hidden" => true
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->execute_remote_command([
|
||||
@@ -1287,6 +1386,9 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
|
||||
});
|
||||
} else {
|
||||
$this->application_deployment_queue->addLogEntry("New container is not healthy, rolling back to the old container.");
|
||||
$this->application_deployment_queue->update([
|
||||
'status' => ApplicationDeploymentStatus::FAILED->value,
|
||||
]);
|
||||
$this->execute_remote_command(
|
||||
[executeInDocker($this->deployment_uuid, "docker rm -f $this->container_name >/dev/null 2>&1"), "hidden" => true, "ignore_errors" => true],
|
||||
);
|
||||
|
||||
@@ -45,7 +45,7 @@ class ContainerStatusJob implements ShouldQueue, ShouldBeEncrypted
|
||||
public function handle()
|
||||
{
|
||||
if (!$this->server->isServerReady($this->tries)) {
|
||||
throw new \RuntimeException('Server is not reachable.');
|
||||
return 'Server is not reachable.';
|
||||
};
|
||||
try {
|
||||
if ($this->server->isSwarm()) {
|
||||
@@ -162,6 +162,10 @@ class ContainerStatusJob implements ShouldQueue, ShouldBeEncrypted
|
||||
// Notify user that this container should not be there.
|
||||
}
|
||||
}
|
||||
if (data_get($container,'Name') === '/coolify-db') {
|
||||
$foundDatabases[] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
$serviceLabelId = data_get($labels, 'coolify.serviceId');
|
||||
if ($serviceLabelId) {
|
||||
@@ -212,7 +216,7 @@ class ContainerStatusJob implements ShouldQueue, ShouldBeEncrypted
|
||||
}
|
||||
$name = data_get($exitedService, 'name');
|
||||
$fqdn = data_get($exitedService, 'fqdn');
|
||||
$containerName = $name ? "$name ($fqdn)" : $fqdn;
|
||||
$containerName = $name ? "$name, available at $fqdn" : $fqdn;
|
||||
$projectUuid = data_get($service, 'environment.project.uuid');
|
||||
$serviceUuid = data_get($service, 'uuid');
|
||||
$environmentName = data_get($service, 'environment.name');
|
||||
|
||||
@@ -37,10 +37,6 @@ class ServerStatusJob implements ShouldQueue, ShouldBeEncrypted
|
||||
|
||||
public function handle()
|
||||
{
|
||||
ray("checking server status for {$this->server->id}");
|
||||
if (!$this->server->isServerReady(4)) {
|
||||
throw new \RuntimeException('Server is not reachable.');
|
||||
};
|
||||
try {
|
||||
if ($this->server->isFunctional()) {
|
||||
$this->cleanup(notify: false);
|
||||
|
||||
@@ -274,7 +274,7 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
|
||||
{
|
||||
$this->skipBoarding();
|
||||
return redirect()->route(
|
||||
'project.resources.new',
|
||||
'project.resource.create',
|
||||
[
|
||||
'project_uuid' => $this->createdProject->uuid,
|
||||
'environment_name' => 'production',
|
||||
|
||||
18
app/Livewire/CommandCenter/Index.php
Normal file
18
app/Livewire/CommandCenter/Index.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\CommandCenter;
|
||||
|
||||
use App\Models\Server;
|
||||
use Livewire\Component;
|
||||
|
||||
class Index extends Component
|
||||
{
|
||||
public $servers = [];
|
||||
public function mount() {
|
||||
$this->servers = Server::isReachable()->get();
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.command-center.index');
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,7 @@ class Form extends Component
|
||||
instant_remote_process(['docker network rm -f ' . $this->destination->network], $this->destination->server);
|
||||
}
|
||||
$this->destination->delete();
|
||||
return $this->redirectRoute('dashboard', navigate: true);
|
||||
return redirect()->route('dashboard');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ class Docker extends Component
|
||||
}
|
||||
}
|
||||
$this->createNetworkAndAttachToProxy();
|
||||
return $this->redirectRoute('destination.show', $docker->uuid, navigate: true);
|
||||
return redirect()->route('destination.show', $docker->uuid);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,10 @@ class ForcePasswordReset extends Component
|
||||
{
|
||||
$this->email = auth()->user()->email;
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.force-password-reset')->layout('layouts.simple');
|
||||
}
|
||||
public function submit()
|
||||
{
|
||||
try {
|
||||
@@ -35,7 +39,7 @@ class ForcePasswordReset extends Component
|
||||
if ($firstLogin) {
|
||||
send_internal_notification('First login for ' . auth()->user()->email);
|
||||
}
|
||||
return $this->redirectRoute('dashboard', navigate: true);
|
||||
return redirect()->route('dashboard');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
||||
@@ -5,21 +5,19 @@ namespace App\Livewire\Profile;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Component;
|
||||
|
||||
class Form extends Component
|
||||
class Index extends Component
|
||||
{
|
||||
public int $userId;
|
||||
public string $email;
|
||||
|
||||
#[Validate('required')]
|
||||
public string $name;
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->userId = auth()->user()->id;
|
||||
$this->name = auth()->user()->name;
|
||||
$this->email = auth()->user()->email;
|
||||
}
|
||||
|
||||
public function submit()
|
||||
|
||||
{
|
||||
@@ -34,4 +32,8 @@ class Form extends Component
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.profile.index');
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,7 @@ class AddEmpty extends Component
|
||||
'description' => $this->description,
|
||||
'team_id' => currentTeam()->id,
|
||||
]);
|
||||
return $this->redirectRoute('project.show', $project->uuid, navigate: true);
|
||||
return redirect()->route('project.show', $project->uuid);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
} finally {
|
||||
|
||||
@@ -27,10 +27,10 @@ class AddEnvironment extends Component
|
||||
'project_id' => $this->project->id,
|
||||
]);
|
||||
|
||||
return $this->redirectRoute('project.resources', [
|
||||
return redirect()->route('project.resource.index', [
|
||||
'project_uuid' => $this->project->uuid,
|
||||
'environment_name' => $environment->name,
|
||||
], navigate: true);
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
handleError($e, $this);
|
||||
} finally {
|
||||
|
||||
@@ -4,26 +4,27 @@ namespace App\Livewire\Project\Application;
|
||||
|
||||
use App\Models\Application;
|
||||
use App\Models\Server;
|
||||
use App\Models\StandaloneDocker;
|
||||
use Livewire\Component;
|
||||
|
||||
class Configuration extends Component
|
||||
{
|
||||
public Application $application;
|
||||
public $servers;
|
||||
protected $listeners = ['build_pack_updated' => '$refresh'];
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
|
||||
if (!$project) {
|
||||
return $this->redirectRoute('dashboard', navigate: true);
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$environment = $project->load(['environments'])->environments->where('name', request()->route('environment_name'))->first()->load(['applications']);
|
||||
if (!$environment) {
|
||||
return $this->redirectRoute('dashboard', navigate: true);
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$application = $environment->applications->where('uuid', request()->route('application_uuid'))->first();
|
||||
if (!$application) {
|
||||
return $this->redirectRoute('dashboard', navigate: true);
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$this->application = $application;
|
||||
$mainServer = $this->application->destination->server;
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Project\Application;
|
||||
namespace App\Livewire\Project\Application\Deployment;
|
||||
|
||||
use App\Models\Application;
|
||||
use Illuminate\Support\Collection;
|
||||
use Livewire\Component;
|
||||
|
||||
class Deployments extends Component
|
||||
class Index extends Component
|
||||
{
|
||||
public Application $application;
|
||||
public Array|Collection $deployments = [];
|
||||
public array|Collection $deployments = [];
|
||||
public int $deployments_count = 0;
|
||||
public string $current_url;
|
||||
public int $skip = 0;
|
||||
@@ -19,11 +19,28 @@ class Deployments extends Component
|
||||
protected $queryString = ['pull_request_id'];
|
||||
public function mount()
|
||||
{
|
||||
$project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
|
||||
if (!$project) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$environment = $project->load(['environments'])->environments->where('name', request()->route('environment_name'))->first()->load(['applications']);
|
||||
if (!$environment) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$application = $environment->applications->where('uuid', request()->route('application_uuid'))->first();
|
||||
if (!$application) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
['deployments' => $deployments, 'count' => $count] = $application->deployments(0, 40);
|
||||
$this->application = $application;
|
||||
$this->deployments = $deployments;
|
||||
$this->deployments_count = $count;
|
||||
$this->current_url = url()->current();
|
||||
$this->show_pull_request_only();
|
||||
$this->show_more();
|
||||
}
|
||||
private function show_pull_request_only() {
|
||||
private function show_pull_request_only()
|
||||
{
|
||||
if ($this->pull_request_id) {
|
||||
$this->deployments = $this->deployments->where('pull_request_id', $this->pull_request_id);
|
||||
}
|
||||
@@ -57,4 +74,8 @@ class Deployments extends Component
|
||||
$this->show_pull_request_only();
|
||||
$this->show_more();
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.project.application.deployment.index');
|
||||
}
|
||||
}
|
||||
@@ -1,35 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
namespace App\Livewire\Project\Application\Deployment;
|
||||
|
||||
use App\Models\Application;
|
||||
use App\Models\ApplicationDeploymentQueue;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Livewire\Component;
|
||||
|
||||
class ApplicationController extends Controller
|
||||
class Show extends Component
|
||||
{
|
||||
use AuthorizesRequests, ValidatesRequests;
|
||||
public Application $application;
|
||||
public ApplicationDeploymentQueue $application_deployment_queue;
|
||||
public string $deployment_uuid;
|
||||
public $isKeepAliveOn = true;
|
||||
protected $listeners = ['refreshQueue'];
|
||||
|
||||
public function deployments()
|
||||
{
|
||||
$project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
|
||||
if (!$project) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$environment = $project->load(['environments'])->environments->where('name', request()->route('environment_name'))->first()->load(['applications']);
|
||||
if (!$environment) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$application = $environment->applications->where('uuid', request()->route('application_uuid'))->first();
|
||||
if (!$application) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
['deployments' => $deployments, 'count' => $count] = $application->deployments(0, 40);
|
||||
return view('project.application.deployments', ['application' => $application, 'deployments' => $deployments, 'deployments_count' => $count]);
|
||||
}
|
||||
|
||||
public function deployment()
|
||||
{
|
||||
public function mount() {
|
||||
$deploymentUuid = request()->route('deployment_uuid');
|
||||
|
||||
$project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
|
||||
@@ -46,7 +31,7 @@ class ApplicationController extends Controller
|
||||
}
|
||||
// $activity = Activity::where('properties->type_uuid', '=', $deploymentUuid)->first();
|
||||
// if (!$activity) {
|
||||
// return redirect()->route('project.application.deployments', [
|
||||
// return redirect()->route('project.application.deployment.index', [
|
||||
// 'project_uuid' => $project->uuid,
|
||||
// 'environment_name' => $environment->name,
|
||||
// 'application_uuid' => $application->uuid,
|
||||
@@ -54,17 +39,32 @@ class ApplicationController extends Controller
|
||||
// }
|
||||
$application_deployment_queue = ApplicationDeploymentQueue::where('deployment_uuid', $deploymentUuid)->first();
|
||||
if (!$application_deployment_queue) {
|
||||
return redirect()->route('project.application.deployments', [
|
||||
return redirect()->route('project.application.deployment.index', [
|
||||
'project_uuid' => $project->uuid,
|
||||
'environment_name' => $environment->name,
|
||||
'application_uuid' => $application->uuid,
|
||||
]);
|
||||
}
|
||||
return view('project.application.deployment', [
|
||||
'application' => $application,
|
||||
// 'activity' => $activity,
|
||||
'application_deployment_queue' => $application_deployment_queue,
|
||||
'deployment_uuid' => $deploymentUuid,
|
||||
]);
|
||||
$this->application = $application;
|
||||
$this->application_deployment_queue = $application_deployment_queue;
|
||||
$this->deployment_uuid = $deploymentUuid;
|
||||
}
|
||||
|
||||
public function refreshQueue()
|
||||
{
|
||||
$this->application_deployment_queue->refresh();
|
||||
}
|
||||
|
||||
public function polling()
|
||||
{
|
||||
$this->dispatch('deploymentFinished');
|
||||
$this->application_deployment_queue->refresh();
|
||||
if (data_get($this->application_deployment_queue, 'status') == 'finished' || data_get($this->application_deployment_queue, 'status') == 'failed') {
|
||||
$this->isKeepAliveOn = false;
|
||||
}
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.project.application.deployment.show');
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Project\Application;
|
||||
|
||||
use App\Models\ApplicationDeploymentQueue;
|
||||
use Livewire\Component;
|
||||
|
||||
class DeploymentLogs extends Component
|
||||
{
|
||||
public ApplicationDeploymentQueue $application_deployment_queue;
|
||||
public $isKeepAliveOn = true;
|
||||
protected $listeners = ['refreshQueue'];
|
||||
|
||||
public function refreshQueue()
|
||||
{
|
||||
$this->application_deployment_queue->refresh();
|
||||
}
|
||||
|
||||
public function polling()
|
||||
{
|
||||
$this->dispatch('deploymentFinished');
|
||||
$this->application_deployment_queue->refresh();
|
||||
if (data_get($this->application_deployment_queue, 'status') == 'finished' || data_get($this->application_deployment_queue, 'status') == 'failed') {
|
||||
$this->isKeepAliveOn = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,6 +66,7 @@ class General extends Component
|
||||
'application.settings.is_static' => 'boolean|required',
|
||||
'application.docker_compose_custom_start_command' => 'nullable',
|
||||
'application.docker_compose_custom_build_command' => 'nullable',
|
||||
'application.settings.is_raw_compose_deployment_enabled' => 'boolean|required',
|
||||
];
|
||||
protected $validationAttributes = [
|
||||
'application.name' => 'name',
|
||||
@@ -98,6 +99,7 @@ class General extends Component
|
||||
'application.settings.is_static' => 'Is static',
|
||||
'application.docker_compose_custom_start_command' => 'Docker compose custom start command',
|
||||
'application.docker_compose_custom_build_command' => 'Docker compose custom build command',
|
||||
'application.settings.is_raw_compose_deployment_enabled' => 'Is raw compose deployment enabled',
|
||||
];
|
||||
public function mount()
|
||||
{
|
||||
@@ -114,6 +116,11 @@ class General extends Component
|
||||
}
|
||||
$this->isConfigurationChanged = $this->application->isConfigurationChanged();
|
||||
$this->customLabels = $this->application->parseContainerLabels();
|
||||
if (!$this->customLabels && $this->application->destination->server->proxyType() === 'TRAEFIK_V2') {
|
||||
$this->customLabels = str(implode(",", generateLabelsApplication($this->application)))->replace(',', "\n");
|
||||
$this->application->custom_labels = base64_encode($this->customLabels);
|
||||
$this->application->save();
|
||||
}
|
||||
$this->initialDockerComposeLocation = $this->application->docker_compose_location;
|
||||
$this->checkLabelUpdates();
|
||||
}
|
||||
@@ -158,12 +165,20 @@ class General extends Component
|
||||
if ($this->application->build_pack !== 'nixpacks') {
|
||||
$this->application->settings->is_static = false;
|
||||
$this->application->settings->save();
|
||||
} else {
|
||||
$this->application->ports_exposes = $this->ports_exposes = 3000;
|
||||
$this->resetDefaultLabels(false);
|
||||
}
|
||||
if ($this->application->build_pack === 'dockercompose') {
|
||||
$this->application->fqdn = null;
|
||||
$this->application->settings->save();
|
||||
}
|
||||
if ($this->application->build_pack === 'static') {
|
||||
$this->application->ports_exposes = $this->ports_exposes = 80;
|
||||
$this->resetDefaultLabels(false);
|
||||
}
|
||||
$this->submit();
|
||||
$this->dispatch('build_pack_updated');
|
||||
}
|
||||
public function checkLabelUpdates()
|
||||
{
|
||||
@@ -199,7 +214,12 @@ class General extends Component
|
||||
public function submit($showToaster = true)
|
||||
{
|
||||
try {
|
||||
ray($this->initialDockerComposeLocation, $this->application->docker_compose_location);
|
||||
if (!$this->customLabels && $this->application->destination->server->proxyType() === 'TRAEFIK_V2') {
|
||||
$this->customLabels = str(implode(",", generateLabelsApplication($this->application)))->replace(',', "\n");
|
||||
$this->application->custom_labels = base64_encode($this->customLabels);
|
||||
$this->application->save();
|
||||
}
|
||||
|
||||
if ($this->application->build_pack === 'dockercompose' && $this->initialDockerComposeLocation !== $this->application->docker_compose_location) {
|
||||
$this->loadComposeFile();
|
||||
}
|
||||
@@ -207,6 +227,7 @@ class General extends Component
|
||||
if ($this->ports_exposes !== $this->application->ports_exposes) {
|
||||
$this->resetDefaultLabels(false);
|
||||
}
|
||||
|
||||
if (data_get($this->application, 'build_pack') === 'dockerimage') {
|
||||
$this->validate([
|
||||
'application.docker_registry_image_name' => 'required',
|
||||
|
||||
@@ -39,7 +39,7 @@ class Heading extends Component
|
||||
} else {
|
||||
dispatch(new ServerStatusJob($this->application->destination->server));
|
||||
}
|
||||
if ($showNotification) $this->dispatch('success', 'Application status updated.');
|
||||
if ($showNotification) $this->dispatch('success', "Application ({$this->application->name}) status updated.");
|
||||
}
|
||||
|
||||
public function force_deploy_without_cache()
|
||||
@@ -60,12 +60,12 @@ class Heading extends Component
|
||||
force_rebuild: false,
|
||||
is_new_deployment: true,
|
||||
);
|
||||
return $this->redirectRoute('project.application.deployment', [
|
||||
return redirect()->route('project.application.deployment.show', [
|
||||
'project_uuid' => $this->parameters['project_uuid'],
|
||||
'application_uuid' => $this->parameters['application_uuid'],
|
||||
'deployment_uuid' => $this->deploymentUuid,
|
||||
'environment_name' => $this->parameters['environment_name'],
|
||||
], navigate: true);
|
||||
]);
|
||||
}
|
||||
public function deploy(bool $force_rebuild = false)
|
||||
{
|
||||
@@ -83,12 +83,12 @@ class Heading extends Component
|
||||
deployment_uuid: $this->deploymentUuid,
|
||||
force_rebuild: $force_rebuild,
|
||||
);
|
||||
$this->redirectRoute('project.application.deployment', [
|
||||
return redirect()->route('project.application.deployment.show', [
|
||||
'project_uuid' => $this->parameters['project_uuid'],
|
||||
'application_uuid' => $this->parameters['application_uuid'],
|
||||
'deployment_uuid' => $this->deploymentUuid,
|
||||
'environment_name' => $this->parameters['environment_name'],
|
||||
], navigate: true);
|
||||
]);
|
||||
}
|
||||
|
||||
protected function setDeploymentUuid()
|
||||
@@ -113,12 +113,12 @@ class Heading extends Component
|
||||
restart_only: true,
|
||||
is_new_deployment: true,
|
||||
);
|
||||
return $this->redirectRoute('project.application.deployment', [
|
||||
return redirect()->route('project.application.deployment.show', [
|
||||
'project_uuid' => $this->parameters['project_uuid'],
|
||||
'application_uuid' => $this->parameters['application_uuid'],
|
||||
'deployment_uuid' => $this->deploymentUuid,
|
||||
'environment_name' => $this->parameters['environment_name'],
|
||||
], navigate: true);
|
||||
]);
|
||||
}
|
||||
public function restart()
|
||||
{
|
||||
@@ -128,11 +128,11 @@ class Heading extends Component
|
||||
deployment_uuid: $this->deploymentUuid,
|
||||
restart_only: true,
|
||||
);
|
||||
return $this->redirectRoute('project.application.deployment', [
|
||||
return redirect()->route('project.application.deployment.show', [
|
||||
'project_uuid' => $this->parameters['project_uuid'],
|
||||
'application_uuid' => $this->parameters['application_uuid'],
|
||||
'deployment_uuid' => $this->deploymentUuid,
|
||||
'environment_name' => $this->parameters['environment_name'],
|
||||
], navigate: true);
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,12 +52,12 @@ class Previews extends Component
|
||||
force_rebuild: true,
|
||||
pull_request_id: $pull_request_id,
|
||||
);
|
||||
return $this->redirectRoute('project.application.deployment', [
|
||||
return redirect()->route('project.application.deployment.show', [
|
||||
'project_uuid' => $this->parameters['project_uuid'],
|
||||
'application_uuid' => $this->parameters['application_uuid'],
|
||||
'deployment_uuid' => $this->deployment_uuid,
|
||||
'environment_name' => $this->parameters['environment_name'],
|
||||
], navigate: true);
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
||||
@@ -29,12 +29,12 @@ class Rollback extends Component
|
||||
commit: $commit,
|
||||
force_rebuild: false,
|
||||
);
|
||||
return $this->redirectRoute('project.application.deployment', [
|
||||
return redirect()->route('project.application.deployment.show', [
|
||||
'project_uuid' => $this->parameters['project_uuid'],
|
||||
'application_uuid' => $this->parameters['application_uuid'],
|
||||
'deployment_uuid' => $deployment_uuid,
|
||||
'environment_name' => $this->parameters['environment_name'],
|
||||
], navigate: true);
|
||||
]);
|
||||
}
|
||||
|
||||
public function loadImages($showToast = false)
|
||||
|
||||
@@ -8,7 +8,7 @@ use App\Models\Server;
|
||||
use Livewire\Component;
|
||||
use Visus\Cuid2\Cuid2;
|
||||
|
||||
class CloneProject extends Component
|
||||
class CloneMe extends Component
|
||||
{
|
||||
public string $project_uuid;
|
||||
public string $environment_name;
|
||||
@@ -41,7 +41,7 @@ class CloneProject extends Component
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.project.clone-project');
|
||||
return view('livewire.project.clone-me');
|
||||
}
|
||||
|
||||
public function selectServer($server_id, $destination_id)
|
||||
@@ -152,10 +152,10 @@ class CloneProject extends Component
|
||||
}
|
||||
$newService->parse();
|
||||
}
|
||||
return $this->redirectRoute('project.resources', [
|
||||
return redirect()->route('project.resource.index', [
|
||||
'project_uuid' => $newProject->uuid,
|
||||
'environment_name' => $newEnvironment->name,
|
||||
], navigate: true);
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
41
app/Livewire/Project/Database/Backup/Execution.php
Normal file
41
app/Livewire/Project/Database/Backup/Execution.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Project\Database\Backup;
|
||||
|
||||
use Livewire\Component;
|
||||
|
||||
class Execution extends Component
|
||||
{
|
||||
public $database;
|
||||
public $backup;
|
||||
public $executions;
|
||||
public $s3s;
|
||||
public function mount() {
|
||||
$backup_uuid = request()->route('backup_uuid');
|
||||
$project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
|
||||
if (!$project) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$environment = $project->load(['environments'])->environments->where('name', request()->route('environment_name'))->first()->load(['applications']);
|
||||
if (!$environment) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$database = $environment->databases()->where('uuid', request()->route('database_uuid'))->first();
|
||||
if (!$database) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$backup = $database->scheduledBackups->where('uuid', $backup_uuid)->first();
|
||||
if (!$backup) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$executions = collect($backup->executions)->sortByDesc('created_at');
|
||||
$this->database = $database;
|
||||
$this->backup = $backup;
|
||||
$this->executions = $executions;
|
||||
$this->s3s = currentTeam()->s3s;
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.project.database.backup.execution');
|
||||
}
|
||||
}
|
||||
39
app/Livewire/Project/Database/Backup/Index.php
Normal file
39
app/Livewire/Project/Database/Backup/Index.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Project\Database\Backup;
|
||||
|
||||
use Livewire\Component;
|
||||
|
||||
class Index extends Component
|
||||
{
|
||||
public $database;
|
||||
public $s3s;
|
||||
public function mount() {
|
||||
$project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
|
||||
if (!$project) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$environment = $project->load(['environments'])->environments->where('name', request()->route('environment_name'))->first()->load(['applications']);
|
||||
if (!$environment) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$database = $environment->databases()->where('uuid', request()->route('database_uuid'))->first();
|
||||
if (!$database) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
// No backups for redis
|
||||
if ($database->getMorphClass() === 'App\Models\StandaloneRedis') {
|
||||
return redirect()->route('project.database.configuration', [
|
||||
'project_uuid' => $project->uuid,
|
||||
'environment_name' => $environment->name,
|
||||
'database_uuid' => $database->uuid,
|
||||
]);
|
||||
}
|
||||
$this->database = $database;
|
||||
$this->s3s = currentTeam()->s3s;
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.project.database.backup.index');
|
||||
}
|
||||
}
|
||||
@@ -50,9 +50,9 @@ class BackupEdit extends Component
|
||||
$url = $url->withoutQueryParameter('selectedBackupId');
|
||||
$url = $url->withFragment('backups');
|
||||
$url = $url->getPath() . "#{$url->getFragment()}";
|
||||
return $this->redirect($url,navigate: true);
|
||||
return redirect($url);
|
||||
} else {
|
||||
return $this->redirectRoute('project.database.backups.all', $this->parameters);
|
||||
return redirect()->route('project.database.backup.index', $this->parameters);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
29
app/Livewire/Project/Database/Configuration.php
Normal file
29
app/Livewire/Project/Database/Configuration.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Project\Database;
|
||||
|
||||
use Livewire\Component;
|
||||
|
||||
class Configuration extends Component
|
||||
{
|
||||
public $database;
|
||||
public function mount() {
|
||||
$project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
|
||||
if (!$project) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$environment = $project->load(['environments'])->environments->where('name', request()->route('environment_name'))->first()->load(['applications']);
|
||||
if (!$environment) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$database = $environment->databases()->where('uuid', request()->route('database_uuid'))->first();
|
||||
if (!$database) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$this->database = $database;
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.project.database.configuration');
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ class DeleteEnvironment extends Component
|
||||
$environment = Environment::findOrFail($this->environment_id);
|
||||
if ($environment->isEmpty()) {
|
||||
$environment->delete();
|
||||
return $this->redirectRoute('project.show', ['project_uuid' => $this->parameters['project_uuid']], navigate: true);
|
||||
return redirect()->route('project.show', ['project_uuid' => $this->parameters['project_uuid']]);
|
||||
}
|
||||
return $this->dispatch('error', 'Environment has defined resources, please delete them first.');
|
||||
}
|
||||
|
||||
@@ -25,6 +25,6 @@ class DeleteProject extends Component
|
||||
return $this->dispatch('error', 'Project has resources defined, please delete them first.');
|
||||
}
|
||||
$project->delete();
|
||||
return $this->redirectRoute('projects', navigate: true);
|
||||
return redirect()->route('project.index');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,15 @@ class Edit extends Component
|
||||
'project.name' => 'required|min:3|max:255',
|
||||
'project.description' => 'nullable|string|max:255',
|
||||
];
|
||||
public function mount() {
|
||||
$projectUuid = request()->route('project_uuid');
|
||||
$teamId = currentTeam()->id;
|
||||
$project = Project::where('team_id', $teamId)->where('uuid', $projectUuid)->first();
|
||||
if (!$project) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$this->project = $project;
|
||||
}
|
||||
|
||||
public function submit()
|
||||
{
|
||||
|
||||
41
app/Livewire/Project/EnvironmentEdit.php
Normal file
41
app/Livewire/Project/EnvironmentEdit.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Project;
|
||||
|
||||
use App\Models\Application;
|
||||
use App\Models\Project;
|
||||
use Livewire\Component;
|
||||
|
||||
class EnvironmentEdit extends Component
|
||||
{
|
||||
public Project $project;
|
||||
public Application $application;
|
||||
public $environment;
|
||||
public array $parameters;
|
||||
|
||||
protected $rules = [
|
||||
'environment.name' => 'required|min:3|max:255',
|
||||
'environment.description' => 'nullable|min:3|max:255',
|
||||
];
|
||||
public function mount() {
|
||||
$this->parameters = get_route_parameters();
|
||||
|
||||
$this->project = Project::ownedByCurrentTeam()->where('uuid', request()->route('project_uuid'))->first();
|
||||
$this->environment = $this->project->environments()->where('name', request()->route('environment_name'))->first();
|
||||
}
|
||||
|
||||
public function submit()
|
||||
{
|
||||
$this->validate();
|
||||
try {
|
||||
$this->environment->save();
|
||||
return redirect()->route('project.environment.edit', ['project_uuid' => $this->project->uuid, 'environment_name' => $this->environment->name]);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.project.environment-edit');
|
||||
}
|
||||
}
|
||||
21
app/Livewire/Project/Index.php
Normal file
21
app/Livewire/Project/Index.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Project;
|
||||
|
||||
use App\Models\Project;
|
||||
use App\Models\Server;
|
||||
use Livewire\Component;
|
||||
|
||||
class Index extends Component
|
||||
{
|
||||
public $projects;
|
||||
public $servers;
|
||||
public function mount() {
|
||||
$this->projects = Project::ownedByCurrentTeam()->get();
|
||||
$this->servers = Server::ownedByCurrentTeam()->count();
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.project.index');
|
||||
}
|
||||
}
|
||||
@@ -69,7 +69,7 @@ class DockerCompose extends Component
|
||||
|
||||
$service->parse(isNew: true);
|
||||
|
||||
return $this->redirectRoute('project.service.configuration', [
|
||||
return redirect()->route('project.service.configuration', [
|
||||
'service_uuid' => $service->uuid,
|
||||
'environment_name' => $environment->name,
|
||||
'project_uuid' => $project->uuid,
|
||||
|
||||
@@ -64,11 +64,11 @@ class DockerImage extends Component
|
||||
'name' => 'docker-image-' . $application->uuid,
|
||||
'fqdn' => $fqdn
|
||||
]);
|
||||
return $this->redirectRoute('project.application.configuration', [
|
||||
return redirect()->route('project.application.configuration', [
|
||||
'application_uuid' => $application->uuid,
|
||||
'environment_name' => $environment->name,
|
||||
'project_uuid' => $project->uuid,
|
||||
], navigate: false);
|
||||
]);
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
|
||||
@@ -13,6 +13,6 @@ class EmptyProject extends Component
|
||||
'name' => generate_random_name(),
|
||||
'team_id' => currentTeam()->id,
|
||||
]);
|
||||
return $this->redirectRoute('project.show', ['project_uuid' => $project->uuid, 'environment_name' => 'production'], navigate: false);
|
||||
return redirect()->route('project.show', ['project_uuid' => $project->uuid, 'environment_name' => 'production']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,11 +151,11 @@ class GithubPrivateRepository extends Component
|
||||
$application->name = generate_application_name($this->selected_repository_owner . '/' . $this->selected_repository_repo, $this->selected_branch_name, $application->uuid);
|
||||
$application->save();
|
||||
|
||||
return $this->redirectRoute('project.application.configuration', [
|
||||
return redirect()->route('project.application.configuration', [
|
||||
'application_uuid' => $application->uuid,
|
||||
'environment_name' => $environment->name,
|
||||
'project_uuid' => $project->uuid,
|
||||
], navigate: false);
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
||||
@@ -55,7 +55,11 @@ class GithubPrivateRepositoryDeployKey extends Component
|
||||
}
|
||||
$this->parameters = get_route_parameters();
|
||||
$this->query = request()->query();
|
||||
$this->private_keys = PrivateKey::where('team_id', currentTeam()->id)->where('id', '!=', 0)->get();
|
||||
if (isDev()) {
|
||||
$this->private_keys = PrivateKey::where('team_id', currentTeam()->id)->get();
|
||||
} else {
|
||||
$this->private_keys = PrivateKey::where('team_id', currentTeam()->id)->where('id', '!=', 0)->get();
|
||||
}
|
||||
}
|
||||
|
||||
public function instantSave()
|
||||
@@ -132,11 +136,11 @@ class GithubPrivateRepositoryDeployKey extends Component
|
||||
$application->name = generate_random_name($application->uuid);
|
||||
$application->save();
|
||||
|
||||
return $this->redirectRoute('project.application.configuration', [
|
||||
return redirect()->route('project.application.configuration', [
|
||||
'application_uuid' => $application->uuid,
|
||||
'environment_name' => $environment->name,
|
||||
'project_uuid' => $project->uuid,
|
||||
], navigate: false);
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
||||
@@ -184,11 +184,11 @@ class PublicGitRepository extends Component
|
||||
$application->fqdn = $fqdn;
|
||||
$application->save();
|
||||
|
||||
return $this->redirectRoute('project.application.configuration', [
|
||||
return redirect()->route('project.application.configuration', [
|
||||
'application_uuid' => $application->uuid,
|
||||
'environment_name' => $environment->name,
|
||||
'project_uuid' => $project->uuid,
|
||||
], navigate: false);
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
||||
@@ -55,10 +55,10 @@ class Select extends Component
|
||||
|
||||
public function updatedSelectedEnvironment()
|
||||
{
|
||||
return $this->redirectRoute('project.resources.new', [
|
||||
return redirect()->route('project.resource.create', [
|
||||
'project_uuid' => $this->parameters['project_uuid'],
|
||||
'environment_name' => $this->selectedEnvironment,
|
||||
], navigate: true);
|
||||
]);
|
||||
}
|
||||
|
||||
// public function addExistingPostgresql()
|
||||
@@ -157,7 +157,7 @@ class Select extends Component
|
||||
public function setDestination(string $destination_uuid)
|
||||
{
|
||||
$this->destination_uuid = $destination_uuid;
|
||||
return redirect()->route('project.resources.new', [
|
||||
return redirect()->route('project.resource.create', [
|
||||
'project_uuid' => $this->parameters['project_uuid'],
|
||||
'environment_name' => $this->parameters['environment_name'],
|
||||
'type' => $this->type,
|
||||
|
||||
@@ -70,10 +70,10 @@ CMD ["nginx", "-g", "daemon off;"]
|
||||
'fqdn' => $fqdn
|
||||
]);
|
||||
|
||||
return $this->redirectRoute('project.application.configuration', [
|
||||
return redirect()->route('project.application.configuration', [
|
||||
'application_uuid' => $application->uuid,
|
||||
'environment_name' => $environment->name,
|
||||
'project_uuid' => $project->uuid,
|
||||
], navigate: false);
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,52 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
namespace App\Livewire\Project\Resource;
|
||||
|
||||
use App\Models\EnvironmentVariable;
|
||||
use App\Models\Project;
|
||||
use App\Models\Server;
|
||||
use App\Models\Service;
|
||||
use App\Models\StandaloneDocker;
|
||||
use Illuminate\Support\Str;
|
||||
use Livewire\Component;
|
||||
|
||||
class ProjectController extends Controller
|
||||
class Create extends Component
|
||||
{
|
||||
public function all()
|
||||
{
|
||||
return view('projects', [
|
||||
'projects' => Project::ownedByCurrentTeam()->get(),
|
||||
'servers' => Server::ownedByCurrentTeam()->count(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function edit()
|
||||
{
|
||||
$projectUuid = request()->route('project_uuid');
|
||||
$teamId = currentTeam()->id;
|
||||
$project = Project::where('team_id', $teamId)->where('uuid', $projectUuid)->first();
|
||||
if (!$project) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
return view('project.edit', ['project' => $project]);
|
||||
}
|
||||
|
||||
public function show()
|
||||
{
|
||||
$projectUuid = request()->route('project_uuid');
|
||||
$teamId = currentTeam()->id;
|
||||
|
||||
$project = Project::where('team_id', $teamId)->where('uuid', $projectUuid)->first();
|
||||
if (!$project) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$project->load(['environments']);
|
||||
return view('project.show', ['project' => $project]);
|
||||
}
|
||||
|
||||
public function new()
|
||||
{
|
||||
public $type;
|
||||
public function mount() {
|
||||
$services = getServiceTemplates();
|
||||
$type = Str::of(request()->query('type'));
|
||||
$type = str(request()->query('type'));
|
||||
$destination_uuid = request()->query('destination');
|
||||
$server_id = request()->query('server_id');
|
||||
|
||||
@@ -81,14 +47,14 @@ class ProjectController extends Controller
|
||||
$oneClickService = data_get($services, "$oneClickServiceName.compose");
|
||||
$oneClickDotEnvs = data_get($services, "$oneClickServiceName.envs", null);
|
||||
if ($oneClickDotEnvs) {
|
||||
$oneClickDotEnvs = Str::of(base64_decode($oneClickDotEnvs))->split('/\r\n|\r|\n/')->filter(function ($value) {
|
||||
$oneClickDotEnvs = str(base64_decode($oneClickDotEnvs))->split('/\r\n|\r|\n/')->filter(function ($value) {
|
||||
return !empty($value);
|
||||
});
|
||||
}
|
||||
if ($oneClickService) {
|
||||
$destination = StandaloneDocker::whereUuid($destination_uuid)->first();
|
||||
$service = Service::create([
|
||||
'name' => "$oneClickServiceName-" . Str::random(10),
|
||||
'name' => "$oneClickServiceName-" . str()->random(10),
|
||||
'docker_compose_raw' => base64_decode($oneClickService),
|
||||
'environment_id' => $environment->id,
|
||||
'server_id' => (int) $server_id,
|
||||
@@ -99,8 +65,8 @@ class ProjectController extends Controller
|
||||
$service->save();
|
||||
if ($oneClickDotEnvs?->count() > 0) {
|
||||
$oneClickDotEnvs->each(function ($value) use ($service) {
|
||||
$key = Str::before($value, '=');
|
||||
$value = Str::of(Str::after($value, '='));
|
||||
$key = str()->before($value, '=');
|
||||
$value = str(str()->after($value, '='));
|
||||
$generatedValue = $value;
|
||||
if ($value->contains('SERVICE_')) {
|
||||
$command = $value->after('SERVICE_')->beforeLast('_');
|
||||
@@ -123,24 +89,10 @@ class ProjectController extends Controller
|
||||
]);
|
||||
}
|
||||
}
|
||||
return view('project.new', [
|
||||
'type' => $type->value()
|
||||
]);
|
||||
$this->type = $type->value();
|
||||
}
|
||||
|
||||
public function resources()
|
||||
public function render()
|
||||
{
|
||||
$project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
|
||||
if (!$project) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$environment = $project->load(['environments'])->environments->where('name', request()->route('environment_name'))->first();
|
||||
if (!$environment) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
return view('project.resources', [
|
||||
'project' => $project,
|
||||
'environment' => $environment
|
||||
]);
|
||||
return view('livewire.project.resource.create');
|
||||
}
|
||||
}
|
||||
29
app/Livewire/Project/Resource/Index.php
Normal file
29
app/Livewire/Project/Resource/Index.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Project\Resource;
|
||||
|
||||
use App\Models\Environment;
|
||||
use App\Models\Project;
|
||||
use Livewire\Component;
|
||||
|
||||
class Index extends Component
|
||||
{
|
||||
public Project $project;
|
||||
public Environment $environment;
|
||||
public function mount () {
|
||||
$project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
|
||||
if (!$project) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$environment = $project->load(['environments'])->environments->where('name', request()->route('environment_name'))->first();
|
||||
if (!$environment) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$this->project = $project;
|
||||
$this->environment = $environment;
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.project.resource.index');
|
||||
}
|
||||
}
|
||||
@@ -41,7 +41,7 @@ class Application extends Component
|
||||
try {
|
||||
$this->application->delete();
|
||||
$this->dispatch('success', 'Application deleted successfully.');
|
||||
return $this->redirectRoute('project.service.configuration', $this->parameters, navigate: true);
|
||||
return redirect()->route('project.service.configuration', $this->parameters);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
||||
54
app/Livewire/Project/Service/Configuration.php
Normal file
54
app/Livewire/Project/Service/Configuration.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Project\Service;
|
||||
|
||||
use App\Jobs\ContainerStatusJob;
|
||||
use App\Models\Service;
|
||||
use Livewire\Component;
|
||||
|
||||
class Configuration extends Component
|
||||
{
|
||||
public Service $service;
|
||||
public $applications;
|
||||
public $databases;
|
||||
public array $parameters;
|
||||
public array $query;
|
||||
public function getListeners()
|
||||
{
|
||||
$userId = auth()->user()->id;
|
||||
return [
|
||||
"echo-private:user.{$userId},ServiceStatusChanged" => 'checkStatus',
|
||||
"refreshStacks",
|
||||
"checkStatus",
|
||||
];
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.project.service.configuration');
|
||||
}
|
||||
public function mount()
|
||||
{
|
||||
$this->parameters = get_route_parameters();
|
||||
$this->query = request()->query();
|
||||
$this->service = Service::whereUuid($this->parameters['service_uuid'])->firstOrFail();
|
||||
$this->applications = $this->service->applications->sort();
|
||||
$this->databases = $this->service->databases->sort();
|
||||
}
|
||||
public function checkStatus()
|
||||
{
|
||||
dispatch_sync(new ContainerStatusJob($this->service->server));
|
||||
$this->refreshStacks();
|
||||
$this->dispatch('serviceStatusChanged');
|
||||
}
|
||||
public function refreshStacks()
|
||||
{
|
||||
$this->applications = $this->service->applications->sort();
|
||||
$this->applications->each(function ($application) {
|
||||
$application->refresh();
|
||||
});
|
||||
$this->databases = $this->service->databases->sort();
|
||||
$this->databases->each(function ($database) {
|
||||
$database->refresh();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -2,53 +2,51 @@
|
||||
|
||||
namespace App\Livewire\Project\Service;
|
||||
|
||||
use App\Jobs\ContainerStatusJob;
|
||||
use App\Models\Service;
|
||||
use App\Models\ServiceApplication;
|
||||
use App\Models\ServiceDatabase;
|
||||
use Illuminate\Support\Collection;
|
||||
use Livewire\Component;
|
||||
|
||||
class Index extends Component
|
||||
{
|
||||
public Service $service;
|
||||
public $applications;
|
||||
public $databases;
|
||||
public ?ServiceApplication $serviceApplication = null;
|
||||
public ?ServiceDatabase $serviceDatabase = null;
|
||||
public array $parameters;
|
||||
public array $query;
|
||||
public function getListeners()
|
||||
public Collection $services;
|
||||
public $s3s;
|
||||
|
||||
protected $listeners = ['generateDockerCompose'];
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$userId = auth()->user()->id;
|
||||
return [
|
||||
"echo-private:user.{$userId},ServiceStatusChanged" => 'checkStatus',
|
||||
"refreshStacks",
|
||||
"checkStatus",
|
||||
];
|
||||
try {
|
||||
$this->services = collect([]);
|
||||
$this->parameters = get_route_parameters();
|
||||
$this->query = request()->query();
|
||||
$this->service = Service::whereUuid($this->parameters['service_uuid'])->firstOrFail();
|
||||
$service = $this->service->applications()->whereName($this->parameters['service_name'])->first();
|
||||
if ($service) {
|
||||
$this->serviceApplication = $service;
|
||||
$this->serviceApplication->getFilesFromServer();
|
||||
} else {
|
||||
$this->serviceDatabase = $this->service->databases()->whereName($this->parameters['service_name'])->first();
|
||||
$this->serviceDatabase->getFilesFromServer();
|
||||
}
|
||||
$this->s3s = currentTeam()->s3s;
|
||||
} catch(\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
||||
}
|
||||
public function generateDockerCompose()
|
||||
{
|
||||
$this->service->parse();
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.project.service.index');
|
||||
}
|
||||
public function mount()
|
||||
{
|
||||
$this->parameters = get_route_parameters();
|
||||
$this->query = request()->query();
|
||||
$this->service = Service::whereUuid($this->parameters['service_uuid'])->firstOrFail();
|
||||
$this->applications = $this->service->applications->sort();
|
||||
$this->databases = $this->service->databases->sort();
|
||||
}
|
||||
public function checkStatus()
|
||||
{
|
||||
dispatch_sync(new ContainerStatusJob($this->service->server));
|
||||
$this->refreshStacks();
|
||||
$this->dispatch('serviceStatusChanged');
|
||||
}
|
||||
public function refreshStacks()
|
||||
{
|
||||
$this->applications = $this->service->applications->sort();
|
||||
$this->applications->each(function ($application) {
|
||||
$application->refresh();
|
||||
});
|
||||
$this->databases = $this->service->databases->sort();
|
||||
$this->databases->each(function ($database) {
|
||||
$database->refresh();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Project\Service;
|
||||
|
||||
use App\Models\Service;
|
||||
use App\Models\ServiceApplication;
|
||||
use App\Models\ServiceDatabase;
|
||||
use Illuminate\Support\Collection;
|
||||
use Livewire\Component;
|
||||
|
||||
class Show extends Component
|
||||
{
|
||||
public Service $service;
|
||||
public ?ServiceApplication $serviceApplication = null;
|
||||
public ?ServiceDatabase $serviceDatabase = null;
|
||||
public array $parameters;
|
||||
public array $query;
|
||||
public Collection $services;
|
||||
public $s3s;
|
||||
|
||||
protected $listeners = ['generateDockerCompose'];
|
||||
|
||||
public function mount()
|
||||
{
|
||||
try {
|
||||
$this->services = collect([]);
|
||||
$this->parameters = get_route_parameters();
|
||||
$this->query = request()->query();
|
||||
$this->service = Service::whereUuid($this->parameters['service_uuid'])->firstOrFail();
|
||||
$service = $this->service->applications()->whereName($this->parameters['service_name'])->first();
|
||||
if ($service) {
|
||||
$this->serviceApplication = $service;
|
||||
$this->serviceApplication->getFilesFromServer();
|
||||
} else {
|
||||
$this->serviceDatabase = $this->service->databases()->whereName($this->parameters['service_name'])->first();
|
||||
$this->serviceDatabase->getFilesFromServer();
|
||||
}
|
||||
$this->s3s = currentTeam()->s3s;
|
||||
} catch(\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
||||
}
|
||||
public function generateDockerCompose()
|
||||
{
|
||||
$this->service->parse();
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.project.service.show');
|
||||
}
|
||||
}
|
||||
@@ -25,10 +25,10 @@ class Danger extends Component
|
||||
{
|
||||
try {
|
||||
DeleteResourceJob::dispatchSync($this->resource);
|
||||
return $this->redirectRoute('project.resources', [
|
||||
return redirect()->route('project.resource.index', [
|
||||
'project_uuid' => $this->projectUuid,
|
||||
'environment_name' => $this->environmentName
|
||||
], navigate: true);
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
||||
@@ -139,6 +139,18 @@ class All extends Component
|
||||
case 'standalone-postgresql':
|
||||
$environment->standalone_postgresql_id = $this->resource->id;
|
||||
break;
|
||||
case 'standalone-redis':
|
||||
$environment->standalone_redis_id = $this->resource->id;
|
||||
break;
|
||||
case 'standalone-mongodb':
|
||||
$environment->standalone_mongodb_id = $this->resource->id;
|
||||
break;
|
||||
case 'standalone-mysql':
|
||||
$environment->standalone_mysql_id = $this->resource->id;
|
||||
break;
|
||||
case 'standalone-mariadb':
|
||||
$environment->standalone_mariadb_id = $this->resource->id;
|
||||
break;
|
||||
case 'service':
|
||||
$environment->service_id = $this->resource->id;
|
||||
break;
|
||||
|
||||
@@ -10,7 +10,6 @@ use App\Models\StandaloneMongodb;
|
||||
use App\Models\StandaloneMysql;
|
||||
use App\Models\StandalonePostgresql;
|
||||
use App\Models\StandaloneRedis;
|
||||
use Illuminate\Support\Sleep;
|
||||
use Livewire\Component;
|
||||
|
||||
class ExecuteContainerCommand extends Component
|
||||
|
||||
26
app/Livewire/Project/Show.php
Normal file
26
app/Livewire/Project/Show.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Project;
|
||||
|
||||
use App\Models\Project;
|
||||
use Livewire\Component;
|
||||
|
||||
class Show extends Component
|
||||
{
|
||||
public Project $project;
|
||||
public function mount() {
|
||||
$projectUuid = request()->route('project_uuid');
|
||||
$teamId = currentTeam()->id;
|
||||
|
||||
$project = Project::where('team_id', $teamId)->where('uuid', $projectUuid)->first();
|
||||
if (!$project) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$project->load(['environments']);
|
||||
$this->project = $project;
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.project.show');
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\PrivateKey;
|
||||
namespace App\Livewire\Security\PrivateKey;
|
||||
|
||||
use App\Models\PrivateKey;
|
||||
use DanHarrin\LivewireRateLimiting\WithRateLimiting;
|
||||
@@ -67,9 +67,9 @@ class Create extends Component
|
||||
'team_id' => currentTeam()->id
|
||||
]);
|
||||
if ($this->from === 'server') {
|
||||
return $this->redirectRoute('server.create', navigate: true);
|
||||
return redirect()->route('server.create');
|
||||
}
|
||||
return $this->redirectRoute('security.private-key.show', ['private_key_uuid' => $private_key->uuid], navigate: true);
|
||||
return redirect()->route('security.private-key.show', ['private_key_uuid' => $private_key->uuid]);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\PrivateKey;
|
||||
namespace App\Livewire\Security\PrivateKey;
|
||||
|
||||
use App\Models\PrivateKey;
|
||||
use Livewire\Component;
|
||||
|
||||
class Change extends Component
|
||||
class Show extends Component
|
||||
{
|
||||
public PrivateKey $private_key;
|
||||
public $public_key;
|
||||
@@ -24,6 +24,7 @@ class Change extends Component
|
||||
public function mount()
|
||||
{
|
||||
try {
|
||||
$this->private_key = PrivateKey::ownedByCurrentTeam(['name', 'description', 'private_key', 'is_git_related'])->whereUuid(request()->private_key_uuid)->firstOrFail();
|
||||
$this->public_key = $this->private_key->publicKey();
|
||||
}catch(\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
@@ -35,7 +36,7 @@ class Change extends Component
|
||||
if ($this->private_key->isEmpty()) {
|
||||
$this->private_key->delete();
|
||||
currentTeam()->privateKeys = PrivateKey::where('team_id', currentTeam()->id)->get();
|
||||
return $this->redirectRoute('security.private-key.index', navigate: true);
|
||||
return redirect()->route('security.private-key.index');
|
||||
}
|
||||
$this->dispatch('error', 'This private key is in use and cannot be deleted. Please delete all servers, applications, and GitHub/GitLab apps that use this private key before deleting it.');
|
||||
} catch (\Throwable $e) {
|
||||
@@ -19,7 +19,7 @@ class Delete extends Component
|
||||
return;
|
||||
}
|
||||
$this->server->delete();
|
||||
return $this->redirectRoute('server.all', navigate: true);
|
||||
return redirect()->route('server.index');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ class Show extends Component
|
||||
try {
|
||||
$this->server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->first();
|
||||
if (is_null($this->server)) {
|
||||
return $this->redirectRoute('server.all', navigate: true);
|
||||
return redirect()->route('server.index');
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
|
||||
@@ -6,7 +6,7 @@ use App\Models\Server;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Livewire\Component;
|
||||
|
||||
class All extends Component
|
||||
class Index extends Component
|
||||
{
|
||||
public ?Collection $servers = null;
|
||||
|
||||
@@ -15,6 +15,6 @@ class All extends Component
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.server.all');
|
||||
return view('livewire.server.index');
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@ class LogDrains extends Component
|
||||
try {
|
||||
$server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->first();
|
||||
if (is_null($server)) {
|
||||
return $this->redirectRoute('server.all', navigate: true);
|
||||
return redirect()->route('server.index');
|
||||
}
|
||||
$this->server = $server;
|
||||
} catch (\Throwable $e) {
|
||||
|
||||
@@ -93,7 +93,7 @@ class ByIp extends Component
|
||||
$server->settings->is_swarm_worker = $this->is_swarm_worker;
|
||||
$server->settings->save();
|
||||
$server->addInitialNetwork();
|
||||
return $this->redirectRoute('server.show', $server->uuid);
|
||||
return redirect()->route('server.show', $server->uuid);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ class Show extends Component
|
||||
try {
|
||||
$this->server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->first();
|
||||
if (is_null($this->server)) {
|
||||
return $this->redirectRoute('server.all', navigate: true);
|
||||
return redirect()->route('server.index');
|
||||
}
|
||||
$this->privateKeys = PrivateKey::ownedByCurrentTeam()->get()->where('is_git_related', false);
|
||||
} catch (\Throwable $e) {
|
||||
|
||||
@@ -15,7 +15,7 @@ class Logs extends Component
|
||||
try {
|
||||
$this->server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->first();
|
||||
if (is_null($this->server)) {
|
||||
return $this->redirectRoute('server.all', navigate: true);
|
||||
return redirect()->route('server.index');
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
|
||||
@@ -20,7 +20,7 @@ class Show extends Component
|
||||
try {
|
||||
$this->server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->first();
|
||||
if (is_null($this->server)) {
|
||||
return $this->redirectRoute('server.all', navigate: true);
|
||||
return redirect()->route('server.index');
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
|
||||
@@ -17,7 +17,7 @@ class Show extends Component
|
||||
try {
|
||||
$this->server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->first();
|
||||
if (is_null($this->server)) {
|
||||
return $this->redirectRoute('server.all', navigate: true);
|
||||
return redirect()->route('server.index');
|
||||
}
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
|
||||
38
app/Livewire/Settings/Index.php
Normal file
38
app/Livewire/Settings/Index.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Settings;
|
||||
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\S3Storage;
|
||||
use App\Models\StandalonePostgresql;
|
||||
use Livewire\Component;
|
||||
|
||||
class Index extends Component
|
||||
{
|
||||
public InstanceSettings $settings;
|
||||
public StandalonePostgresql $database;
|
||||
public $s3s;
|
||||
public function mount()
|
||||
{
|
||||
if (isInstanceAdmin()) {
|
||||
$settings = InstanceSettings::get();
|
||||
$database = StandalonePostgresql::whereName('coolify-db')->first();
|
||||
$s3s = S3Storage::whereTeamId(0)->get() ?? [];
|
||||
if ($database) {
|
||||
if ($database->status !== 'running') {
|
||||
$database->status = 'running';
|
||||
$database->save();
|
||||
}
|
||||
$this->database = $database;
|
||||
}
|
||||
$this->settings = $settings;
|
||||
$this->s3s = $s3s;
|
||||
} else {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.settings.index');
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire;
|
||||
namespace App\Livewire\Settings;
|
||||
|
||||
use App\Actions\License\CheckResaleLicense;
|
||||
use App\Models\InstanceSettings;
|
||||
use Livewire\Component;
|
||||
|
||||
class CheckLicense extends Component
|
||||
class License extends Component
|
||||
{
|
||||
public InstanceSettings|null $settings = null;
|
||||
public InstanceSettings $settings;
|
||||
public string|null $instance_id = null;
|
||||
|
||||
protected $rules = [
|
||||
'settings.resale_license' => 'nullable',
|
||||
'settings.is_resale_license_active' => 'nullable',
|
||||
@@ -20,12 +21,17 @@ class CheckLicense extends Component
|
||||
'settings.is_resale_license_active' => 'Is License Active',
|
||||
];
|
||||
|
||||
public function mount()
|
||||
{
|
||||
public function mount () {
|
||||
if (!isCloud()) {
|
||||
abort(404);
|
||||
}
|
||||
$this->instance_id = config('app.id');
|
||||
$this->settings = InstanceSettings::get();
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.settings.license')->layout('layouts.subscription');
|
||||
}
|
||||
public function submit()
|
||||
{
|
||||
$this->validate();
|
||||
@@ -37,7 +43,7 @@ class CheckLicense extends Component
|
||||
} catch (\Throwable $e) {
|
||||
session()->flash('error', 'Something went wrong. Please contact support. <br>Error: ' . $e->getMessage());
|
||||
ray($e->getMessage());
|
||||
return $this->redirect('/settings/license', navigate: true);
|
||||
return redirect()->route('settings.license');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,7 +41,7 @@ class Change extends Component
|
||||
$github_app_uuid = request()->github_app_uuid;
|
||||
$this->github_app = GithubApp::where('uuid', $github_app_uuid)->first();
|
||||
if (!$this->github_app) {
|
||||
return $this->redirectRoute('source.all', navigate: true);
|
||||
return redirect()->route('source.all');
|
||||
}
|
||||
$settings = InstanceSettings::get();
|
||||
$this->github_app->makeVisible('client_secret')->makeVisible('webhook_secret');
|
||||
@@ -67,7 +67,7 @@ class Change extends Component
|
||||
$type = data_get($parameters, 'type');
|
||||
$destination = data_get($parameters, 'destination');
|
||||
session()->forget('from');
|
||||
return $this->redirectRoute($back, [
|
||||
return redirect()->route($back, [
|
||||
'environment_name' => $environment_name,
|
||||
'project_uuid' => $project_uuid,
|
||||
'type' => $type,
|
||||
@@ -117,7 +117,7 @@ class Change extends Component
|
||||
{
|
||||
try {
|
||||
$this->github_app->delete();
|
||||
return $this->redirectRoute('source.all', navigate: true);
|
||||
return redirect()->route('source.all');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ class Create extends Component
|
||||
if (session('from')) {
|
||||
session(['from' => session('from') + ['source_id' => $github_app->id]]);
|
||||
}
|
||||
return $this->redirectRoute('source.github.show', ['github_app_uuid' => $github_app->uuid], navigate: true);
|
||||
return redirect()->route('source.github.show', ['github_app_uuid' => $github_app->uuid]);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
||||
@@ -3,15 +3,16 @@
|
||||
namespace App\Livewire\Subscription;
|
||||
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use Livewire\Component;
|
||||
|
||||
class Show extends Component
|
||||
class Index extends Component
|
||||
{
|
||||
public InstanceSettings $settings;
|
||||
public bool $alreadySubscribed = false;
|
||||
public function mount() {
|
||||
if (!isCloud()) {
|
||||
return $this->redirect('/', navigate: true);
|
||||
return redirect(RouteServiceProvider::HOME);
|
||||
}
|
||||
$this->settings = InstanceSettings::get();
|
||||
$this->alreadySubscribed = currentTeam()->subscription()->exists();
|
||||
@@ -25,6 +26,6 @@ class Show extends Component
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.subscription.show')->layout('layouts.subscription');
|
||||
return view('livewire.subscription.index')->layout('layouts.subscription');
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ class Create extends Component
|
||||
]);
|
||||
auth()->user()->teams()->attach($team, ['role' => 'admin']);
|
||||
refreshSession();
|
||||
return $this->redirectRoute('team.index', navigate: true);
|
||||
return redirect()->route('team.index');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Team;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Livewire\Component;
|
||||
|
||||
class Delete extends Component
|
||||
{
|
||||
public function delete()
|
||||
{
|
||||
$currentTeam = currentTeam();
|
||||
$currentTeam->delete();
|
||||
|
||||
$currentTeam->members->each(function ($user) use ($currentTeam) {
|
||||
if ($user->id === auth()->user()->id) {
|
||||
return;
|
||||
}
|
||||
$user->teams()->detach($currentTeam);
|
||||
$session = DB::table('sessions')->where('user_id', $user->id)->first();
|
||||
if ($session) {
|
||||
DB::table('sessions')->where('id', $session->id)->delete();
|
||||
}
|
||||
});
|
||||
|
||||
refreshSession();
|
||||
return $this->redirectRoute('team.index', navigate: true);
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Team;
|
||||
|
||||
use App\Models\Team;
|
||||
use Livewire\Component;
|
||||
|
||||
class Form extends Component
|
||||
{
|
||||
public Team $team;
|
||||
protected $rules = [
|
||||
'team.name' => 'required|min:3|max:255',
|
||||
'team.description' => 'nullable|min:3|max:255',
|
||||
];
|
||||
protected $validationAttributes = [
|
||||
'team.name' => 'name',
|
||||
'team.description' => 'description',
|
||||
];
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->team = currentTeam();
|
||||
}
|
||||
|
||||
public function submit()
|
||||
{
|
||||
$this->validate();
|
||||
try {
|
||||
$this->team->save();
|
||||
refreshSession();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
}
|
||||
65
app/Livewire/Team/Index.php
Normal file
65
app/Livewire/Team/Index.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Team;
|
||||
|
||||
use App\Models\Team;
|
||||
use App\Models\TeamInvitation;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Livewire\Component;
|
||||
|
||||
class Index extends Component
|
||||
{
|
||||
public $invitations = [];
|
||||
public Team $team;
|
||||
protected $rules = [
|
||||
'team.name' => 'required|min:3|max:255',
|
||||
'team.description' => 'nullable|min:3|max:255',
|
||||
];
|
||||
protected $validationAttributes = [
|
||||
'team.name' => 'name',
|
||||
'team.description' => 'description',
|
||||
];
|
||||
public function mount() {
|
||||
$this->team = currentTeam();
|
||||
|
||||
if (auth()->user()->isAdminFromSession()) {
|
||||
$this->invitations = TeamInvitation::whereTeamId(currentTeam()->id)->get();
|
||||
}
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.team.index');
|
||||
}
|
||||
|
||||
public function submit()
|
||||
{
|
||||
$this->validate();
|
||||
try {
|
||||
$this->team->save();
|
||||
refreshSession();
|
||||
$this->dispatch('success', 'Team updated successfully.');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function delete()
|
||||
{
|
||||
$currentTeam = currentTeam();
|
||||
$currentTeam->delete();
|
||||
|
||||
$currentTeam->members->each(function ($user) use ($currentTeam) {
|
||||
if ($user->id === auth()->user()->id) {
|
||||
return;
|
||||
}
|
||||
$user->teams()->detach($currentTeam);
|
||||
$session = DB::table('sessions')->where('user_id', $user->id)->first();
|
||||
if ($session) {
|
||||
DB::table('sessions')->where('id', $session->id)->delete();
|
||||
}
|
||||
});
|
||||
|
||||
refreshSession();
|
||||
return redirect()->route('team.index');
|
||||
}
|
||||
}
|
||||
20
app/Livewire/Team/Member/Index.php
Normal file
20
app/Livewire/Team/Member/Index.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Team\Member;
|
||||
|
||||
use App\Models\TeamInvitation;
|
||||
use Livewire\Component;
|
||||
|
||||
class Index extends Component
|
||||
{
|
||||
public $invitations = [];
|
||||
public function mount() {
|
||||
if (auth()->user()->isAdminFromSession()) {
|
||||
$this->invitations = TeamInvitation::whereTeamId(currentTeam()->id)->get();
|
||||
}
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.team.member.index');
|
||||
}
|
||||
}
|
||||
13
app/Livewire/Team/Notification/Index.php
Normal file
13
app/Livewire/Team/Notification/Index.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Team\Notification;
|
||||
|
||||
use Livewire\Component;
|
||||
|
||||
class Index extends Component
|
||||
{
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.team.notification.index');
|
||||
}
|
||||
}
|
||||
@@ -65,7 +65,7 @@ class Create extends Component
|
||||
$this->storage->team_id = currentTeam()->id;
|
||||
$this->storage->testConnection();
|
||||
$this->storage->save();
|
||||
return $this->redirectRoute('team.storages.show', $this->storage->uuid, navigate: true);
|
||||
return redirect()->route('team.storage.show', $this->storage->uuid);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ class Form extends Component
|
||||
{
|
||||
try {
|
||||
$this->storage->delete();
|
||||
return $this->redirectRoute('team.storages.all', navigate: true);
|
||||
return redirect()->route('team.storage.index');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
||||
18
app/Livewire/Team/Storage/Index.php
Normal file
18
app/Livewire/Team/Storage/Index.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Team\Storage;
|
||||
|
||||
use App\Models\S3Storage;
|
||||
use Livewire\Component;
|
||||
|
||||
class Index extends Component
|
||||
{
|
||||
public $s3;
|
||||
public function mount() {
|
||||
$this->s3 = S3Storage::ownedByCurrentTeam()->get();
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.team.storage.index');
|
||||
}
|
||||
}
|
||||
22
app/Livewire/Team/Storage/Show.php
Normal file
22
app/Livewire/Team/Storage/Show.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Team\Storage;
|
||||
|
||||
use App\Models\S3Storage;
|
||||
use Livewire\Component;
|
||||
|
||||
class Show extends Component
|
||||
{
|
||||
public $storage = null;
|
||||
public function mount()
|
||||
{
|
||||
$this->storage = S3Storage::ownedByCurrentTeam()->whereUuid(request()->storage_uuid)->first();
|
||||
if (!$this->storage) {
|
||||
abort(404);
|
||||
}
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.team.storage.show');
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ class Index extends Component
|
||||
public function mount()
|
||||
{
|
||||
if (config('coolify.waitlist') == false) {
|
||||
return $this->redirectRoute('register', navigate: true);
|
||||
return redirect()->route('register');
|
||||
}
|
||||
$this->waitingInLine = Waitlist::whereVerified(true)->count();
|
||||
$this->users = User::count();
|
||||
|
||||
@@ -382,6 +382,9 @@ class Application extends BaseModel
|
||||
|
||||
public function deploymentType()
|
||||
{
|
||||
if (isDev() && data_get($this, 'private_key_id') === 0) {
|
||||
return 'deploy_key';
|
||||
}
|
||||
if (data_get($this, 'private_key_id')) {
|
||||
return 'deploy_key';
|
||||
} else if (data_get($this, 'source')) {
|
||||
@@ -422,7 +425,7 @@ class Application extends BaseModel
|
||||
public function isConfigurationChanged($save = false)
|
||||
{
|
||||
$newConfigHash = $this->fqdn . $this->git_repository . $this->git_branch . $this->git_commit_sha . $this->build_pack . $this->static_image . $this->install_command . $this->build_command . $this->start_command . $this->port_exposes . $this->port_mappings . $this->base_directory . $this->publish_directory . $this->health_check_path . $this->health_check_port . $this->health_check_host . $this->health_check_method . $this->health_check_return_code . $this->health_check_scheme . $this->health_check_response_text . $this->health_check_interval . $this->health_check_timeout . $this->health_check_retries . $this->health_check_start_period . $this->health_check_enabled . $this->limits_memory . $this->limits_swap . $this->limits_swappiness . $this->limits_reservation . $this->limits_cpus . $this->limits_cpuset . $this->limits_cpu_shares . $this->dockerfile . $this->dockerfile_location . $this->custom_labels;
|
||||
if ($this->pull_request_id === 0) {
|
||||
if ($this->pull_request_id === 0 || $this->pull_request_id === null) {
|
||||
$newConfigHash .= json_encode($this->environment_variables->all());
|
||||
} else {
|
||||
$newConfigHash .= json_encode($this->environment_variables_preview->all());
|
||||
@@ -633,7 +636,7 @@ class Application extends BaseModel
|
||||
'memswap_limit' => $this->limits_memory_swap,
|
||||
'mem_swappiness' => $this->limits_memory_swappiness,
|
||||
'mem_reservation' => $this->limits_memory_reservation,
|
||||
'cpus' => (int) $this->limits_cpus,
|
||||
'cpus' => (float) $this->limits_cpus,
|
||||
'cpuset' => $this->limits_cpuset,
|
||||
'cpu_shares' => $this->limits_cpu_shares,
|
||||
]
|
||||
@@ -752,7 +755,6 @@ class Application extends BaseModel
|
||||
// if (count($this->ports_mappings_array) > 0) {
|
||||
// $deployment->addLogEntry('Application has ports mapped to the host system, rolling update is not supported.');
|
||||
$containers = getCurrentApplicationContainerStatus($server, $this->id, $pullRequestId);
|
||||
ray($containers);
|
||||
// if ($pullRequestId === 0) {
|
||||
// $containers = $containers->filter(function ($container) use ($containerName) {
|
||||
// return data_get($container, 'Names') !== $containerName;
|
||||
@@ -859,7 +861,9 @@ class Application extends BaseModel
|
||||
}
|
||||
$private_key = base64_encode($private_key);
|
||||
$git_clone_command_base = "GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" {$git_clone_command} {$customRepository} {$baseDir}";
|
||||
if (!$only_checkout) {
|
||||
if ($only_checkout) {
|
||||
$git_clone_command = $git_clone_command_base;
|
||||
} else {
|
||||
$git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command_base);
|
||||
}
|
||||
if ($exec_in_docker) {
|
||||
@@ -979,6 +983,7 @@ class Application extends BaseModel
|
||||
// $fileList->push(".$prComposeFile");
|
||||
// }
|
||||
$commands = collect([
|
||||
"rm -rf /tmp/{$uuid}",
|
||||
"mkdir -p /tmp/{$uuid} && cd /tmp/{$uuid}",
|
||||
$cloneCommand,
|
||||
"git sparse-checkout init --cone",
|
||||
|
||||
@@ -48,7 +48,7 @@ class S3Storage extends BaseModel
|
||||
if ($this->unusable_email_sent === false && is_transactional_emails_active()) {
|
||||
$mail = new MailMessage();
|
||||
$mail->subject('Coolify: S3 Storage Connection Error');
|
||||
$mail->view('emails.s3-connection-error', ['name' => $this->name, 'reason' => $e->getMessage(), 'url' => route('team.storages.show', ['storage_uuid' => $this->uuid])]);
|
||||
$mail->view('emails.s3-connection-error', ['name' => $this->name, 'reason' => $e->getMessage(), 'url' => route('team.storage.show', ['storage_uuid' => $this->uuid])]);
|
||||
$users = collect([]);
|
||||
$members = $this->team->members()->get();
|
||||
foreach ($members as $user) {
|
||||
|
||||
@@ -154,17 +154,21 @@ class Server extends BaseModel
|
||||
if ($this->skipServer()) {
|
||||
return false;
|
||||
}
|
||||
$serverUptimeCheckNumber = $this->unreachable_count;
|
||||
if ($this->unreachable_count < $tries) {
|
||||
$serverUptimeCheckNumber = $this->unreachable_count + 1;
|
||||
}
|
||||
if ($this->unreachable_count > $tries) {
|
||||
$serverUptimeCheckNumber = $tries;
|
||||
}
|
||||
|
||||
$serverUptimeCheckNumberMax = $tries;
|
||||
|
||||
ray('server: ' . $this->name);
|
||||
ray('serverUptimeCheckNumber: ' . $serverUptimeCheckNumber);
|
||||
ray('serverUptimeCheckNumberMax: ' . $serverUptimeCheckNumberMax);
|
||||
// ray('server: ' . $this->name);
|
||||
// ray('serverUptimeCheckNumber: ' . $serverUptimeCheckNumber);
|
||||
// ray('serverUptimeCheckNumberMax: ' . $serverUptimeCheckNumberMax);
|
||||
|
||||
$result = $this->validateConnection();
|
||||
ray($result);
|
||||
if ($result) {
|
||||
if ($this->unreachable_notification_sent === true) {
|
||||
$this->update(['unreachable_notification_sent' => false]);
|
||||
|
||||
@@ -27,7 +27,7 @@ class ContainerRestarted extends Notification implements ShouldQueue
|
||||
public function toMail(): MailMessage
|
||||
{
|
||||
$mail = new MailMessage();
|
||||
$mail->subject("Coolify: A service ({$this->name}) has been restarted automatically on {$this->server->name}");
|
||||
$mail->subject("Coolify: A resource ({$this->name}) has been restarted automatically on {$this->server->name}");
|
||||
$mail->view('emails.container-restarted', [
|
||||
'containerName' => $this->name,
|
||||
'serverName' => $this->server->name,
|
||||
@@ -38,12 +38,12 @@ class ContainerRestarted extends Notification implements ShouldQueue
|
||||
|
||||
public function toDiscord(): string
|
||||
{
|
||||
$message = "Coolify: A service ({$this->name}) has been restarted automatically on {$this->server->name}";
|
||||
$message = "Coolify: A resource ({$this->name}) has been restarted automatically on {$this->server->name}";
|
||||
return $message;
|
||||
}
|
||||
public function toTelegram(): array
|
||||
{
|
||||
$message = "Coolify: A service ({$this->name}) has been restarted automatically on {$this->server->name}";
|
||||
$message = "Coolify: A resource ({$this->name}) has been restarted automatically on {$this->server->name}";
|
||||
$payload = [
|
||||
"message" => $message,
|
||||
];
|
||||
|
||||
@@ -26,7 +26,7 @@ class ContainerStopped extends Notification implements ShouldQueue
|
||||
public function toMail(): MailMessage
|
||||
{
|
||||
$mail = new MailMessage();
|
||||
$mail->subject("Coolify: A service ({$this->name}) has been stopped on {$this->server->name}");
|
||||
$mail->subject("Coolify: A resource has been stopped unexpectedly on {$this->server->name}");
|
||||
$mail->view('emails.container-stopped', [
|
||||
'containerName' => $this->name,
|
||||
'serverName' => $this->server->name,
|
||||
@@ -37,12 +37,12 @@ class ContainerStopped extends Notification implements ShouldQueue
|
||||
|
||||
public function toDiscord(): string
|
||||
{
|
||||
$message = "Coolify: A service ({$this->name}) has been stopped on {$this->server->name}";
|
||||
$message = "Coolify: A resource has been stopped unexpectedly on {$this->server->name}";
|
||||
return $message;
|
||||
}
|
||||
public function toTelegram(): array
|
||||
{
|
||||
$message = "Coolify: A service ($this->name} has been stopped on {$this->server->name}";
|
||||
$message = "Coolify: A resource has been stopped unexpectedly on {$this->server->name}";
|
||||
$payload = [
|
||||
"message" => $message,
|
||||
];
|
||||
|
||||
@@ -31,9 +31,9 @@ class FortifyServiceProvider extends ServiceProvider
|
||||
{
|
||||
// First user (root) will be redirected to /settings instead of / on registration.
|
||||
if ($request->user()->currentTeam->id === 0) {
|
||||
return redirect('/settings');
|
||||
return redirect()->route('settings.index');
|
||||
}
|
||||
return redirect('/');
|
||||
return redirect(RouteServiceProvider::HOME);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -41,11 +41,11 @@ function queue_application_deployment(int $application_id, string $deployment_uu
|
||||
dispatch(new ApplicationDeploymentNewJob(
|
||||
deployment: $deployment,
|
||||
application: Application::find($application_id)
|
||||
))->onConnection('long-running')->onQueue('long-running');
|
||||
));
|
||||
} else {
|
||||
dispatch(new ApplicationDeploymentJob(
|
||||
application_deployment_queue_id: $deployment->id,
|
||||
))->onConnection('long-running')->onQueue('long-running');
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,11 +57,11 @@ function queue_next_deployment(Application $application, bool $isNew = false)
|
||||
dispatch(new ApplicationDeploymentNewJob(
|
||||
deployment: $next_found,
|
||||
application: $application
|
||||
))->onConnection('long-running')->onQueue('long-running');
|
||||
));
|
||||
} else {
|
||||
dispatch(new ApplicationDeploymentJob(
|
||||
application_deployment_queue_id: $next_found->id,
|
||||
))->onConnection('long-running')->onQueue('long-running');
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,64 +216,72 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_
|
||||
$labels = collect([]);
|
||||
$labels->push('traefik.enable=true');
|
||||
foreach ($domains as $loop => $domain) {
|
||||
$uuid = new Cuid2(7);
|
||||
$url = Url::fromString($domain);
|
||||
$host = $url->getHost();
|
||||
$path = $url->getPath();
|
||||
$schema = $url->getScheme();
|
||||
$port = $url->getPort();
|
||||
if (is_null($port) && !is_null($onlyPort)) {
|
||||
$port = $onlyPort;
|
||||
}
|
||||
$http_label = "{$uuid}-{$loop}-http";
|
||||
$https_label = "{$uuid}-{$loop}-https";
|
||||
try {
|
||||
$uuid = new Cuid2(7);
|
||||
$url = Url::fromString($domain);
|
||||
$host = $url->getHost();
|
||||
$path = $url->getPath();
|
||||
$schema = $url->getScheme();
|
||||
$port = $url->getPort();
|
||||
if (is_null($port) && !is_null($onlyPort)) {
|
||||
$port = $onlyPort;
|
||||
}
|
||||
$http_label = "http-{$loop}-{$uuid}";
|
||||
$https_label = "https-{$loop}-{$uuid}";
|
||||
|
||||
if ($schema === 'https') {
|
||||
// Set labels for https
|
||||
$labels->push("traefik.http.routers.{$https_label}.rule=Host(`{$host}`) && PathPrefix(`{$path}`)");
|
||||
$labels->push("traefik.http.routers.{$https_label}.entryPoints=https");
|
||||
$labels->push("traefik.http.routers.{$https_label}.middlewares=gzip");
|
||||
if ($port) {
|
||||
$labels->push("traefik.http.routers.{$https_label}.service={$https_label}");
|
||||
$labels->push("traefik.http.services.{$https_label}.loadbalancer.server.port=$port");
|
||||
}
|
||||
if ($path !== '/') {
|
||||
$labels->push("traefik.http.routers.{$https_label}.middlewares={$https_label}-stripprefix");
|
||||
$labels->push("traefik.http.middlewares.{$https_label}-stripprefix.stripprefix.prefixes={$path}");
|
||||
}
|
||||
if ($schema === 'https') {
|
||||
// Set labels for https
|
||||
$labels->push("traefik.http.routers.{$https_label}.rule=Host(`{$host}`) && PathPrefix(`{$path}`)");
|
||||
$labels->push("traefik.http.routers.{$https_label}.entryPoints=https");
|
||||
$labels->push("traefik.http.routers.{$https_label}.middlewares=gzip");
|
||||
if ($port) {
|
||||
$labels->push("traefik.http.routers.{$https_label}.service={$https_label}");
|
||||
$labels->push("traefik.http.services.{$https_label}.loadbalancer.server.port=$port");
|
||||
}
|
||||
if ($path !== '/') {
|
||||
$labels->push("traefik.http.routers.{$https_label}.middlewares={$https_label}-stripprefix");
|
||||
$labels->push("traefik.http.middlewares.{$https_label}-stripprefix.stripprefix.prefixes={$path}");
|
||||
}
|
||||
|
||||
$labels->push("traefik.http.routers.{$https_label}.tls=true");
|
||||
$labels->push("traefik.http.routers.{$https_label}.tls.certresolver=letsencrypt");
|
||||
$labels->push("traefik.http.routers.{$https_label}.tls=true");
|
||||
$labels->push("traefik.http.routers.{$https_label}.tls.certresolver=letsencrypt");
|
||||
|
||||
// Set labels for http (redirect to https)
|
||||
$labels->push("traefik.http.routers.{$http_label}.rule=Host(`{$host}`) && PathPrefix(`{$path}`)");
|
||||
$labels->push("traefik.http.routers.{$http_label}.entryPoints=http");
|
||||
if ($is_force_https_enabled) {
|
||||
$labels->push("traefik.http.routers.{$http_label}.middlewares=redirect-to-https");
|
||||
}
|
||||
} else {
|
||||
// Set labels for http
|
||||
$labels->push("traefik.http.routers.{$http_label}.rule=Host(`{$host}`) && PathPrefix(`{$path}`)");
|
||||
$labels->push("traefik.http.routers.{$http_label}.entryPoints=http");
|
||||
$labels->push("traefik.http.routers.{$http_label}.middlewares=gzip");
|
||||
if ($port) {
|
||||
$labels->push("traefik.http.routers.{$http_label}.service={$http_label}");
|
||||
$labels->push("traefik.http.services.{$http_label}.loadbalancer.server.port=$port");
|
||||
}
|
||||
if ($path !== '/') {
|
||||
$labels->push("traefik.http.routers.{$http_label}.middlewares={$http_label}-stripprefix");
|
||||
$labels->push("traefik.http.middlewares.{$http_label}-stripprefix.stripprefix.prefixes={$path}");
|
||||
// Set labels for http (redirect to https)
|
||||
$labels->push("traefik.http.routers.{$http_label}.rule=Host(`{$host}`) && PathPrefix(`{$path}`)");
|
||||
$labels->push("traefik.http.routers.{$http_label}.entryPoints=http");
|
||||
if ($port) {
|
||||
$labels->push("traefik.http.services.{$http_label}.loadbalancer.server.port=$port");
|
||||
$labels->push("traefik.http.routers.{$http_label}.service={$http_label}");
|
||||
}
|
||||
if ($is_force_https_enabled) {
|
||||
$labels->push("traefik.http.routers.{$http_label}.middlewares=redirect-to-https");
|
||||
}
|
||||
} else {
|
||||
// Set labels for http
|
||||
$labels->push("traefik.http.routers.{$http_label}.rule=Host(`{$host}`) && PathPrefix(`{$path}`)");
|
||||
$labels->push("traefik.http.routers.{$http_label}.entryPoints=http");
|
||||
$labels->push("traefik.http.routers.{$http_label}.middlewares=gzip");
|
||||
if ($port) {
|
||||
$labels->push("traefik.http.services.{$http_label}.loadbalancer.server.port=$port");
|
||||
$labels->push("traefik.http.routers.{$http_label}.service={$http_label}");
|
||||
}
|
||||
if ($path !== '/') {
|
||||
$labels->push("traefik.http.routers.{$http_label}.middlewares={$http_label}-stripprefix");
|
||||
$labels->push("traefik.http.middlewares.{$http_label}-stripprefix.stripprefix.prefixes={$path}");
|
||||
}
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return $labels;
|
||||
return $labels->sort();
|
||||
}
|
||||
function generateLabelsApplication(Application $application, ?ApplicationPreview $preview = null): array
|
||||
{
|
||||
$ports = $application->settings->is_static ? [80] : $application->ports_exposes_array;
|
||||
$onlyPort = null;
|
||||
if (count($ports) === 1) {
|
||||
if (count($ports) > 0) {
|
||||
$onlyPort = $ports[0];
|
||||
}
|
||||
$pull_request_id = data_get($preview, 'pull_request_id', 0);
|
||||
|
||||
@@ -101,7 +101,6 @@ function generate_default_proxy_configuration(Server $server)
|
||||
$labels = [
|
||||
"traefik.enable=true",
|
||||
"traefik.http.routers.traefik.entrypoints=http",
|
||||
"traefik.http.routers.traefik.middlewares=traefik-basic-auth@file",
|
||||
"traefik.http.routers.traefik.service=api@internal",
|
||||
"traefik.http.services.traefik.loadbalancer.server.port=8080",
|
||||
// Global Middlewares
|
||||
@@ -156,7 +155,7 @@ function generate_default_proxy_configuration(Server $server)
|
||||
],
|
||||
];
|
||||
if (isDev()) {
|
||||
$config['services']['traefik']['command'][] = "--log.level=debug";
|
||||
// $config['services']['traefik']['command'][] = "--log.level=debug";
|
||||
$config['services']['traefik']['command'][] = "--accesslog.filepath=/traefik/access.log";
|
||||
$config['services']['traefik']['command'][] = "--accesslog.bufferingsize=100";
|
||||
}
|
||||
|
||||
@@ -102,6 +102,7 @@ function refreshSession(?Team $team = null): void
|
||||
}
|
||||
function handleError(?Throwable $error = null, ?Livewire\Component $livewire = null, ?string $customErrorMessage = null)
|
||||
{
|
||||
ray($error);
|
||||
if ($error instanceof TooManyRequestsException) {
|
||||
if (isset($livewire)) {
|
||||
return $livewire->dispatch('error', "Too many requests. Please try again in {$error->secondsUntilAvailable} seconds.");
|
||||
@@ -227,11 +228,15 @@ function base_ip(): string
|
||||
}
|
||||
function getFqdnWithoutPort(String $fqdn)
|
||||
{
|
||||
$url = Url::fromString($fqdn);
|
||||
$host = $url->getHost();
|
||||
$scheme = $url->getScheme();
|
||||
$path = $url->getPath();
|
||||
return "$scheme://$host$path";
|
||||
try {
|
||||
$url = Url::fromString($fqdn);
|
||||
$host = $url->getHost();
|
||||
$scheme = $url->getScheme();
|
||||
$path = $url->getPath();
|
||||
return "$scheme://$host$path";
|
||||
} catch (\Throwable $e) {
|
||||
return $fqdn;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* If fqdn is set, return it, otherwise return public ip.
|
||||
@@ -403,7 +408,7 @@ function generateFqdn(Server $server, string $random)
|
||||
}
|
||||
function sslip(Server $server)
|
||||
{
|
||||
if (isDev()) {
|
||||
if (isDev() && $server->id === 0) {
|
||||
return "http://127.0.0.1.sslip.io";
|
||||
}
|
||||
if ($server->ip === 'host.docker.internal') {
|
||||
@@ -1030,7 +1035,9 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
}
|
||||
data_set($service, 'labels', $serviceLabels->toArray());
|
||||
data_forget($service, 'is_database');
|
||||
data_set($service, 'restart', RESTART_MODE);
|
||||
if (!data_get($service, 'restart')) {
|
||||
data_set($service, 'restart', RESTART_MODE);
|
||||
}
|
||||
data_set($service, 'container_name', $containerName);
|
||||
data_forget($service, 'volumes.*.content');
|
||||
data_forget($service, 'volumes.*.isDirectory');
|
||||
@@ -1394,6 +1401,11 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
$key = $value;
|
||||
$defaultValue = null;
|
||||
}
|
||||
$foundEnv = EnvironmentVariable::where([
|
||||
'key' => $key,
|
||||
'application_id' => $resource->id,
|
||||
'is_preview' => false,
|
||||
])->first();
|
||||
if ($foundEnv) {
|
||||
$defaultValue = data_get($foundEnv, 'value');
|
||||
}
|
||||
@@ -1463,7 +1475,9 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
}
|
||||
data_set($service, 'labels', $serviceLabels->toArray());
|
||||
data_forget($service, 'is_database');
|
||||
data_set($service, 'restart', RESTART_MODE);
|
||||
if (!data_get($service, 'restart')) {
|
||||
data_set($service, 'restart', RESTART_MODE);
|
||||
}
|
||||
data_set($service, 'container_name', $containerName);
|
||||
data_forget($service, 'volumes.*.content');
|
||||
data_forget($service, 'volumes.*.isDirectory');
|
||||
@@ -1520,6 +1534,9 @@ function parseEnvVariable(Str|string $value)
|
||||
$command = $value->after('SERVICE_')->before('_');
|
||||
$forService = $value->after('SERVICE_')->after('_')->before('_');
|
||||
$port = $value->afterLast('_');
|
||||
if (filter_var($port, FILTER_VALIDATE_INT) === false) {
|
||||
$port = null;
|
||||
}
|
||||
} else {
|
||||
// SERVICE_BASE64_64_UMAMI
|
||||
$command = $value->after('SERVICE_')->beforeLast('_');
|
||||
|
||||
991
composer.lock
generated
991
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -184,19 +184,8 @@ return [
|
||||
'connection' => 'redis',
|
||||
'queue' => ['default'],
|
||||
'balance' => 'auto',
|
||||
'autoScalingStrategy' => 'time',
|
||||
'maxProcesses' => 1,
|
||||
'maxTime' => 0,
|
||||
'maxJobs' => 0,
|
||||
'memory' => 128,
|
||||
'tries' => 1,
|
||||
'timeout' => 300,
|
||||
'nice' => 0,
|
||||
],
|
||||
'long-running' => [
|
||||
'connection' => 'redis',
|
||||
'queue' => ['long-running'],
|
||||
'balance' => 'auto',
|
||||
// 'autoScalingStrategy' => 'time',
|
||||
// 'maxProcesses' => 1,
|
||||
'maxTime' => 0,
|
||||
'maxJobs' => 0,
|
||||
'memory' => 128,
|
||||
@@ -209,27 +198,15 @@ return [
|
||||
'environments' => [
|
||||
'production' => [
|
||||
's6' => [
|
||||
'autoScalingStrategy' => 'size',
|
||||
'maxProcesses' => env('HORIZON_MAX_PROCESSES', 2),
|
||||
'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1),
|
||||
'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1),
|
||||
],
|
||||
'long-running' => [
|
||||
'autoScalingStrategy' => 'size',
|
||||
'maxProcesses' => env('HORIZON_MAX_PROCESSES', 6),
|
||||
'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1),
|
||||
'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1),
|
||||
],
|
||||
],
|
||||
|
||||
],
|
||||
'local' => [
|
||||
's6' => [
|
||||
'autoScalingStrategy' => 'size',
|
||||
'maxProcesses' => env('HORIZON_MAX_PROCESSES', 2),
|
||||
'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1),
|
||||
'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1),
|
||||
],
|
||||
'long-running' => [
|
||||
'autoScalingStrategy' => 'size',
|
||||
'maxProcesses' => env('HORIZON_MAX_PROCESSES', 6),
|
||||
'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1),
|
||||
|
||||
@@ -33,14 +33,6 @@ return [
|
||||
'sync' => [
|
||||
'driver' => 'sync',
|
||||
],
|
||||
'long-running' => [
|
||||
'driver' => 'redis',
|
||||
'connection' => 'default',
|
||||
'queue' => 'long-running',
|
||||
'retry_after' => 3600,
|
||||
'block_for' => null,
|
||||
'after_commit' => true,
|
||||
],
|
||||
'database' => [
|
||||
'driver' => 'database',
|
||||
'table' => 'jobs',
|
||||
@@ -73,7 +65,7 @@ return [
|
||||
'driver' => 'redis',
|
||||
'connection' => 'default',
|
||||
'queue' => env('REDIS_QUEUE', 'default'),
|
||||
'retry_after' => 300,
|
||||
'retry_after' => 3600,
|
||||
'block_for' => null,
|
||||
'after_commit' => true,
|
||||
],
|
||||
|
||||
@@ -7,7 +7,7 @@ return [
|
||||
|
||||
// The release version of your application
|
||||
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
|
||||
'release' => '4.0.0-beta.171',
|
||||
'release' => '4.0.0-beta.185',
|
||||
// When left empty or `null` the Laravel environment will be used
|
||||
'environment' => config('app.env'),
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user