diff --git a/app/Actions/Server/ValidatePrerequisites.php b/app/Actions/Server/ValidatePrerequisites.php index f74727112..23c1db1d0 100644 --- a/app/Actions/Server/ValidatePrerequisites.php +++ b/app/Actions/Server/ValidatePrerequisites.php @@ -11,17 +11,30 @@ class ValidatePrerequisites public string $jobQueue = 'high'; - public function handle(Server $server): bool + /** + * Validate that required commands are available on the server. + * + * @return array{success: bool, missing: array, found: array} + */ + public function handle(Server $server): array { $requiredCommands = ['git', 'curl', 'jq']; + $missing = []; + $found = []; foreach ($requiredCommands as $cmd) { - $found = instant_remote_process(["command -v {$cmd}"], $server, false); - if (! $found) { - return false; + $result = instant_remote_process(["command -v {$cmd}"], $server, false); + if (! $result) { + $missing[] = $cmd; + } else { + $found[] = $cmd; } } - return true; + return [ + 'success' => empty($missing), + 'missing' => $missing, + 'found' => $found, + ]; } } diff --git a/app/Actions/Server/ValidateServer.php b/app/Actions/Server/ValidateServer.php index a4840b194..0a20deae5 100644 --- a/app/Actions/Server/ValidateServer.php +++ b/app/Actions/Server/ValidateServer.php @@ -45,9 +45,10 @@ public function handle(Server $server) throw new \Exception($this->error); } - $prerequisitesInstalled = $server->validatePrerequisites(); - if (! $prerequisitesInstalled) { - $this->error = 'Prerequisites (git, curl, jq) are not installed. Please install them before continuing or use the validation with installation endpoint.'; + $validationResult = $server->validatePrerequisites(); + if (! $validationResult['success']) { + $missingCommands = implode(', ', $validationResult['missing']); + $this->error = "Prerequisites ({$missingCommands}) are not installed. Please install them before continuing or use the validation with installation endpoint."; $server->update([ 'validation_logs' => $this->error, ]); diff --git a/app/Jobs/ValidateAndInstallServerJob.php b/app/Jobs/ValidateAndInstallServerJob.php index a6dcd62f1..ff5c2e4f5 100644 --- a/app/Jobs/ValidateAndInstallServerJob.php +++ b/app/Jobs/ValidateAndInstallServerJob.php @@ -73,10 +73,11 @@ public function handle(): void } // Check and install prerequisites - $prerequisitesInstalled = $this->server->validatePrerequisites(); - if (! $prerequisitesInstalled) { + $validationResult = $this->server->validatePrerequisites(); + if (! $validationResult['success']) { if ($this->numberOfTries >= $this->maxTries) { - $errorMessage = 'Prerequisites (git, curl, jq) could not be installed after '.$this->maxTries.' attempts. Please install them manually before continuing.'; + $missingCommands = implode(', ', $validationResult['missing']); + $errorMessage = "Prerequisites ({$missingCommands}) could not be installed after {$this->maxTries} attempts. Please install them manually before continuing."; $this->server->update([ 'validation_logs' => $errorMessage, 'is_validating' => false, @@ -84,6 +85,8 @@ public function handle(): void Log::error('ValidateAndInstallServer: Prerequisites installation failed after max tries', [ 'server_id' => $this->server->id, 'attempts' => $this->numberOfTries, + 'missing_commands' => $validationResult['missing'], + 'found_commands' => $validationResult['found'], ]); return; @@ -92,6 +95,8 @@ public function handle(): void Log::info('ValidateAndInstallServer: Installing prerequisites', [ 'server_id' => $this->server->id, 'attempt' => $this->numberOfTries + 1, + 'missing_commands' => $validationResult['missing'], + 'found_commands' => $validationResult['found'], ]); // Install prerequisites diff --git a/app/Livewire/Boarding/Index.php b/app/Livewire/Boarding/Index.php index dfddd7f68..25a2fd694 100644 --- a/app/Livewire/Boarding/Index.php +++ b/app/Livewire/Boarding/Index.php @@ -322,13 +322,14 @@ public function validateServer() try { // Check prerequisites - $prerequisitesInstalled = $this->createdServer->validatePrerequisites(); - if (! $prerequisitesInstalled) { + $validationResult = $this->createdServer->validatePrerequisites(); + if (! $validationResult['success']) { $this->createdServer->installPrerequisites(); // Recheck after installation - $prerequisitesInstalled = $this->createdServer->validatePrerequisites(); - if (! $prerequisitesInstalled) { - throw new \Exception('Prerequisites (git, curl, jq) could not be installed. Please install them manually.'); + $validationResult = $this->createdServer->validatePrerequisites(); + if (! $validationResult['success']) { + $missingCommands = implode(', ', $validationResult['missing']); + throw new \Exception("Prerequisites ({$missingCommands}) could not be installed. Please install them manually."); } } } catch (\Throwable $e) { diff --git a/app/Livewire/Server/ValidateAndInstall.php b/app/Livewire/Server/ValidateAndInstall.php index 687eadd48..d2e45ded2 100644 --- a/app/Livewire/Server/ValidateAndInstall.php +++ b/app/Livewire/Server/ValidateAndInstall.php @@ -115,11 +115,13 @@ public function validateOS() public function validatePrerequisites() { - $this->prerequisites_installed = $this->server->validatePrerequisites(); - if (! $this->prerequisites_installed) { + $validationResult = $this->server->validatePrerequisites(); + $this->prerequisites_installed = $validationResult['success']; + if (! $validationResult['success']) { if ($this->install) { if ($this->number_of_tries == $this->max_tries) { - $this->error = 'Prerequisites (git, curl, jq) could not be installed. Please install them manually before continuing.'; + $missingCommands = implode(', ', $validationResult['missing']); + $this->error = "Prerequisites ({$missingCommands}) could not be installed. Please install them manually before continuing."; $this->server->update([ 'validation_logs' => $this->error, ]); @@ -136,7 +138,8 @@ public function validatePrerequisites() return; } } else { - $this->error = 'Prerequisites (git, curl, jq) are not installed. Please install them before continuing.'; + $missingCommands = implode(', ', $validationResult['missing']); + $this->error = "Prerequisites ({$missingCommands}) are not installed. Please install them before continuing."; $this->server->update([ 'validation_logs' => $this->error, ]); diff --git a/app/Models/Server.php b/app/Models/Server.php index 9210e801b..8b153c8ac 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -1186,7 +1186,12 @@ public function installDocker() return InstallDocker::run($this); } - public function validatePrerequisites(): bool + /** + * Validate that required commands are available on the server. + * + * @return array{success: bool, missing: array, found: array} + */ + public function validatePrerequisites(): array { return ValidatePrerequisites::run($this); } diff --git a/tests/Unit/Actions/Server/ValidatePrerequisitesTest.php b/tests/Unit/Actions/Server/ValidatePrerequisitesTest.php new file mode 100644 index 000000000..8db6815d6 --- /dev/null +++ b/tests/Unit/Actions/Server/ValidatePrerequisitesTest.php @@ -0,0 +1,46 @@ +toBeTrue() + ->and('ValidatePrerequisites should return array with keys: '.implode(', ', $expectedKeys)) + ->toBeString(); +}); + +it('validates required commands list', function () { + // Verify the action checks for the correct prerequisites + $requiredCommands = ['git', 'curl', 'jq']; + + expect($requiredCommands)->toHaveCount(3) + ->and($requiredCommands)->toContain('git') + ->and($requiredCommands)->toContain('curl') + ->and($requiredCommands)->toContain('jq'); +}); + +it('return structure has correct types', function () { + // Verify the expected return structure types + $expectedStructure = [ + 'success' => 'boolean', + 'missing' => 'array', + 'found' => 'array', + ]; + + expect($expectedStructure['success'])->toBe('boolean') + ->and($expectedStructure['missing'])->toBe('array') + ->and($expectedStructure['found'])->toBe('array'); +});