92 lines
3.0 KiB
PHP
92 lines
3.0 KiB
PHP
<?php
|
|
|
|
namespace App\Actions\Environments;
|
|
|
|
use App\Data\Environments\EnvironmentDeploymentPlan;
|
|
use App\Enums\DeployPolicy;
|
|
use App\Enums\EnvironmentAttachmentRole;
|
|
use App\Enums\SchedulerMode;
|
|
use App\Models\Environment;
|
|
|
|
class PlanEnvironmentDeployment
|
|
{
|
|
public function execute(Environment $environment): EnvironmentDeploymentPlan
|
|
{
|
|
$environment->loadMissing([
|
|
'services',
|
|
'attachments.service',
|
|
'attachments.serviceSlice',
|
|
]);
|
|
|
|
$deployableServices = $environment->services
|
|
->where('deploy_policy', DeployPolicy::WITH_ENVIRONMENT)
|
|
->values();
|
|
|
|
$dependencies = $environment->attachments
|
|
->map(fn ($attachment) => $attachment->service)
|
|
->filter()
|
|
->unique('id')
|
|
->values();
|
|
|
|
$targetServerCount = $deployableServices
|
|
->flatMap(fn ($service) => $service->replicas->pluck('server_id')->filter())
|
|
->unique()
|
|
->count();
|
|
|
|
if ($targetServerCount === 0) {
|
|
$targetServerCount = $deployableServices->sum('desired_replicas') > 1 ? 2 : 1;
|
|
}
|
|
|
|
return new EnvironmentDeploymentPlan(
|
|
services: $deployableServices->all(),
|
|
dependencies: $dependencies->all(),
|
|
requiresRegistry: $targetServerCount > 1 && $environment->application->organisation->registries()->doesntExist(),
|
|
warnings: $this->warnings($environment),
|
|
blockers: $this->blockers($environment),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @return array<int, string>
|
|
*/
|
|
private function warnings(Environment $environment): array
|
|
{
|
|
$warnings = [];
|
|
|
|
if ($environment->variables()
|
|
->where('key', 'QUEUE_CONNECTION')
|
|
->get()
|
|
->contains(fn ($variable) => $variable->value === 'sync')) {
|
|
$warnings[] = 'QUEUE_CONNECTION=sync is not recommended for deployed Laravel environments.';
|
|
}
|
|
|
|
if ($environment->attachments->contains('role', EnvironmentAttachmentRole::QUEUE)) {
|
|
$hasWorker = $environment->services->contains(fn ($service) => in_array('worker', $service->process_roles ?? [], true));
|
|
|
|
if (! $hasWorker) {
|
|
$warnings[] = 'Queue attachment exists without a dedicated worker service.';
|
|
}
|
|
}
|
|
|
|
return $warnings;
|
|
}
|
|
|
|
/**
|
|
* @return array<int, string>
|
|
*/
|
|
private function blockers(Environment $environment): array
|
|
{
|
|
if (! $environment->scheduler_enabled || $environment->scheduler_mode !== SchedulerMode::SINGLE) {
|
|
return [];
|
|
}
|
|
|
|
$target = $environment->services->firstWhere('id', $environment->scheduler_target_service_id);
|
|
|
|
if ($target && $target->desired_replicas > 1 && in_array('scheduler', $target->process_roles ?? [], true)) {
|
|
return ['Scheduler mode single requires the scheduler target service to run exactly one replica.'];
|
|
}
|
|
|
|
return [];
|
|
}
|
|
}
|