Merge remote-tracking branch 'origin/v4' into ijpatricio-wip-4
# Conflicts: # bootstrap/helpers.php # docker/dev/supervisord.conf
This commit is contained in:
commit
2d25d3848c
@ -41,6 +41,9 @@ public function __construct(Activity $activity)
|
|||||||
|
|
||||||
public function __invoke(): ProcessResult
|
public function __invoke(): ProcessResult
|
||||||
{
|
{
|
||||||
|
$this->activity->properties = $this->activity->properties->merge([
|
||||||
|
'status' => ProcessStatus::IN_PROGRESS,
|
||||||
|
]);
|
||||||
$this->timeStart = hrtime(true);
|
$this->timeStart = hrtime(true);
|
||||||
|
|
||||||
$processResult = Process::run($this->getCommand(), $this->handleOutput(...));
|
$processResult = Process::run($this->getCommand(), $this->handleOutput(...));
|
||||||
@ -70,22 +73,7 @@ protected function getCommand(): string
|
|||||||
$port = $this->activity->getExtraProperty('port');
|
$port = $this->activity->getExtraProperty('port');
|
||||||
$command = $this->activity->getExtraProperty('command');
|
$command = $this->activity->getExtraProperty('command');
|
||||||
|
|
||||||
$delimiter = 'EOF-COOLIFY-SSH';
|
return generateSshCommand($private_key_location, $server_ip, $user, $port, $command);
|
||||||
Storage::disk('local')->makeDirectory('.ssh');
|
|
||||||
|
|
||||||
$ssh_command = "ssh "
|
|
||||||
. "-i {$private_key_location} "
|
|
||||||
. '-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null '
|
|
||||||
. '-o PasswordAuthentication=no '
|
|
||||||
. '-o RequestTTY=no '
|
|
||||||
. '-o LogLevel=ERROR '
|
|
||||||
. '-o ControlMaster=auto -o ControlPersist=1m -o ControlPath=/var/www/html/storage/app/.ssh/ssh_mux_%h_%p_%r '
|
|
||||||
. "-p {$port} "
|
|
||||||
. "{$user}@{$server_ip} "
|
|
||||||
. " 'bash -se' << \\$delimiter" . PHP_EOL
|
|
||||||
. $command . PHP_EOL
|
|
||||||
. $delimiter;
|
|
||||||
return $ssh_command;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function handleOutput(string $type, string $output)
|
protected function handleOutput(string $type, string $output)
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Console;
|
namespace App\Console;
|
||||||
|
|
||||||
|
use App\Jobs\ContainerStatusJob;
|
||||||
use Illuminate\Console\Scheduling\Schedule;
|
use Illuminate\Console\Scheduling\Schedule;
|
||||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||||
|
|
||||||
@ -12,7 +13,7 @@ class Kernel extends ConsoleKernel
|
|||||||
*/
|
*/
|
||||||
protected function schedule(Schedule $schedule): void
|
protected function schedule(Schedule $schedule): void
|
||||||
{
|
{
|
||||||
// $schedule->command('inspire')->hourly();
|
$schedule->job(new ContainerStatusJob)->everyMinute();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -6,7 +6,7 @@ class HomeController extends Controller
|
|||||||
{
|
{
|
||||||
public function show()
|
public function show()
|
||||||
{
|
{
|
||||||
$projects = session('currentTeam')->projects;
|
$projects = session('currentTeam')->load(['projects'])->projects;
|
||||||
return view('home', ['projects' => $projects]);
|
return view('home', ['projects' => $projects]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Application;
|
||||||
|
use App\Models\Environment;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
@ -9,8 +11,7 @@ class ProjectController extends Controller
|
|||||||
{
|
{
|
||||||
public function environments()
|
public function environments()
|
||||||
{
|
{
|
||||||
$project_uuid = request()->route('project_uuid');
|
$project = session('currentTeam')->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first()->load(['environments']);
|
||||||
$project = session('currentTeam')->projects->where('uuid', $project_uuid)->first();
|
|
||||||
if (!$project) {
|
if (!$project) {
|
||||||
return redirect()->route('home');
|
return redirect()->route('home');
|
||||||
}
|
}
|
||||||
@ -18,94 +19,50 @@ public function environments()
|
|||||||
}
|
}
|
||||||
public function resources()
|
public function resources()
|
||||||
{
|
{
|
||||||
$project_uuid = request()->route('project_uuid');
|
$project = session('currentTeam')->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
|
||||||
$project = session('currentTeam')->projects->where('uuid', $project_uuid)->first();
|
|
||||||
if (!$project) {
|
if (!$project) {
|
||||||
return redirect()->route('home');
|
return redirect()->route('home');
|
||||||
}
|
}
|
||||||
$environment = $project->environments->where('name', request()->route('environment_name'))->first();
|
$environment = $project->load(['environments'])->environments->where('name', request()->route('environment_name'))->first();
|
||||||
|
if (!$environment) {
|
||||||
|
return redirect()->route('home');
|
||||||
|
}
|
||||||
return view('project.resources', ['project' => $project, 'environment' => $environment]);
|
return view('project.resources', ['project' => $project, 'environment' => $environment]);
|
||||||
}
|
}
|
||||||
public function application()
|
public function application()
|
||||||
{
|
{
|
||||||
$project_uuid = request()->route('project_uuid');
|
$project = session('currentTeam')->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
|
||||||
$environment_name = request()->route('environment_name');
|
|
||||||
$application_uuid = request()->route('application_uuid');
|
|
||||||
$project = session('currentTeam')->projects->where('uuid', $project_uuid)->first();
|
|
||||||
if (!$project) {
|
if (!$project) {
|
||||||
return redirect()->route('home');
|
return redirect()->route('home');
|
||||||
}
|
}
|
||||||
$environment = $project->environments->where('name', $environment_name)->first();
|
$environment = $project->load(['environments'])->environments->where('name', request()->route('environment_name'))->first()->load(['applications']);
|
||||||
if (!$environment) {
|
if (!$environment) {
|
||||||
return redirect()->route('home');
|
return redirect()->route('home');
|
||||||
}
|
}
|
||||||
$application = $environment->applications->where('uuid', $application_uuid)->first();
|
$application = $environment->applications->where('uuid', request()->route('application_uuid'))->first();
|
||||||
if (!$application) {
|
if (!$application) {
|
||||||
return redirect()->route('home');
|
return redirect()->route('home');
|
||||||
}
|
}
|
||||||
return view('project.application', ['project' => $project, 'application' => $application, 'deployments' => $application->deployments()]);
|
return view('project.application', ['application' => $application, 'deployments' => $application->deployments()]);
|
||||||
}
|
|
||||||
public function database()
|
|
||||||
{
|
|
||||||
$project_uuid = request()->route('project_uuid');
|
|
||||||
$environment_name = request()->route('environment_name');
|
|
||||||
$database_uuid = request()->route('database_uuid');
|
|
||||||
$project = session('currentTeam')->projects->where('uuid', $project_uuid)->first();
|
|
||||||
if (!$project) {
|
|
||||||
return redirect()->route('home');
|
|
||||||
}
|
|
||||||
$environment = $project->environments->where('name', $environment_name)->first();
|
|
||||||
if (!$environment) {
|
|
||||||
return redirect()->route('home');
|
|
||||||
}
|
|
||||||
$database = $environment->databases->where('uuid', $database_uuid)->first();
|
|
||||||
if (!$database) {
|
|
||||||
return redirect()->route('home');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return view('project.database', ['project' => $project, 'database' => $database]);
|
|
||||||
}
|
|
||||||
public function service()
|
|
||||||
{
|
|
||||||
$project_uuid = request()->route('project_uuid');
|
|
||||||
$environment_name = request()->route('environment_name');
|
|
||||||
$service_uuid = request()->route('service_uuid');
|
|
||||||
|
|
||||||
$project = session('currentTeam')->projects->where('uuid', $project_uuid)->first();
|
|
||||||
if (!$project) {
|
|
||||||
return redirect()->route('home');
|
|
||||||
}
|
|
||||||
$environment = $project->environments->where('name', $environment_name)->first();
|
|
||||||
if (!$environment) {
|
|
||||||
return redirect()->route('home');
|
|
||||||
}
|
|
||||||
$service = $environment->services->where('uuid', $service_uuid)->first();
|
|
||||||
if (!$service) {
|
|
||||||
return redirect()->route('home');
|
|
||||||
}
|
|
||||||
|
|
||||||
return view('project.service', ['project' => $project, 'service' => $service]);
|
|
||||||
}
|
|
||||||
public function deployment()
|
public function deployment()
|
||||||
{
|
{
|
||||||
$project_uuid = request()->route('project_uuid');
|
|
||||||
$environment_name = request()->route('environment_name');
|
|
||||||
$application_uuid = request()->route('application_uuid');
|
|
||||||
$deployment_uuid = request()->route('deployment_uuid');
|
$deployment_uuid = request()->route('deployment_uuid');
|
||||||
|
|
||||||
$project = session('currentTeam')->projects->where('uuid', $project_uuid)->first();
|
$project = session('currentTeam')->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
|
||||||
if (!$project) {
|
if (!$project) {
|
||||||
return redirect()->route('home');
|
return redirect()->route('home');
|
||||||
}
|
}
|
||||||
$environment = $project->environments->where('name', $environment_name)->first();
|
$environment = $project->load(['environments'])->environments->where('name', request()->route('environment_name'))->first()->load(['applications']);
|
||||||
if (!$environment) {
|
if (!$environment) {
|
||||||
return redirect()->route('home');
|
return redirect()->route('home');
|
||||||
}
|
}
|
||||||
$application = $environment->applications->where('uuid', $application_uuid)->first();
|
$application = $environment->applications->where('uuid', request()->route('application_uuid'))->first();
|
||||||
if (!$application) {
|
if (!$application) {
|
||||||
return redirect()->route('home');
|
return redirect()->route('home');
|
||||||
}
|
}
|
||||||
$activity = $application->get_deployment($deployment_uuid);
|
$activity = $application->get_deployment($deployment_uuid);
|
||||||
return view('project.deployment', ['project' => $project, 'activity' => $activity]);
|
return view('project.deployment', ['activity' => $activity]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,12 @@
|
|||||||
|
|
||||||
namespace App\Http\Livewire;
|
namespace App\Http\Livewire;
|
||||||
|
|
||||||
|
use App\Jobs\ContainerStatusJob;
|
||||||
use App\Models\Application;
|
use App\Models\Application;
|
||||||
use App\Models\CoolifyInstanceSettings;
|
use App\Models\CoolifyInstanceSettings;
|
||||||
use DateTimeImmutable;
|
use DateTimeImmutable;
|
||||||
use Illuminate\Support\Facades\Http;
|
use Illuminate\Support\Facades\Http;
|
||||||
|
use Illuminate\Support\Facades\Process;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
use Symfony\Component\Yaml\Yaml;
|
use Symfony\Component\Yaml\Yaml;
|
||||||
use Visus\Cuid2\Cuid2;
|
use Visus\Cuid2\Cuid2;
|
||||||
@ -19,20 +21,31 @@ class DeployApplication extends Component
|
|||||||
{
|
{
|
||||||
public string $application_uuid;
|
public string $application_uuid;
|
||||||
public $activity;
|
public $activity;
|
||||||
|
public $status;
|
||||||
|
public Application $application;
|
||||||
|
public $destination;
|
||||||
|
|
||||||
protected string $deployment_uuid;
|
protected string $deployment_uuid;
|
||||||
protected array $command = [];
|
protected array $command = [];
|
||||||
protected Application $application;
|
|
||||||
protected $destination;
|
|
||||||
protected $source;
|
protected $source;
|
||||||
|
|
||||||
|
public function mount($application_uuid)
|
||||||
|
{
|
||||||
|
$this->application_uuid = $application_uuid;
|
||||||
|
$this->application = Application::where('uuid', $this->application_uuid)->first();
|
||||||
|
$this->destination = $this->application->destination->getMorphClass()::where('id', $this->application->destination->id)->first();
|
||||||
|
}
|
||||||
|
public function render()
|
||||||
|
{
|
||||||
|
return view('livewire.deploy-application');
|
||||||
|
}
|
||||||
private function execute_in_builder(string $command)
|
private function execute_in_builder(string $command)
|
||||||
{
|
{
|
||||||
if ($this->application->settings->is_debug) {
|
|
||||||
return $this->command[] = "docker exec {$this->deployment_uuid} bash -c '{$command}'";
|
return $this->command[] = "docker exec {$this->deployment_uuid} bash -c '{$command}'";
|
||||||
} else {
|
// if ($this->application->settings->is_debug) {
|
||||||
return $this->command[] = "docker exec {$this->deployment_uuid} bash -c '{$command}' > /dev/null 2>&1";
|
// } else {
|
||||||
}
|
// return $this->command[] = "docker exec {$this->deployment_uuid} bash -c '{$command}'";
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
private function start_builder_container()
|
private function start_builder_container()
|
||||||
{
|
{
|
||||||
@ -45,7 +58,6 @@ private function generate_docker_compose()
|
|||||||
'services' => [
|
'services' => [
|
||||||
$this->application->uuid => [
|
$this->application->uuid => [
|
||||||
'image' => "{$this->application->uuid}:TAG",
|
'image' => "{$this->application->uuid}:TAG",
|
||||||
'expose' => $this->application->ports_exposes,
|
|
||||||
'container_name' => $this->application->uuid,
|
'container_name' => $this->application->uuid,
|
||||||
'restart' => 'always',
|
'restart' => 'always',
|
||||||
'labels' => $this->set_labels_for_applications(),
|
'labels' => $this->set_labels_for_applications(),
|
||||||
@ -144,7 +156,6 @@ private function generate_jwt_token_for_github()
|
|||||||
public function deploy()
|
public function deploy()
|
||||||
{
|
{
|
||||||
$coolify_instance_settings = CoolifyInstanceSettings::find(1);
|
$coolify_instance_settings = CoolifyInstanceSettings::find(1);
|
||||||
$this->application = Application::where('uuid', $this->application_uuid)->first();
|
|
||||||
$this->destination = $this->application->destination->getMorphClass()::where('id', $this->application->destination->id)->first();
|
$this->destination = $this->application->destination->getMorphClass()::where('id', $this->application->destination->id)->first();
|
||||||
$this->source = $this->application->source->getMorphClass()::where('id', $this->application->source->id)->first();
|
$this->source = $this->application->source->getMorphClass()::where('id', $this->application->source->id)->first();
|
||||||
|
|
||||||
@ -220,7 +231,7 @@ public function deploy()
|
|||||||
|
|
||||||
$this->execute_in_builder("docker build -f {$workdir}/Dockerfile --build-arg SOURCE_COMMIT=$(cat {$workdir}/.git-commit) --progress plain -t {$this->application->uuid}:$(cat {$workdir}/.git-commit) {$workdir}");
|
$this->execute_in_builder("docker build -f {$workdir}/Dockerfile --build-arg SOURCE_COMMIT=$(cat {$workdir}/.git-commit) --progress plain -t {$this->application->uuid}:$(cat {$workdir}/.git-commit) {$workdir}");
|
||||||
$this->command[] = "echo 'Done.'";
|
$this->command[] = "echo 'Done.'";
|
||||||
$this->execute_in_builder("test ! -z \"$(docker ps --format '{{.State}}' --filter 'name={$this->application->uuid}')\" && docker rm -f {$this->application->uuid} >/dev/null 2>&1");
|
$this->execute_in_builder("docker rm -f {$this->application->uuid} >/dev/null 2>&1");
|
||||||
|
|
||||||
$this->command[] = "echo -n 'Deploying... '";
|
$this->command[] = "echo -n 'Deploying... '";
|
||||||
|
|
||||||
@ -233,11 +244,26 @@ public function deploy()
|
|||||||
$deploymentUrl = "$currentUrl/deployment/$this->deployment_uuid";
|
$deploymentUrl = "$currentUrl/deployment/$this->deployment_uuid";
|
||||||
return redirect($deploymentUrl);
|
return redirect($deploymentUrl);
|
||||||
}
|
}
|
||||||
public function cancel()
|
|
||||||
|
public function stop()
|
||||||
{
|
{
|
||||||
|
runRemoteCommandSync($this->destination->server, ["docker rm -f {$this->application_uuid} >/dev/null 2>&1"]);
|
||||||
|
$this->application->status = 'exited';
|
||||||
|
$this->application->save();
|
||||||
}
|
}
|
||||||
public function render()
|
public function pollingStatus()
|
||||||
{
|
{
|
||||||
return view('livewire.deploy-application');
|
$this->application->refresh();
|
||||||
|
}
|
||||||
|
public function checkStatus()
|
||||||
|
{
|
||||||
|
$output = runRemoteCommandSync($this->destination->server, ["docker ps -a --format '{{.State}}' --filter 'name={$this->application->uuid}'"]);
|
||||||
|
if ($output == '') {
|
||||||
|
$this->application->status = 'exited';
|
||||||
|
$this->application->save();
|
||||||
|
} else {
|
||||||
|
$this->application->status = $output;
|
||||||
|
$this->application->save();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
60
app/Jobs/ContainerStatusJob.php
Normal file
60
app/Jobs/ContainerStatusJob.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Jobs;
|
||||||
|
|
||||||
|
use App\Actions\RemoteProcess\RunRemoteProcess;
|
||||||
|
use App\Models\Application;
|
||||||
|
use App\Models\Server;
|
||||||
|
use App\Traits\Docker;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Support\Facades\Process;
|
||||||
|
use Tests\Support\Output;
|
||||||
|
|
||||||
|
class ContainerStatusJob implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
public function handle(): void
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$servers = Server::all()->reject(fn (Server $server) => $server->settings->is_build_server);
|
||||||
|
$applications = Application::all();
|
||||||
|
$not_found_applications = $applications;
|
||||||
|
$containers = collect();
|
||||||
|
foreach ($servers as $server) {
|
||||||
|
$output = runRemoteCommandSync($server, ['docker ps -a -q --format \'{{json .}}\'']);
|
||||||
|
$containers = $containers->concat(formatDockerCmdOutputToJson($output));
|
||||||
|
}
|
||||||
|
foreach ($containers as $container) {
|
||||||
|
$found_application = $applications->filter(function ($value, $key) use ($container) {
|
||||||
|
return $value->uuid == $container['Names'];
|
||||||
|
})->first();
|
||||||
|
if ($found_application) {
|
||||||
|
$not_found_applications = $not_found_applications->filter(function ($value, $key) use ($found_application) {
|
||||||
|
return $value->uuid != $found_application->uuid;
|
||||||
|
});
|
||||||
|
$found_application->status = $container['State'];
|
||||||
|
$found_application->save();
|
||||||
|
Log::info('Found application: ' . $found_application->uuid . '. Set status to: ' . $found_application->status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach ($not_found_applications as $not_found_application) {
|
||||||
|
$not_found_application->status = 'exited';
|
||||||
|
$not_found_application->save();
|
||||||
|
Log::info('Not found application: ' . $not_found_application->uuid . '. Set status to: ' . $not_found_application->status);
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error($e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -18,4 +18,7 @@ public function environments() {
|
|||||||
public function settings() {
|
public function settings() {
|
||||||
return $this->hasOne(ProjectSetting::class);
|
return $this->hasOne(ProjectSetting::class);
|
||||||
}
|
}
|
||||||
|
public function applications() {
|
||||||
|
return $this->hasManyThrough(Application::class, Environment::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,20 @@
|
|||||||
|
|
||||||
class Server extends BaseModel
|
class Server extends BaseModel
|
||||||
{
|
{
|
||||||
|
protected static function booted()
|
||||||
|
{
|
||||||
|
static::created(function ($server) {
|
||||||
|
ServerSetting::create([
|
||||||
|
'server_id' => $server->id,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
public function privateKey()
|
public function privateKey()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(PrivateKey::class);
|
return $this->belongsTo(PrivateKey::class);
|
||||||
}
|
}
|
||||||
|
public function settings()
|
||||||
|
{
|
||||||
|
return $this->hasOne(ServerSetting::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
11
app/Models/ServerSetting.php
Normal file
11
app/Models/ServerSetting.php
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
class ServerSetting extends BaseModel
|
||||||
|
{
|
||||||
|
public function server()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Server::class);
|
||||||
|
}
|
||||||
|
}
|
@ -16,4 +16,7 @@ public function projects() {
|
|||||||
public function servers() {
|
public function servers() {
|
||||||
return $this->hasMany(Server::class);
|
return $this->hasMany(Server::class);
|
||||||
}
|
}
|
||||||
|
public function applications() {
|
||||||
|
return $this->hasManyThrough(Application::class, Project::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
use App\Enums\ActivityTypes;
|
use App\Enums\ActivityTypes;
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Support\Facades\Process;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Spatie\Activitylog\Contracts\Activity;
|
use Spatie\Activitylog\Contracts\Activity;
|
||||||
|
|
||||||
@ -24,33 +27,105 @@ function remoteProcess(
|
|||||||
// @TODO: Check if the user has access to this server
|
// @TODO: Check if the user has access to this server
|
||||||
// checkTeam($server->team_id);
|
// checkTeam($server->team_id);
|
||||||
|
|
||||||
$temp_file = 'id.rsa_' . 'root' . '@' . $server->ip;
|
$private_key_location = savePrivateKey($server);
|
||||||
Storage::disk('local')->put($temp_file, $server->privateKey->private_key, 'private');
|
|
||||||
$private_key_location = '/var/www/html/storage/app/' . $temp_file;
|
|
||||||
|
|
||||||
return resolve(DispatchRemoteProcess::class, [
|
return resolve(DispatchRemoteProcess::class, [
|
||||||
'remoteProcessArgs' => new RemoteProcessArgs(
|
'remoteProcessArgs' => new RemoteProcessArgs(
|
||||||
|
type: $deployment_uuid ? ActivityTypes::DEPLOYMENT->value : ActivityTypes::REMOTE_PROCESS->value,
|
||||||
model: $model,
|
model: $model,
|
||||||
server_ip: $server->ip,
|
server_ip: $server->ip,
|
||||||
private_key_location: $private_key_location,
|
|
||||||
deployment_uuid: $deployment_uuid,
|
deployment_uuid: $deployment_uuid,
|
||||||
|
private_key_location: $private_key_location,
|
||||||
command: <<<EOT
|
command: <<<EOT
|
||||||
{$command_string}
|
{$command_string}
|
||||||
EOT,
|
EOT,
|
||||||
port: $server->port,
|
port: $server->port,
|
||||||
user: $server->user,
|
user: $server->user,
|
||||||
type: $deployment_uuid ? ActivityTypes::DEPLOYMENT->value : ActivityTypes::REMOTE_PROCESS->value,
|
|
||||||
),
|
),
|
||||||
])();
|
])();
|
||||||
}
|
}
|
||||||
|
// function checkTeam(string $team_id)
|
||||||
|
// {
|
||||||
|
// $found_team = auth()->user()->teams->pluck('id')->contains($team_id);
|
||||||
|
// if (!$found_team) {
|
||||||
|
// throw new \RuntimeException('You do not have access to this server.');
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!function_exists('checkTeam')) {
|
if (!function_exists('savePrivateKey')) {
|
||||||
function checkTeam(string $team_id)
|
function savePrivateKey(Server $server)
|
||||||
{
|
{
|
||||||
$found_team = auth()->user()->teams->pluck('id')->contains($team_id);
|
$temp_file = 'id.rsa_' . 'root' . '@' . $server->ip;
|
||||||
if (!$found_team) {
|
Storage::disk('local')->put($temp_file, $server->privateKey->private_key, 'private');
|
||||||
throw new \RuntimeException('You do not have access to this server.');
|
return '/var/www/html/storage/app/' . $temp_file;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('generateSshCommand')) {
|
||||||
|
function generateSshCommand(string $private_key_location, string $server_ip, string $user, string $port, string $command, bool $isMux = true)
|
||||||
|
{
|
||||||
|
$delimiter = 'EOF-COOLIFY-SSH';
|
||||||
|
Storage::disk('local')->makeDirectory('.ssh');
|
||||||
|
$ssh_command = "ssh ";
|
||||||
|
if ($isMux) {
|
||||||
|
$ssh_command .= '-o ControlMaster=auto -o ControlPersist=1m -o ControlPath=/var/www/html/storage/app/.ssh/ssh_mux_%h_%p_%r ';
|
||||||
|
}
|
||||||
|
$ssh_command .= "-i {$private_key_location} "
|
||||||
|
. '-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null '
|
||||||
|
. '-o PasswordAuthentication=no '
|
||||||
|
. '-o RequestTTY=no '
|
||||||
|
. '-o LogLevel=ERROR '
|
||||||
|
. "-p {$port} "
|
||||||
|
. "{$user}@{$server_ip} "
|
||||||
|
. " 'bash -se' << \\$delimiter" . PHP_EOL
|
||||||
|
. $command . PHP_EOL
|
||||||
|
. $delimiter;
|
||||||
|
|
||||||
|
return $ssh_command;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!function_exists('formatDockerCmdOutputToJson')) {
|
||||||
|
function formatDockerCmdOutputToJson($rawOutput): Collection
|
||||||
|
{
|
||||||
|
$outputLines = explode(PHP_EOL, $rawOutput);
|
||||||
|
|
||||||
|
return collect($outputLines)
|
||||||
|
->reject(fn ($line) => empty($line))
|
||||||
|
->map(fn ($outputLine) => json_decode($outputLine, true, flags: JSON_THROW_ON_ERROR));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!function_exists('formatDockerLabelsToJson')) {
|
||||||
|
function formatDockerLabelsToJson($rawOutput): Collection
|
||||||
|
{
|
||||||
|
$outputLines = explode(PHP_EOL, $rawOutput);
|
||||||
|
|
||||||
|
return collect($outputLines)
|
||||||
|
->reject(fn ($line) => empty($line))
|
||||||
|
->map(function ($outputLine) {
|
||||||
|
$outputArray = explode(',', $outputLine);
|
||||||
|
return collect($outputArray)
|
||||||
|
->map(function ($outputLine) {
|
||||||
|
return explode('=', $outputLine);
|
||||||
|
})
|
||||||
|
->mapWithKeys(function ($outputLine) {
|
||||||
|
return [$outputLine[0] => $outputLine[1]];
|
||||||
|
});
|
||||||
|
})[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!function_exists('runRemoteCommandSync')) {
|
||||||
|
function runRemoteCommandSync($server, array $command) {
|
||||||
|
$command_string = implode("\n", $command);
|
||||||
|
$private_key_location = savePrivateKey($server);
|
||||||
|
$ssh_command = generateSshCommand($private_key_location, $server->ip, $server->user, $server->port, $command_string);
|
||||||
|
$process = Process::run($ssh_command);
|
||||||
|
$output = trim($process->output());
|
||||||
|
$exitCode = $process->exitCode();
|
||||||
|
if ($exitCode !== 0) {
|
||||||
|
Log::error($output);
|
||||||
|
throw new \RuntimeException('There was an error running the command.');
|
||||||
|
}
|
||||||
|
return $output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
72
composer.lock
generated
72
composer.lock
generated
@ -1193,16 +1193,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "laravel/framework",
|
"name": "laravel/framework",
|
||||||
"version": "v10.4.1",
|
"version": "v10.5.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/laravel/framework.git",
|
"url": "https://github.com/laravel/framework.git",
|
||||||
"reference": "7d15f7eef442633cff108f83d9fe43d8c3b8b76f"
|
"reference": "485f22333e8c1dff5bae0fe0421c1e2e139713de"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/laravel/framework/zipball/7d15f7eef442633cff108f83d9fe43d8c3b8b76f",
|
"url": "https://api.github.com/repos/laravel/framework/zipball/485f22333e8c1dff5bae0fe0421c1e2e139713de",
|
||||||
"reference": "7d15f7eef442633cff108f83d9fe43d8c3b8b76f",
|
"reference": "485f22333e8c1dff5bae0fe0421c1e2e139713de",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -1389,7 +1389,7 @@
|
|||||||
"issues": "https://github.com/laravel/framework/issues",
|
"issues": "https://github.com/laravel/framework/issues",
|
||||||
"source": "https://github.com/laravel/framework"
|
"source": "https://github.com/laravel/framework"
|
||||||
},
|
},
|
||||||
"time": "2023-03-18T11:34:02+00:00"
|
"time": "2023-03-29T15:09:16+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "laravel/sanctum",
|
"name": "laravel/sanctum",
|
||||||
@ -2683,16 +2683,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpdocumentor/type-resolver",
|
"name": "phpdocumentor/type-resolver",
|
||||||
"version": "1.7.0",
|
"version": "1.7.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/phpDocumentor/TypeResolver.git",
|
"url": "https://github.com/phpDocumentor/TypeResolver.git",
|
||||||
"reference": "1534aea9bde19a5c85c5d1e1f834ab63f4c5dcf5"
|
"reference": "dfc078e8af9c99210337325ff5aa152872c98714"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/1534aea9bde19a5c85c5d1e1f834ab63f4c5dcf5",
|
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/dfc078e8af9c99210337325ff5aa152872c98714",
|
||||||
"reference": "1534aea9bde19a5c85c5d1e1f834ab63f4c5dcf5",
|
"reference": "dfc078e8af9c99210337325ff5aa152872c98714",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -2735,9 +2735,9 @@
|
|||||||
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
|
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/phpDocumentor/TypeResolver/issues",
|
"issues": "https://github.com/phpDocumentor/TypeResolver/issues",
|
||||||
"source": "https://github.com/phpDocumentor/TypeResolver/tree/1.7.0"
|
"source": "https://github.com/phpDocumentor/TypeResolver/tree/1.7.1"
|
||||||
},
|
},
|
||||||
"time": "2023-03-12T10:13:29+00:00"
|
"time": "2023-03-27T19:02:04+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpoption/phpoption",
|
"name": "phpoption/phpoption",
|
||||||
@ -3378,16 +3378,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "psy/psysh",
|
"name": "psy/psysh",
|
||||||
"version": "v0.11.13",
|
"version": "v0.11.14",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/bobthecow/psysh.git",
|
"url": "https://github.com/bobthecow/psysh.git",
|
||||||
"reference": "722317c9f5627e588788e340f29b923e58f92f54"
|
"reference": "8c2e264def7a8263a68ef6f0b55ce90b77d41e17"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/bobthecow/psysh/zipball/722317c9f5627e588788e340f29b923e58f92f54",
|
"url": "https://api.github.com/repos/bobthecow/psysh/zipball/8c2e264def7a8263a68ef6f0b55ce90b77d41e17",
|
||||||
"reference": "722317c9f5627e588788e340f29b923e58f92f54",
|
"reference": "8c2e264def7a8263a68ef6f0b55ce90b77d41e17",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -3448,9 +3448,9 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/bobthecow/psysh/issues",
|
"issues": "https://github.com/bobthecow/psysh/issues",
|
||||||
"source": "https://github.com/bobthecow/psysh/tree/v0.11.13"
|
"source": "https://github.com/bobthecow/psysh/tree/v0.11.14"
|
||||||
},
|
},
|
||||||
"time": "2023-03-21T14:22:44+00:00"
|
"time": "2023-03-28T03:41:01+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ralouphie/getallheaders",
|
"name": "ralouphie/getallheaders",
|
||||||
@ -7534,16 +7534,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "laravel/sail",
|
"name": "laravel/sail",
|
||||||
"version": "v1.21.2",
|
"version": "v1.21.3",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/laravel/sail.git",
|
"url": "https://github.com/laravel/sail.git",
|
||||||
"reference": "19d6fe167e2389b41fe1b4ee52293d1eaf8a43fc"
|
"reference": "3042ff8cf403817c340d5a7762b2d32900239f46"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/laravel/sail/zipball/19d6fe167e2389b41fe1b4ee52293d1eaf8a43fc",
|
"url": "https://api.github.com/repos/laravel/sail/zipball/3042ff8cf403817c340d5a7762b2d32900239f46",
|
||||||
"reference": "19d6fe167e2389b41fe1b4ee52293d1eaf8a43fc",
|
"reference": "3042ff8cf403817c340d5a7762b2d32900239f46",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -7595,7 +7595,7 @@
|
|||||||
"issues": "https://github.com/laravel/sail/issues",
|
"issues": "https://github.com/laravel/sail/issues",
|
||||||
"source": "https://github.com/laravel/sail"
|
"source": "https://github.com/laravel/sail"
|
||||||
},
|
},
|
||||||
"time": "2023-03-06T14:23:15+00:00"
|
"time": "2023-03-13T01:22:10+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "mockery/mockery",
|
"name": "mockery/mockery",
|
||||||
@ -7889,16 +7889,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "pestphp/pest",
|
"name": "pestphp/pest",
|
||||||
"version": "v2.2.3",
|
"version": "v2.3.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/pestphp/pest.git",
|
"url": "https://github.com/pestphp/pest.git",
|
||||||
"reference": "6c8970e0a3b9bb36544bb1eacba0a4175dbafe97"
|
"reference": "5ae061d2080ea09608fe37fb05ebadcd183cef85"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/pestphp/pest/zipball/6c8970e0a3b9bb36544bb1eacba0a4175dbafe97",
|
"url": "https://api.github.com/repos/pestphp/pest/zipball/5ae061d2080ea09608fe37fb05ebadcd183cef85",
|
||||||
"reference": "6c8970e0a3b9bb36544bb1eacba0a4175dbafe97",
|
"reference": "5ae061d2080ea09608fe37fb05ebadcd183cef85",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -7908,10 +7908,10 @@
|
|||||||
"pestphp/pest-plugin": "^2.0.1",
|
"pestphp/pest-plugin": "^2.0.1",
|
||||||
"pestphp/pest-plugin-arch": "^2.0.2",
|
"pestphp/pest-plugin-arch": "^2.0.2",
|
||||||
"php": "^8.1.0",
|
"php": "^8.1.0",
|
||||||
"phpunit/phpunit": "^10.0.18"
|
"phpunit/phpunit": "^10.0.19"
|
||||||
},
|
},
|
||||||
"conflict": {
|
"conflict": {
|
||||||
"phpunit/phpunit": ">10.0.18",
|
"phpunit/phpunit": ">10.0.19",
|
||||||
"webmozart/assert": "<1.11.0"
|
"webmozart/assert": "<1.11.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
@ -7972,7 +7972,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/pestphp/pest/issues",
|
"issues": "https://github.com/pestphp/pest/issues",
|
||||||
"source": "https://github.com/pestphp/pest/tree/v2.2.3"
|
"source": "https://github.com/pestphp/pest/tree/v2.3.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -7984,7 +7984,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-03-24T11:26:54+00:00"
|
"time": "2023-03-28T09:16:29+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "pestphp/pest-plugin",
|
"name": "pestphp/pest-plugin",
|
||||||
@ -8606,16 +8606,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpunit/phpunit",
|
"name": "phpunit/phpunit",
|
||||||
"version": "10.0.18",
|
"version": "10.0.19",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||||
"reference": "582563ed2edc62d1455cdbe00ea49fe09428eef3"
|
"reference": "20c23e85c86e5c06d63538ba464e8054f4744e62"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/582563ed2edc62d1455cdbe00ea49fe09428eef3",
|
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/20c23e85c86e5c06d63538ba464e8054f4744e62",
|
||||||
"reference": "582563ed2edc62d1455cdbe00ea49fe09428eef3",
|
"reference": "20c23e85c86e5c06d63538ba464e8054f4744e62",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -8687,7 +8687,7 @@
|
|||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||||
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
||||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.0.18"
|
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.0.19"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -8703,7 +8703,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-03-22T06:15:31+00:00"
|
"time": "2023-03-27T11:46:33+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sebastian/cli-parser",
|
"name": "sebastian/cli-parser",
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('server_settings', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('uuid')->unique();
|
||||||
|
$table->boolean('is_build_server')->default(false);
|
||||||
|
|
||||||
|
$table->foreignId('server_id');
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('server_settings');
|
||||||
|
}
|
||||||
|
};
|
@ -52,7 +52,7 @@ public function up(): void
|
|||||||
$table->integer('health_check_retries')->default(10);
|
$table->integer('health_check_retries')->default(10);
|
||||||
$table->integer('health_check_start_period')->default(5);
|
$table->integer('health_check_start_period')->default(5);
|
||||||
|
|
||||||
$table->string('status')->default('killed');
|
$table->string('status')->default('exited');
|
||||||
|
|
||||||
$table->morphs('destination');
|
$table->morphs('destination');
|
||||||
$table->morphs('source');
|
$table->morphs('source');
|
||||||
|
@ -25,7 +25,7 @@ public function run(): void
|
|||||||
$github_private_source = GithubApp::find(2);
|
$github_private_source = GithubApp::find(2);
|
||||||
Application::create([
|
Application::create([
|
||||||
'id' => 1,
|
'id' => 1,
|
||||||
'name' => 'My first application',
|
'name' => 'Public application (from GitHub)',
|
||||||
'git_repository' => 'coollabsio/coolify-examples',
|
'git_repository' => 'coollabsio/coolify-examples',
|
||||||
'git_branch' => 'nodejs-fastify',
|
'git_branch' => 'nodejs-fastify',
|
||||||
'build_pack' => 'nixpacks',
|
'build_pack' => 'nixpacks',
|
||||||
@ -39,7 +39,7 @@ public function run(): void
|
|||||||
]);
|
]);
|
||||||
Application::create([
|
Application::create([
|
||||||
'id' => 2,
|
'id' => 2,
|
||||||
'name' => 'My second application',
|
'name' => 'Private application (through GitHub App)',
|
||||||
'git_repository' => 'coollabsio/nodejs-example',
|
'git_repository' => 'coollabsio/nodejs-example',
|
||||||
'git_branch' => 'main',
|
'git_branch' => 'main',
|
||||||
'build_pack' => 'nixpacks',
|
'build_pack' => 'nixpacks',
|
||||||
|
@ -13,12 +13,12 @@ public function run(): void
|
|||||||
{
|
{
|
||||||
$environment_1 = Environment::find(1);
|
$environment_1 = Environment::find(1);
|
||||||
$standalone_docker_1 = StandaloneDocker::find(1);
|
$standalone_docker_1 = StandaloneDocker::find(1);
|
||||||
Database::create([
|
// Database::create([
|
||||||
'id' => 1,
|
// 'id' => 1,
|
||||||
'name'=> "My first database",
|
// 'name'=> "My first database",
|
||||||
'environment_id' => $environment_1->id,
|
// 'environment_id' => $environment_1->id,
|
||||||
'destination_id' => $standalone_docker_1->id,
|
// 'destination_id' => $standalone_docker_1->id,
|
||||||
'destination_type' => StandaloneDocker::class,
|
// 'destination_type' => StandaloneDocker::class,
|
||||||
]);
|
// ]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ public function run(): void
|
|||||||
TeamSeeder::class,
|
TeamSeeder::class,
|
||||||
PrivateKeySeeder::class,
|
PrivateKeySeeder::class,
|
||||||
ServerSeeder::class,
|
ServerSeeder::class,
|
||||||
|
ServerSettingSeeder::class,
|
||||||
ProjectSeeder::class,
|
ProjectSeeder::class,
|
||||||
ProjectSettingSeeder::class,
|
ProjectSettingSeeder::class,
|
||||||
EnvironmentSeeder::class,
|
EnvironmentSeeder::class,
|
||||||
|
25
database/seeders/ServerSettingSeeder.php
Normal file
25
database/seeders/ServerSettingSeeder.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use App\Models\Server;
|
||||||
|
use App\Models\Team;
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
|
||||||
|
class ServerSettingSeeder extends Seeder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the database seeds.
|
||||||
|
*/
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
$server_1 = Server::find(1)->load(['settings']);
|
||||||
|
$server_1->settings->is_build_server = true;
|
||||||
|
$server_1->settings->save();
|
||||||
|
|
||||||
|
$server_2 = Server::find(2)->load(['settings']);
|
||||||
|
$server_2->settings->is_build_server = true;
|
||||||
|
$server_2->settings->save();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -16,12 +16,12 @@ public function run(): void
|
|||||||
{
|
{
|
||||||
$environment_1 = Environment::find(1);
|
$environment_1 = Environment::find(1);
|
||||||
$standalone_docker_1 = StandaloneDocker::find(1);
|
$standalone_docker_1 = StandaloneDocker::find(1);
|
||||||
Service::create([
|
// Service::create([
|
||||||
'id' => 1,
|
// 'id' => 1,
|
||||||
'name'=> "My first service",
|
// 'name'=> "My first service",
|
||||||
'environment_id' => $environment_1->id,
|
// 'environment_id' => $environment_1->id,
|
||||||
'destination_id' => $standalone_docker_1->id,
|
// 'destination_id' => $standalone_docker_1->id,
|
||||||
'destination_type' => StandaloneDocker::class,
|
// 'destination_type' => StandaloneDocker::class,
|
||||||
]);
|
// ]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,5 +22,5 @@ RUN curl -sSL https://nixpacks.com/install.sh | bash
|
|||||||
RUN chmod +x ~/.docker/cli-plugins/docker-compose /usr/bin/docker /usr/local/bin/pack
|
RUN chmod +x ~/.docker/cli-plugins/docker-compose /usr/bin/docker /usr/local/bin/pack
|
||||||
|
|
||||||
ENTRYPOINT ["/sbin/tini", "--"]
|
ENTRYPOINT ["/sbin/tini", "--"]
|
||||||
CMD ["sh", "-c", "while true; do sleep 1000; done"]
|
CMD ["sh", "-c", "while true; do sleep 69420; done"]
|
||||||
|
|
||||||
|
@ -27,3 +27,16 @@ stderr_logfile_maxbytes=0
|
|||||||
#redirect_stderr=true
|
#redirect_stderr=true
|
||||||
#stdout_logfile=/var/www/html/storage/logs/worker.log
|
#stdout_logfile=/var/www/html/storage/logs/worker.log
|
||||||
#stopwaitsecs=3600
|
#stopwaitsecs=3600
|
||||||
|
|
||||||
|
[program:laravel-schedule]
|
||||||
|
process_name=%(program_name)s_%(process_num)02d
|
||||||
|
command=/usr/bin/php -d variables_order=EGPCS /var/www/html/artisan schedule:work
|
||||||
|
user=sail
|
||||||
|
autostart=true
|
||||||
|
autorestart=true
|
||||||
|
stopasgroup=true
|
||||||
|
killasgroup=true
|
||||||
|
numprocs=1
|
||||||
|
redirect_stderr=true
|
||||||
|
stdout_logfile=/var/www/html/storage/logs/worker.log
|
||||||
|
stopwaitsecs=3600
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
<div>
|
|
||||||
@isset($activity?->id)
|
|
||||||
<div>
|
|
||||||
Activity: <span>{{ $activity?->id ?? 'waiting' }}</span>
|
|
||||||
</div>
|
|
||||||
<pre style="width: 100%;overflow-y: scroll;" @if ($isKeepAliveOn) wire:poll.750ms="polling" @endif>{{ data_get($activity, 'description') }}</pre>
|
|
||||||
@endisset
|
|
||||||
<button wire:click='deploy'>Deploy</button>
|
|
||||||
</div>
|
|
@ -1,4 +1,6 @@
|
|||||||
<div>
|
<div>
|
||||||
<button wire:click='deploy'>Deploy</button>
|
<button wire:click='deploy'>Deploy</button>
|
||||||
<button wire:click='cancel'>Cancel</button>
|
<button wire:click='stop'>Stop</button>
|
||||||
|
<button wire:click='checkStatus'>CheckStatus</button>
|
||||||
|
<span wire:poll='pollingStatus'>status: {{ $application->status }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,4 +2,5 @@
|
|||||||
@isset($activity?->id)
|
@isset($activity?->id)
|
||||||
<pre style="width: 100%;overflow-y: scroll;" @if ($isKeepAliveOn) wire:poll.750ms="polling" @endif>{{ data_get($activity, 'description') }}</pre>
|
<pre style="width: 100%;overflow-y: scroll;" @if ($isKeepAliveOn) wire:poll.750ms="polling" @endif>{{ data_get($activity, 'description') }}</pre>
|
||||||
@endisset
|
@endisset
|
||||||
|
{{-- <pre style="width: 100%;overflow-y: scroll;">{{ data_get($activity, 'properties') }}</pre> --}}
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
<x-layout>
|
<x-layout>
|
||||||
<h1>Application</h1>
|
<h1>Application</h1>
|
||||||
<p>Name: {{ $project->name }}</p>
|
<p>Name: {{ $application->name }}</p>
|
||||||
<p>UUID: {{ $project->uuid }}</p>
|
|
||||||
<livewire:deploy-application :application_uuid="$application->uuid" />
|
<livewire:deploy-application :application_uuid="$application->uuid" />
|
||||||
<div>
|
<div>
|
||||||
<h1>Deployments</h1>
|
<h2>Deployments</h2>
|
||||||
@foreach ($deployments as $deployment)
|
@foreach ($deployments as $deployment)
|
||||||
<p>
|
<p>
|
||||||
<a href="{{ url()->current() }}/deployment/{{ data_get($deployment->properties, 'deployment_uuid') }}">
|
<a href="{{ url()->current() }}/deployment/{{ data_get($deployment->properties, 'deployment_uuid') }}">
|
||||||
{{ data_get($deployment->properties, 'deployment_uuid') }}</a>
|
{{ data_get($deployment->properties, 'deployment_uuid') }}</a>
|
||||||
|
{{ data_get($deployment->properties, 'status') }}
|
||||||
</p>
|
</p>
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
<x-layout>
|
<x-layout>
|
||||||
<h1>Deployment</h1>
|
<h1>Deployment</h1>
|
||||||
<p>Name: {{ $project->name }}</p>
|
|
||||||
<p>UUID: {{ $project->uuid }}</p>
|
|
||||||
|
|
||||||
<livewire:poll-activity :activity="$activity" />
|
<livewire:poll-activity :activity="$activity" />
|
||||||
</x-layout>
|
</x-layout>
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
<x-layout>
|
<x-layout>
|
||||||
<h1>Environments</h1>
|
<h1>Environments</h1>
|
||||||
|
|
||||||
@foreach ($project->environments as $environment)
|
@foreach ($project->environments as $environment)
|
||||||
<div>
|
<div>
|
||||||
<a href="{{ route('project.resources', [$project->uuid, $environment->name]) }}">
|
<a href="{{ route('project.resources', [$project->uuid, $environment->name]) }}">
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
@endforeach
|
@endforeach
|
||||||
@foreach ($environment->databases as $database)
|
{{-- @foreach ($environment->databases as $database)
|
||||||
<p>
|
<p>
|
||||||
<a href="{{ route('project.database', [$project->uuid, $environment->name, $database->uuid]) }}">
|
<a href="{{ route('project.database', [$project->uuid, $environment->name, $database->uuid]) }}">
|
||||||
{{ $database->name }}
|
{{ $database->name }}
|
||||||
@ -21,6 +21,6 @@
|
|||||||
{{ $service->name }}
|
{{ $service->name }}
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
@endforeach
|
@endforeach --}}
|
||||||
</div>
|
</div>
|
||||||
</x-layout>
|
</x-layout>
|
||||||
|
@ -26,8 +26,8 @@
|
|||||||
Route::get('/project/{project_uuid}/{environment_name}/application/{application_uuid}', [ProjectController::class, 'application'])->name('project.application');
|
Route::get('/project/{project_uuid}/{environment_name}/application/{application_uuid}', [ProjectController::class, 'application'])->name('project.application');
|
||||||
Route::get('/project/{project_uuid}/{environment_name}/application/{application_uuid}/deployment/{deployment_uuid}', [ProjectController::class, 'deployment'])->name('project.deployment');
|
Route::get('/project/{project_uuid}/{environment_name}/application/{application_uuid}/deployment/{deployment_uuid}', [ProjectController::class, 'deployment'])->name('project.deployment');
|
||||||
|
|
||||||
Route::get('/project/{project_uuid}/{environment_name}/database/{database_uuid}', [ProjectController::class, 'database'])->name('project.database');
|
// Route::get('/database/{database_uuid}', [ProjectController::class, 'database'])->name('project.database');
|
||||||
Route::get('/project/{project_uuid}/{environment_name}/service/{service_uuid}', [ProjectController::class, 'service'])->name('project.service');
|
// Route::get('//service/{service_uuid}', [ProjectController::class, 'service'])->name('project.service');
|
||||||
|
|
||||||
Route::get('/profile', function () {
|
Route::get('/profile', function () {
|
||||||
return view('profile');
|
return view('profile');
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
|
|
||||||
// Assert there's no containers start with coolify_test_*
|
// Assert there's no containers start with coolify_test_*
|
||||||
$activity = remoteProcess([$areThereCoolifyTestContainers], $host);
|
$activity = remoteProcess([$areThereCoolifyTestContainers], $host);
|
||||||
$containers = Output::containerList($activity->getExtraProperty('stdout'));
|
$containers = formatDockerCmdOutputToJson($activity->getExtraProperty('stdout'));
|
||||||
expect($containers)->toBeEmpty();
|
expect($containers)->toBeEmpty();
|
||||||
|
|
||||||
// start a container nginx -d --name = $containerName
|
// start a container nginx -d --name = $containerName
|
||||||
@ -55,7 +55,7 @@
|
|||||||
|
|
||||||
// docker ps name = $container
|
// docker ps name = $container
|
||||||
$activity = remoteProcess([$areThereCoolifyTestContainers], $host);
|
$activity = remoteProcess([$areThereCoolifyTestContainers], $host);
|
||||||
$containers = Output::containerList($activity->getExtraProperty('stdout'));
|
$containers = formatDockerCmdOutputToJson($activity->getExtraProperty('stdout'));
|
||||||
expect($containers->where('Names', $containerName)->count())->toBe(1);
|
expect($containers->where('Names', $containerName)->count())->toBe(1);
|
||||||
|
|
||||||
// Stop testing containers
|
// Stop testing containers
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Support;
|
|
||||||
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
|
|
||||||
class Output
|
|
||||||
{
|
|
||||||
public static function containerList($rawOutput): Collection
|
|
||||||
{
|
|
||||||
$outputLines = explode(PHP_EOL, $rawOutput);
|
|
||||||
|
|
||||||
return collect($outputLines)
|
|
||||||
->reject(fn($line) => empty($line))
|
|
||||||
->map(fn($outputLine) => json_decode($outputLine, flags: JSON_THROW_ON_ERROR));
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user