wip: broadcast

This commit is contained in:
Andras Bacsai 2023-12-04 20:47:32 +01:00
parent 17deff4d86
commit 42ee4ca032
22 changed files with 142 additions and 103 deletions

View File

@ -4,3 +4,11 @@ APP_KEY=
DB_PASSWORD= DB_PASSWORD=
REDIS_PASSWORD= REDIS_PASSWORD=
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
VITE_PUSHER_HOST="${PUSHER_HOST}"
VITE_PUSHER_PORT="${PUSHER_PORT}"

View File

@ -1,6 +1,6 @@
<?php <?php
namespace App\Providers; namespace App\Events;
use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Broadcasting\InteractsWithSockets;
@ -14,14 +14,25 @@ class ApplicationDeploymentFinished implements ShouldBroadcast
{ {
use Dispatchable, InteractsWithSockets, SerializesModels; use Dispatchable, InteractsWithSockets, SerializesModels;
public function __construct() public ?int $teamId = null;
/**
* Create a new event instance.
*/
public function __construct(public ?string $applicationUuid = null, public ?string $status = null)
{ {
$this->teamId = auth()->user()->currentTeam()->id;
} }
/**
* Get the channels the event should broadcast on.
*
* @return array<int, \Illuminate\Broadcasting\Channel>
*/
public function broadcastOn(): array public function broadcastOn(): array
{ {
return [ return [
new Channel('custom-channel'), new PrivateChannel("custom.{$this->teamId}"),
]; ];
} }
} }

View File

@ -10,7 +10,6 @@ class Dashboard extends Component
{ {
public $projects = []; public $projects = [];
public $servers = []; public $servers = [];
public function mount() public function mount()
{ {
$this->servers = Server::ownedByCurrentTeam()->get(); $this->servers = Server::ownedByCurrentTeam()->get();

View File

@ -26,7 +26,7 @@ public function mount()
return redirect()->route('dashboard'); return redirect()->route('dashboard');
} }
$this->application = $application; $this->application = $application;
$mainServer = $application->destination->server; $mainServer = $this->application->destination->server;
$servers = Server::ownedByCurrentTeam()->get(); $servers = Server::ownedByCurrentTeam()->get();
$this->servers = $servers->filter(function ($server) use ($mainServer) { $this->servers = $servers->filter(function ($server) use ($mainServer) {
return $server->id != $mainServer->id; return $server->id != $mainServer->id;

View File

@ -17,11 +17,7 @@ class DeploymentNavbar extends Component
public Application $application; public Application $application;
public Server $server; public Server $server;
public bool $is_debug_enabled = false; public bool $is_debug_enabled = false;
protected $listeners = ['deploymentFinished','echo:custom-channel,ApplicationDeploymentFinished' => 'notifyNewOrder']; protected $listeners = ['deploymentFinished'];
public function notifyNewOrder() {
ray('New order received');
}
public function mount() public function mount()
{ {
$this->application = Application::find($this->application_deployment_queue->application_id); $this->application = Application::find($this->application_deployment_queue->application_id);

View File

@ -11,11 +11,24 @@
class Heading extends Component class Heading extends Component
{ {
protected string $deploymentUuid;
public Application $application; public Application $application;
public array $parameters; public array $parameters;
public function getListeners()
{
$teamId = auth()->user()->currentTeam()->id;
return [
"echo-private:custom.{$teamId},ApplicationDeploymentFinished" => 'updateStatus',
];
}
protected string $deploymentUuid; public function updateStatus($message)
{
$applicationUuid = data_get($message, 'applicationUuid');
if ($this->application->uuid === $applicationUuid) {
$this->application->status = data_get($message, 'status');
}
}
public function mount() public function mount()
{ {
$this->parameters = get_route_parameters(); $this->parameters = get_route_parameters();

View File

@ -44,6 +44,7 @@ public function mount()
{ {
$this->wildcard_domain = $this->server->settings->wildcard_domain; $this->wildcard_domain = $this->server->settings->wildcard_domain;
$this->cleanup_after_percentage = $this->server->settings->cleanup_after_percentage; $this->cleanup_after_percentage = $this->server->settings->cleanup_after_percentage;
$this->validateServer();
} }
public function serverRefresh($install = true) public function serverRefresh($install = true)
{ {

View File

@ -4,6 +4,7 @@
use App\Enums\ApplicationDeploymentStatus; use App\Enums\ApplicationDeploymentStatus;
use App\Enums\ProxyTypes; use App\Enums\ProxyTypes;
use App\Events\ApplicationDeploymentFinished;
use App\Models\Application; use App\Models\Application;
use App\Models\ApplicationDeploymentQueue; use App\Models\ApplicationDeploymentQueue;
use App\Models\ApplicationPreview; use App\Models\ApplicationPreview;
@ -14,7 +15,6 @@
use App\Models\SwarmDocker; use App\Models\SwarmDocker;
use App\Notifications\Application\DeploymentFailed; use App\Notifications\Application\DeploymentFailed;
use App\Notifications\Application\DeploymentSuccess; use App\Notifications\Application\DeploymentSuccess;
use App\Providers\ApplicationDeploymentFinished;
use App\Traits\ExecuteRemoteCommand; use App\Traits\ExecuteRemoteCommand;
use Exception; use Exception;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
@ -102,7 +102,7 @@ public function handle()
}); });
} }
$this->next(ApplicationDeploymentStatus::FINISHED->value); $this->next(ApplicationDeploymentStatus::FINISHED->value);
ApplicationDeploymentFinished::dispatch($this->application, $this->deployment); ApplicationDeploymentFinished::dispatch($this->application->uuid, ApplicationDeploymentStatus::FINISHED->value);
} catch (Throwable $exception) { } catch (Throwable $exception) {
$this->fail($exception); $this->fail($exception);
} finally { } finally {

View File

@ -382,17 +382,17 @@ public function isSwarm()
public function validateConnection() public function validateConnection()
{ {
$server = Server::find($this->id); $server = Server::find($this->id);
if ($this->skipServer()) { if ($server->skipServer()) {
return false; return false;
} }
$uptime = instant_remote_process(['uptime'], $this, false); $uptime = instant_remote_process(['uptime'], $server, false);
if (!$uptime) { if (!$uptime) {
$this->settings()->update([ $server->settings()->update([
'is_reachable' => false, 'is_reachable' => false,
]); ]);
return false; return false;
} else { } else {
$this->settings()->update([ $server->settings()->update([
'is_reachable' => true, 'is_reachable' => true,
]); ]);
$server->update([ $server->update([
@ -400,8 +400,8 @@ public function validateConnection()
]); ]);
} }
if (data_get($this, 'unreachable_notification_sent') === true) { if (data_get($server, 'unreachable_notification_sent') === true) {
$this->team->notify(new Revived($this)); $server->team->notify(new Revived($server));
$server->update(['unreachable_notification_sent' => false]); $server->update(['unreachable_notification_sent' => false]);
} }

View File

@ -8,31 +8,15 @@
class EventServiceProvider extends ServiceProvider class EventServiceProvider extends ServiceProvider
{ {
/**
* The event to listener mappings for the application.
*
* @var array<class-string, array<int, class-string>>
*/
protected $listen = [ protected $listen = [
// Registered::class => [ // Registered::class => [
// SendEmailVerificationNotification::class, // SendEmailVerificationNotification::class,
// ], // ],
ApplicationDeploymentFinished::class => [
SendDeploymentNotification::class,
],
]; ];
/**
* Register any events for your application.
*/
public function boot(): void public function boot(): void
{ {
// //
} }
/**
* Determine if events and listeners should be automatically discovered.
*/
public function shouldDiscoverEvents(): bool public function shouldDiscoverEvents(): bool
{ {
return false; return false;

View File

@ -1,28 +0,0 @@
<?php
namespace App\Providers;
use App\Providers\ApplicationDeploymentFinished;
use Illuminate\Contracts\Events\ShouldHandleEventsAfterCommit;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
class SendDeploymentNotification implements ShouldQueue, ShouldHandleEventsAfterCommit
{
use InteractsWithQueue;
/**
* Create the event listener.
*/
public function __construct()
{
//
}
/**
* Handle the event.
*/
public function handle(ApplicationDeploymentFinished $event): void
{
ray('SendDeploymentNotification');
}
}

View File

@ -28,6 +28,7 @@
"nubs/random-name-generator": "^2.2", "nubs/random-name-generator": "^2.2",
"phpseclib/phpseclib": "~3.0", "phpseclib/phpseclib": "~3.0",
"poliander/cron": "^3.0", "poliander/cron": "^3.0",
"pusher/pusher-php-server": "^7.2",
"resend/resend-laravel": "^0.5.0", "resend/resend-laravel": "^0.5.0",
"sentry/sentry-laravel": "^3.4", "sentry/sentry-laravel": "^3.4",
"spatie/laravel-activitylog": "^4.7.3", "spatie/laravel-activitylog": "^4.7.3",

View File

@ -194,7 +194,7 @@
App\Providers\AppServiceProvider::class, App\Providers\AppServiceProvider::class,
App\Providers\FortifyServiceProvider::class, App\Providers\FortifyServiceProvider::class,
App\Providers\AuthServiceProvider::class, App\Providers\AuthServiceProvider::class,
// App\Providers\BroadcastServiceProvider::class, App\Providers\BroadcastServiceProvider::class,
App\Providers\EventServiceProvider::class, App\Providers\EventServiceProvider::class,
App\Providers\HorizonServiceProvider::class, App\Providers\HorizonServiceProvider::class,
App\Providers\RouteServiceProvider::class, App\Providers\RouteServiceProvider::class,

View File

@ -15,7 +15,7 @@
| |
*/ */
'default' => env('BROADCAST_DRIVER', 'log'), 'default' => env('BROADCAST_DRIVER', 'pusher'),
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
@ -32,9 +32,9 @@
'pusher' => [ 'pusher' => [
'driver' => 'pusher', 'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'), 'key' => env('PUSHER_APP_KEY', 'coolify'),
'secret' => env('PUSHER_APP_SECRET'), 'secret' => env('PUSHER_APP_SECRET', 'coolify'),
'app_id' => env('PUSHER_APP_ID'), 'app_id' => env('PUSHER_APP_ID', 'coolify'),
'options' => [ 'options' => [
'host' => 'coolify-soketi', 'host' => 'coolify-soketi',
'port' => env('PUSHER_PORT', 6001), 'port' => env('PUSHER_PORT', 6001),

View File

@ -13,11 +13,11 @@ class StandaloneDockerSeeder extends Seeder
*/ */
public function run(): void public function run(): void
{ {
// StandaloneDocker::create([ StandaloneDocker::create([
// 'id' => 0, 'id' => 0,
// 'name' => 'Standalone Docker 1', 'name' => 'Standalone Docker 1',
// 'network' => 'coolify', 'network' => 'coolify',
// 'server_id' => 0, 'server_id' => 0,
// ]); ]);
} }
} }

View File

@ -21,6 +21,10 @@ services:
SSL_MODE: "off" SSL_MODE: "off"
AUTORUN_LARAVEL_STORAGE_LINK: "false" AUTORUN_LARAVEL_STORAGE_LINK: "false"
AUTORUN_LARAVEL_MIGRATION: "false" AUTORUN_LARAVEL_MIGRATION: "false"
PUSHER_HOST: "${PUSHER_HOST:-127.0.0.1}"
PUSHER_APP_ID: "${PUSHER_APP_ID:-coolify}"
PUSHER_APP_KEY: "${PUSHER_APP_KEY:-coolify}"
PUSHER_APP_SECRET: "${PUSHER_APP_SECRET:-coolify}"
volumes: volumes:
- .:/var/www/html/:cached - .:/var/www/html/:cached
postgres: postgres:
@ -45,15 +49,22 @@ services:
- /data/coolify/_volumes/redis/:/data - /data/coolify/_volumes/redis/:/data
# - coolify-redis-data-dev:/data # - coolify-redis-data-dev:/data
soketi: soketi:
env_file:
- .env
ports: ports:
- "${FORWARD_SOKETI_PORT:-6001}:6001" - "${FORWARD_SOKETI_PORT:-6001}:6001"
- "${FORWARD_SOKETI_METRICS_SERVER_PORT:-9601}:9601"
environment: environment:
SOKETI_DEBUG: "true" SOKETI_DEBUG: "true"
SOKETI_METRICS_SERVER_PORT: "${SOKETI_METRICS_SERVER_PORT:-9601}" SOKETI_DEFAULT_APP_ID: "${PUSHER_APP_ID:-coolify}"
SOKETI_DEFAULT_APP_KEY: "${PUSHER_APP_KEY:-coolify}"
SOKETI_DEFAULT_APP_SECRET: "${PUSHER_APP_SECRET:-coolify}"
vite: vite:
image: node:20 image: node:20
working_dir: /var/www/html working_dir: /var/www/html
environment:
VITE_PUSHER_HOST: "${PUSHER_HOST:-127.0.0.1}"
VITE_PUSHER_APP_KEY: "${PUSHER_APP_KEY:-coolify}"
VITE_PUSHER_PORT: "${FORWARD_SOKETI_PORT:-6001}"
ports: ports:
- "${VITE_PORT:-5173}:${VITE_PORT:-5173}" - "${VITE_PORT:-5173}:${VITE_PORT:-5173}"
volumes: volumes:
@ -67,14 +78,14 @@ services:
- /var/run/docker.sock:/var/run/docker.sock - /var/run/docker.sock:/var/run/docker.sock
- /data/coolify/:/data/coolify - /data/coolify/:/data/coolify
# - coolify-data-dev:/data/coolify # - coolify-data-dev:/data/coolify
remote-host: # remote-host:
<<: *testing-host-base # <<: *testing-host-base
container_name: coolify-remote-host # container_name: coolify-remote-host
volumes: # volumes:
- /:/host # - /:/host
- /var/run/docker.sock:/var/run/docker.sock # - /var/run/docker.sock:/var/run/docker.sock
- /data/coolify/:/data/coolify # - /data/coolify/:/data/coolify
# - coolify-data-dev:/data/coolify # # - coolify-data-dev:/data/coolify
mailpit: mailpit:
image: "axllent/mailpit:latest" image: "axllent/mailpit:latest"
container_name: coolify-mail container_name: coolify-mail

View File

@ -1,7 +1,7 @@
version: '3.8' version: '3.8'
services: services:
coolify: coolify:
image: "ghcr.io/coollabsio/coolify:${LATEST_IMAGE:-4.0.0-beta.20}" image: "ghcr.io/coollabsio/coolify:${LATEST_IMAGE:-4.0.0-beta.153}"
volumes: volumes:
- type: bind - type: bind
source: /data/coolify/source/.env source: /data/coolify/source/.env
@ -35,6 +35,13 @@ services:
- PHP_PM_START_SERVERS=1 - PHP_PM_START_SERVERS=1
- PHP_PM_MIN_SPARE_SERVERS=1 - PHP_PM_MIN_SPARE_SERVERS=1
- PHP_PM_MAX_SPARE_SERVERS=10 - PHP_PM_MAX_SPARE_SERVERS=10
- PUSHER_HOST
- PUSHER_APP_ID
- PUSHER_APP_KEY
- PUSHER_APP_SECRET
- VITE_PUSHER_HOST
- VITE_PUSHER_APP_KEY
- VITE_PUSHER_PORT
- SELF_HOSTED - SELF_HOSTED
- WAITLIST - WAITLIST
- SUBSCRIPTION_PROVIDER - SUBSCRIPTION_PROVIDER
@ -111,6 +118,12 @@ services:
interval: 2s interval: 2s
retries: 5 retries: 5
timeout: 2s timeout: 2s
soketi:
environment:
SOKETI_DEBUG: "${SOKETI_DEBUG:-false}"
SOKETI_DEFAULT_APP_ID: "${PUSHER_APP_ID}"
SOKETI_DEFAULT_APP_KEY: "${PUSHER_APP_KEY}"
SOKETI_DEFAULT_APP_SECRET: "${PUSHER_APP_SECRET}"
volumes: volumes:
coolify-db: coolify-db:
name: coolify-db name: coolify-db

View File

@ -9,14 +9,15 @@ window.Pusher = Pusher;
window.Echo = new Echo({ window.Echo = new Echo({
broadcaster: 'pusher', broadcaster: 'pusher',
cluster: import.meta.env.VITE_PUSHER_HOST, cluster: import.meta.env.VITE_PUSHER_HOST ?? '127.0.0.1',
key: import.meta.env.VITE_PUSHER_APP_KEY, key: import.meta.env.VITE_PUSHER_APP_KEY ?? 'coolify',
wsHost: import.meta.env.VITE_PUSHER_HOST, wsHost: import.meta.env.VITE_PUSHER_HOST ?? '127.0.0.1',
wsPort: import.meta.env.VITE_PUSHER_PORT, wsPort: import.meta.env.VITE_PUSHER_PORT,
wssPort: import.meta.env.VITE_PUSHER_PORT, wssPort: import.meta.env.VITE_PUSHER_PORT,
forceTLS: false, forceTLS: false,
encrypted: false, encrypted: true,
disableStats: true, disableStats: false,
enableLogging: true,
enabledTransports: ['ws', 'wss'], enabledTransports: ['ws', 'wss'],
}); });
@ -30,6 +31,4 @@ app.component("magic-bar", MagicBar);
app.mount("#vue"); app.mount("#vue");
window.Echo.channel("custom-channel").listen("ApplicationDeploymentFinished", (e) => {
console.log(e);
});

View File

@ -1,4 +1,4 @@
<nav x-init="$wire.check_status" wire:poll.10000ms="check_status"> <nav x-init="$wire.check_status">
<x-resources.breadcrumbs :resource="$application" :parameters="$parameters" /> <x-resources.breadcrumbs :resource="$application" :parameters="$parameters" />
<x-applications.navbar :application="$application" :parameters="$parameters" /> <x-applications.navbar :application="$application" :parameters="$parameters" />
</nav> </nav>

View File

@ -11,6 +11,13 @@
| |
*/ */
// Broadcast::channel('App.Models.User.{id}', function ($user, $id) { use App\Models\Application;
// return (int) $user->id === (int) $id; use App\Models\User;
// }); use Illuminate\Support\Facades\Broadcast;
Broadcast::channel('custom.{teamId}', function (User $user, int $teamId) {
if ($user->teams->pluck('id')->contains($teamId)) {
return true;
}
return false;
});

View File

@ -1,5 +1,6 @@
<?php <?php
use App\Events\ApplicationDeploymentFinished;
use App\Http\Controllers\ApplicationController; use App\Http\Controllers\ApplicationController;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Http\Controllers\DatabaseController; use App\Http\Controllers\DatabaseController;
@ -39,6 +40,11 @@
use Laravel\Fortify\Contracts\SuccessfulPasswordResetLinkRequestResponse; use Laravel\Fortify\Contracts\SuccessfulPasswordResetLinkRequestResponse;
use Laravel\Fortify\Fortify; use Laravel\Fortify\Fortify;
Route::get('/fire', function () {
ApplicationDeploymentFinished::dispatch('kk0gg0s', 'stopped');
return 'Event has been sent!';
});
if (isDev()) { if (isDev()) {
Route::get('/dev/compose', Compose::class)->name('dev.compose'); Route::get('/dev/compose', Compose::class)->name('dev.compose');
} }

View File

@ -1,11 +1,7 @@
#!/bin/bash #!/bin/bash
## Do not modify this file. You will lost the ability to autoupdate! ## Do not modify this file. You will lost the ability to autoupdate!
########### VERSION="1.1.0"
## Always run "php artisan app:sync-to-bunny-cdn --env=secrets" if you update this file.
###########
VERSION="1.0.1"
CDN="https://cdn.coollabs.io/coolify" CDN="https://cdn.coollabs.io/coolify"
curl -fsSL $CDN/docker-compose.yml -o /data/coolify/source/docker-compose.yml curl -fsSL $CDN/docker-compose.yml -o /data/coolify/source/docker-compose.yml
@ -15,6 +11,28 @@ curl -fsSL $CDN/.env.production -o /data/coolify/source/.env.production
# Merge .env and .env.production. New values will be added to .env # Merge .env and .env.production. New values will be added to .env
sort -u -t '=' -k 1,1 /data/coolify/source/.env /data/coolify/source/.env.production | sed '/^$/d' > /data/coolify/source/.env.temp && mv /data/coolify/source/.env.temp /data/coolify/source/.env sort -u -t '=' -k 1,1 /data/coolify/source/.env /data/coolify/source/.env.production | sed '/^$/d' > /data/coolify/source/.env.temp && mv /data/coolify/source/.env.temp /data/coolify/source/.env
# Check if PUSHER_APP_ID or PUSHER_APP_KEY or PUSHER_APP_SECRET is empty in /data/coolify/source/.env
if grep -q "PUSHER_APP_ID=" /data/coolify/source/.env; then
echo "PUSHER_APP_ID is set in .env"
else
echo "PUSHER_APP_ID is not set in .env"
sed -i "s|PUSHER_APP_ID=.*|PUSHER_APP_ID=$(openssl rand -base64 32)|g" /data/coolify/source/.env
fi
if grep -q "PUSHER_APP_KEY=" /data/coolify/source/.env; then
echo "PUSHER_APP_KEY is set in .env"
else
echo "PUSHER_APP_KEY is not set in .env"
sed -i "s|PUSHER_APP_KEY=.*|PUSHER_APP_KEY=$(openssl rand -base64 32)|g" /data/coolify/source/.env
fi
if grep -q "PUSHER_APP_SECRET=" /data/coolify/source/.env; then
echo "PUSHER_APP_SECRET is set in .env"
else
echo "PUSHER_APP_SECRET is not set in .env"
sed -i "s|PUSHER_APP_SECRET=.*|PUSHER_APP_SECRET=$(openssl rand -base64 32)|g" /data/coolify/source/.env
fi
# Make sure coolify network exists # Make sure coolify network exists
docker network create --attachable coolify 2>/dev/null docker network create --attachable coolify 2>/dev/null
# docker network create --attachable --driver=overlay coolify-overlay 2>/dev/null # docker network create --attachable --driver=overlay coolify-overlay 2>/dev/null