Files
isaaccladandCursor e251a4cf60
Deploy Ladill Hosting / deploy (push) Failing after 17s
Initial Ladill Hosting app with Gitea deploy pipeline.
Shared web hosting extracted from the platform monolith, with CI deploy
to /var/www/ladill-hosting matching Bird/Domains/Email.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 16:24:20 +00:00

141 lines
4.8 KiB
PHP

<?php
namespace App\Services\Hosting\PanelRuntimes;
use App\Models\CustomerHostingOrder;
use App\Models\ServerAgent;
use App\Models\ServerTask;
use App\Services\Hosting\ServerAgentBootstrapService;
use Illuminate\Support\Str;
use RuntimeException;
class ServerAgentPanelRuntime
{
public function __construct(
private ServerAgentBootstrapService $bootstrap,
) {}
public function label(): string
{
return 'Ladill Hosting Panel';
}
public function supports(CustomerHostingOrder $order): bool
{
return (bool) data_get($order->meta, 'server_panel_runtime.managed_stack_candidate', false);
}
public function ensureAgent(CustomerHostingOrder $order): ServerAgent
{
if (! $this->supports($order)) {
throw new RuntimeException('This server image is not enabled for agent-backed Ladill hosting tasks.');
}
return $this->bootstrap->ensureBootstrap($order)['agent'];
}
public function queueDomainTask(CustomerHostingOrder $order, string $domain, ?string $documentRoot = null, ?string $phpVersion = null): ServerTask
{
return $this->queueTask($order, ServerTask::TYPE_DOMAIN_ADD, array_filter([
'domain' => strtolower($domain),
'document_root' => $documentRoot,
'php_version' => $phpVersion,
], static fn ($value): bool => $value !== null && $value !== ''));
}
public function queueSslTask(CustomerHostingOrder $order, string $domain): ServerTask
{
return $this->queueTask($order, ServerTask::TYPE_SSL_REQUEST, [
'domain' => strtolower($domain),
]);
}
public function queueDatabaseTask(CustomerHostingOrder $order, string $name): ServerTask
{
return $this->queueTask($order, ServerTask::TYPE_DATABASE_CREATE, [
'name' => Str::lower($name),
]);
}
public function queueSiteDeleteTask(CustomerHostingOrder $order, string $domain): ServerTask
{
return $this->queueTask($order, ServerTask::TYPE_SITE_DELETE, [
'domain' => strtolower($domain),
]);
}
public function queuePhpTask(CustomerHostingOrder $order, string $domain, string $phpVersion): ServerTask
{
return $this->queueTask($order, ServerTask::TYPE_PHP_CONFIGURE, [
'domain' => strtolower($domain),
'php_version' => $phpVersion,
]);
}
public function queueCronTask(
CustomerHostingOrder $order,
string $operation,
?string $name = null,
?string $expression = null,
?string $command = null,
?string $user = null,
): ServerTask {
$taskType = match ($operation) {
'list' => ServerTask::TYPE_CRON_LIST,
'upsert' => ServerTask::TYPE_CRON_UPSERT,
'remove' => ServerTask::TYPE_CRON_REMOVE,
default => throw new RuntimeException('Unsupported cron operation.'),
};
return $this->queueTask($order, $taskType, array_filter([
'name' => $name,
'expression' => $expression,
'command' => $command,
'user' => $user,
], static fn ($value): bool => $value !== null && $value !== ''));
}
public function queueLogTask(CustomerHostingOrder $order, string $target, ?string $domain = null, int $lines = 120): ServerTask
{
return $this->queueTask($order, ServerTask::TYPE_LOG_READ, [
'target' => $target,
'domain' => $domain ? strtolower($domain) : null,
'lines' => max(20, min(500, $lines)),
]);
}
public function queueFileTask(CustomerHostingOrder $order, string $operation, string $path, ?string $content = null): ServerTask
{
$taskType = match ($operation) {
'list' => ServerTask::TYPE_FILE_LIST,
'read' => ServerTask::TYPE_FILE_READ,
'write' => ServerTask::TYPE_FILE_WRITE,
default => throw new RuntimeException('Unsupported file operation.'),
};
return $this->queueTask($order, $taskType, array_filter([
'path' => $path,
'content' => $content,
], static fn ($value): bool => $value !== null));
}
private function queueTask(CustomerHostingOrder $order, string $type, array $payload): ServerTask
{
$agent = $this->ensureAgent($order);
return ServerTask::create([
'customer_hosting_order_id' => $order->id,
'server_agent_id' => $agent->id,
'type' => $type,
'status' => ServerTask::STATUS_QUEUED,
'payload' => $payload,
'progress' => 0,
'max_attempts' => 3,
'retry_backoff_seconds' => 60,
'stale_after_seconds' => 120,
'queued_at' => now(),
'available_at' => now(),
]);
}
}