Refactor to remove slices and environments, replace with instances.

This commit is contained in:
2025-09-15 12:19:13 +01:00
parent a91780d1d5
commit 65d3142d03
24 changed files with 454 additions and 290 deletions

View File

@@ -0,0 +1,24 @@
<?php
namespace App\Actions\Applications;
use App\Models\Application;
use App\Models\Instance;
use App\Models\Server;
class CreateInstance
{
public function execute(
Application $application,
Server $server,
string $branch = 'main',
array $config = []
): Instance {
return $application->instances()->create([
'server_id' => $server->id,
'branch' => $branch,
'status' => 'pending',
'config' => $config,
]);
}
}

View File

@@ -1,12 +0,0 @@
<?php
namespace App\Data\Slices;
class CaddySliceData
{
public function __construct(
public string $domain,
public string $type,
public array $targets
) {}
}

View File

@@ -2,6 +2,8 @@
namespace App\Http\Controllers;
use App\Enums\ServerStatus;
use App\Models\Application;
use App\Models\Organisation;
use Illuminate\Http\Request;
@@ -9,7 +11,7 @@ class ApplicationController extends Controller
{
public function index(Request $request)
{
$organisation = Organisation::with('applications')->findOrFail($request->route('organisation'));
$organisation = Organisation::with('applications.instances.server')->findOrFail($request->route('organisation'));
return inertia('applications/Index', [
'applications' => $organisation->applications,
@@ -19,7 +21,18 @@ class ApplicationController extends Controller
public function show(Request $request)
{
$id = $request->route('application');
$application = Application::with(['instances.server', 'organisation'])->findOrFail($id);
return inertia('applications/Show');
return inertia('applications/Show', [
'application' => $application,
'servers' => inertia()->optional(function () use ($application) {
return $application
->organisation
?->servers()
->where('status', ServerStatus::ACTIVE)
->with('services')
->get() ?? [];
}),
]);
}
}

View File

@@ -1,29 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Enums\ServerStatus;
use App\Models\Environment;
use Illuminate\Http\Request;
class EnvironmentController extends Controller
{
public function show(Request $request)
{
$id = $request->route('environment');
$environment = Environment::with('application')->findOrFail($id);
return inertia('environments/Show', [
'environment' => $environment,
'servers' => inertia()->optional(function () use ($environment) {
return $environment
->application
?->organisation
?->servers()
->where('status', ServerStatus::ACTIVE)
->with('services')
->get() ?? [];
}),
]);
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace App\Http\Controllers;
use App\Actions\Applications\CreateInstance;
use App\Models\Application;
use App\Models\Server;
use Illuminate\Http\Request;
class InstanceController extends Controller
{
public function store(Request $request, Application $application)
{
$validated = $request->validate([
'server_id' => 'required|exists:servers,id',
'branch' => 'required|string|max:255',
'config' => 'sometimes|array',
]);
$server = Server::findOrFail($validated['server_id']);
$instance = (new CreateInstance())->execute(
$application,
$server,
$validated['branch'],
$validated['config'] ?? []
);
return redirect()
->route('applications.show', [
'organisation' => $application->organisation_id,
'application' => $application->id
])
->with('success', 'Instance created successfully');
}
}

View File

@@ -0,0 +1,59 @@
<?php
namespace App\Jobs\Applications;
use App\Enums\DeploymentStatus;
use App\Models\Application;
use App\Models\Deployment;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
class DeployApplication implements ShouldQueue
{
use Queueable;
protected Deployment $deployment;
public function __construct(
public Application $application,
) {
//
}
public function handle(): void
{
$this->deployment = $this->application->deployments()->create([
'status' => DeploymentStatus::PENDING,
]);
foreach ($this->application->instances as $instance) {
$step = $this->deployment->steps()->create([
'name' => "Deploy to {$instance->server->name}",
'order' => $instance->id,
'status' => DeploymentStatus::PENDING,
'script' => $this->getDeploymentScript($instance),
'secrets' => [],
]);
$step->dispatchJob();
}
}
protected function getDeploymentScript($instance): string
{
return "#!/bin/bash\n" .
"cd /opt/apps/{$this->application->name}-{$instance->id}\n" .
"git fetch origin\n" .
"git checkout {$instance->branch}\n" .
"git pull origin {$instance->branch}\n";
}
public function failed(\Throwable $exception): void
{
if (isset($this->deployment)) {
$this->deployment->update([
'status' => DeploymentStatus::FAILED,
]);
}
}
}

View File

@@ -6,6 +6,8 @@ use App\Enums\RepositoryType;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
use Illuminate\Database\Eloquent\Relations\MorphMany;
class Application extends Model
{
@@ -23,8 +25,18 @@ class Application extends Model
return $this->belongsTo(Organisation::class);
}
public function environments(): HasMany
public function instances(): HasMany
{
return $this->hasMany(Environment::class);
return $this->hasMany(Instance::class);
}
public function servers(): HasManyThrough
{
return $this->hasManyThrough(Server::class, Instance::class);
}
public function deployments(): MorphMany
{
return $this->morphMany(Deployment::class, 'target');
}
}

View File

@@ -1,28 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
class Environment extends Model
{
protected $guarded = [];
public function application(): BelongsTo
{
return $this->belongsTo(Application::class);
}
public function slices(): HasMany
{
return $this->hasMany(Slice::class);
}
public function services(): HasManyThrough
{
return $this->hasManyThrough(Service::class, Slice::class);
}
}

34
app/Models/Instance.php Normal file
View File

@@ -0,0 +1,34 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphMany;
class Instance extends Model
{
protected $guarded = [];
protected function casts(): array
{
return [
'config' => 'array',
];
}
public function application(): BelongsTo
{
return $this->belongsTo(Application::class);
}
public function server(): BelongsTo
{
return $this->belongsTo(Server::class);
}
public function deployments(): MorphMany
{
return $this->morphMany(Deployment::class, 'target');
}
}

View File

@@ -44,6 +44,16 @@ class Server extends Model
return $this->hasMany(Service::class);
}
public function instances(): HasMany
{
return $this->hasMany(Instance::class);
}
public function applications(): HasManyThrough
{
return $this->hasManyThrough(Application::class, Instance::class);
}
public function firewallRules(): HasMany
{
return $this->hasMany(FirewallRule::class);
@@ -64,14 +74,14 @@ class Server extends Model
)->where('target_type', (new Service)->getMorphClass());
}
public function environmentDeployments(): HasManyThrough
public function applicationDeployments(): HasManyThrough
{
return $this->hasManyThrough(
Deployment::class,
Environment::class,
Application::class,
'server_id',
'target_id',
)->where('target_type', (new Environment)->getMorphClass());
)->where('target_type', (new Application)->getMorphClass());
}
public function sshClient(string $user = 'root'): Ssh

View File

@@ -10,7 +10,6 @@ use App\Enums\ServiceType;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphMany;
class Service extends Model
@@ -41,11 +40,6 @@ class Service extends Model
return $this->belongsTo(Server::class);
}
public function slices(): HasMany
{
return $this->hasMany(Slice::class);
}
public function deployments(): MorphMany
{
return $this->morphMany(Deployment::class, 'target');

View File

@@ -1,16 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Slice extends Model
{
protected $guarded = [];
public function service(): BelongsTo
{
return $this->belongsTo(Service::class);
}
}

View File

@@ -4,12 +4,11 @@ namespace App\Providers;
use App\Models\Application;
use App\Models\Deployment;
use App\Models\Environment;
use App\Models\Instance;
use App\Models\Organisation;
use App\Models\OrganisationUser;
use App\Models\Server;
use App\Models\Service;
use App\Models\Slice;
use App\Models\Step;
use App\Models\User;
use Illuminate\Database\Eloquent\Relations\Relation;
@@ -33,12 +32,11 @@ class AppServiceProvider extends ServiceProvider
Relation::enforceMorphMap([
'application' => Application::class,
'deployment' => Deployment::class,
'environment' => Environment::class,
'instance' => Instance::class,
'organisation' => Organisation::class,
'organisation-user' => OrganisationUser::class,
'server' => Server::class,
'service' => Service::class,
'slice' => Slice::class,
'step' => Step::class,
'user' => User::class,
]);