Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/Console/HelloCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int

$user = $this->env->get(['USER', 'USERNAME'], false) ?? 'there';

$this->success('Hello ' . $user . '!');
$this->io->success('Hello ' . $user . '!');

return Command::SUCCESS;
}
Expand Down
58 changes: 29 additions & 29 deletions app/Console/Server/ServerAddCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,17 @@ protected function execute(InputInterface $input, OutputInterface $output): int
{
parent::execute($input, $output);

$this->hr();
$this->io->hr();

$this->h1('Add New Server');
$this->io->h1('Add New Server');

//
// Gather server details

/** @var string|null $name */
$name = $this->getValidatedOptionOrPrompt(
$name = $this->io->getValidatedOptionOrPrompt(
'name',
fn ($validate) => $this->promptText(
fn ($validate) => $this->io->promptText(
label: 'Server name:',
placeholder: 'web1',
required: true,
Expand All @@ -75,9 +75,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int
}

/** @var string|null $host */
$host = $this->getValidatedOptionOrPrompt(
$host = $this->io->getValidatedOptionOrPrompt(
'host',
fn ($validate) => $this->promptText(
fn ($validate) => $this->io->promptText(
label: 'Host/IP address:',
placeholder: '192.168.1.100',
required: true,
Expand All @@ -91,9 +91,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int
}

/** @var string|null $portString */
$portString = $this->getValidatedOptionOrPrompt(
$portString = $this->io->getValidatedOptionOrPrompt(
'port',
fn ($validate) => $this->promptText(
fn ($validate) => $this->io->promptText(
label: 'SSH port:',
default: '22',
required: true,
Expand All @@ -109,19 +109,19 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$port = (int) $portString;

/** @var string $username */
$username = $this->getOptionOrPrompt(
$username = $this->io->getOptionOrPrompt(
'username',
fn (): string => $this->promptText(
fn (): string => $this->io->promptText(
label: 'SSH username:',
default: 'root',
required: true
)
);

/** @var string $privateKeyPathRaw */
$privateKeyPathRaw = $this->getOptionOrPrompt(
$privateKeyPathRaw = $this->io->getOptionOrPrompt(
'private-key-path',
fn (): string => $this->promptText(
fn (): string => $this->io->promptText(
label: 'SSH private key path (leave empty for default ~/.ssh/id_ed25519 or ~/.ssh/id_rsa):',
default: '',
required: false
Expand All @@ -142,25 +142,25 @@ protected function execute(InputInterface $input, OutputInterface $output): int
privateKeyPath: $privateKeyPath
);

$this->hr();
$this->io->hr();

$this->displayServerDeets($server);

//
// Verify connectivity

/** @var bool $skipCheck */
$skipCheck = $this->getOptionOrPrompt(
$skipCheck = $this->io->getOptionOrPrompt(
'skip',
fn (): bool => !$this->promptConfirm(
fn (): bool => !$this->io->promptConfirm(
label: 'Test SSH connection before saving?',
default: true
)
);

if ($skipCheck) {
$this->warning('Skipping SSH connection check');
$this->writeln('');
$this->io->warning('Skipping SSH connection check');
$this->io->writeln('');
} else {
if (!$this->testConnection($server)) {
return Command::FAILURE;
Expand All @@ -171,17 +171,17 @@ protected function execute(InputInterface $input, OutputInterface $output): int
// Confirm creation

/** @var bool $confirmed */
$confirmed = $this->getOptionOrPrompt(
$confirmed = $this->io->getOptionOrPrompt(
'yes',
fn (): bool => $this->promptConfirm(
fn (): bool => $this->io->promptConfirm(
label: 'Save this server to inventory?',
default: true
)
);

if (!$confirmed) {
$this->warning('Cancelled adding server');
$this->writeln('');
$this->io->warning('Cancelled adding server');
$this->io->writeln('');

return Command::SUCCESS;
}
Expand All @@ -192,18 +192,18 @@ protected function execute(InputInterface $input, OutputInterface $output): int
try {
$this->servers->create($server);
} catch (\RuntimeException $e) {
$this->error('Failed to add server: ' . $e->getMessage());
$this->io->error('Failed to add server: ' . $e->getMessage());

return Command::FAILURE;
}

$this->success('Server added successfully');
$this->writeln('');
$this->io->success('Server added successfully');
$this->io->writeln('');

//
// Show command hint

$this->showCommandHint('server:add', [
$this->io->showCommandHint('server:add', [
'name' => $name,
'host' => $host,
'port' => $port,
Expand All @@ -226,7 +226,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
private function testConnection(ServerDTO $server): bool
{
try {
$this->promptSpin(
$this->io->promptSpin(
callback: fn () => $this->ssh->assertCanConnect(
$server->host,
$server->port,
Expand All @@ -236,13 +236,13 @@ private function testConnection(ServerDTO $server): bool
message: 'Connecting to server...'
);

$this->success('SSH connection successful');
$this->io->success('SSH connection successful');

return true;
} catch (\RuntimeException $e) {
$this->error($e->getMessage());
$this->io->error($e->getMessage());

$this->writeln([
$this->io->writeln([
'',
' <fg=yellow>Common issues:</>',
'',
Expand Down
18 changes: 9 additions & 9 deletions app/Console/Server/ServerDeleteCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int
{
parent::execute($input, $output);

$this->hr();
$this->io->hr();

$this->h1('Delete Server');
$this->io->h1('Delete Server');

//
// Select server
Expand All @@ -61,17 +61,17 @@ protected function execute(InputInterface $input, OutputInterface $output): int
// Confirm deletion

/** @var bool $confirmed */
$confirmed = $this->getOptionOrPrompt(
$confirmed = $this->io->getOptionOrPrompt(
'yes',
fn (): bool => $this->promptConfirm(
fn (): bool => $this->io->promptConfirm(
label: 'Are you sure you want to delete this server?',
default: true
)
);

if (!$confirmed) {
$this->warning('Cancelled deleting server');
$this->writeln('');
$this->io->warning('Cancelled deleting server');
$this->io->writeln('');

return Command::SUCCESS;
}
Expand All @@ -81,13 +81,13 @@ protected function execute(InputInterface $input, OutputInterface $output): int

$this->servers->delete($server->name);

$this->success("Server '{$server->name}' deleted successfully");
$this->writeln('');
$this->io->success("Server '{$server->name}' deleted successfully");
$this->io->writeln('');

//
// Show command hint

$this->showCommandHint('server:delete', [
$this->io->showCommandHint('server:delete', [
'server' => $server->name,
'yes' => $confirmed,
]);
Expand Down
8 changes: 4 additions & 4 deletions app/Console/Server/ServerListCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ protected function execute(InputInterface $input, OutputInterface $output): int
{
parent::execute($input, $output);

$this->hr();
$this->io->hr();

//
// Get all servers

$allServers = $this->servers->all();
if (count($allServers) === 0) {
$this->warning('No servers found in inventory');
$this->writeln([
$this->io->warning('No servers found in inventory');
$this->io->writeln([
'',
'Use <fg=cyan>server:add</> to add a server',
'',
Expand All @@ -44,7 +44,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
return Command::SUCCESS;
}

$this->h1('All Servers');
$this->io->h1('All Servers');

foreach ($allServers as $server) {
$this->displayServerDeets($server);
Expand Down
40 changes: 15 additions & 25 deletions app/Contracts/BaseCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,37 +9,27 @@
use Bigpixelrocket\DeployerPHP\Repositories\SiteRepository;
use Bigpixelrocket\DeployerPHP\Services\EnvService;
use Bigpixelrocket\DeployerPHP\Services\InventoryService;
use Bigpixelrocket\DeployerPHP\Services\IOService;
use Bigpixelrocket\DeployerPHP\Services\ProcessService;
use Bigpixelrocket\DeployerPHP\Services\PrompterService;
use Bigpixelrocket\DeployerPHP\Services\SSHService;
use Bigpixelrocket\DeployerPHP\Traits\ConsoleInputTrait;
use Bigpixelrocket\DeployerPHP\Traits\ConsoleOutputTrait;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

/**
* Base command with shared functionality for all commands.
*
* Uses ConsoleInputTrait for input gathering and ConsoleOutputTrait
* for formatted output. All console commands should extend this class.
* Uses IOService for all console input/output operations.
* All console commands should extend this class.
*/
abstract class BaseCommand extends Command
{
use ConsoleInputTrait;
use ConsoleOutputTrait;

protected InputInterface $input;
protected OutputInterface $output;
protected SymfonyStyle $io;

/**
* Create a new BaseCommand with the application's services and repositories.
*
* The constructor accepts and stores dependencies (environment and inventory services,
* process and prompting helpers, server/site repositories, SSH service, and the DI container)
* The constructor accepts and stores dependencies (I/O service, environment and inventory services,
* process service, server/site repositories, SSH service, and the DI container)
* used by this command and its subclasses.
*/
public function __construct(
Expand All @@ -49,8 +39,8 @@ public function __construct(
// Base services
protected readonly EnvService $env,
protected readonly InventoryService $inventory,
protected readonly IOService $io,
protected readonly ProcessService $proc,
protected readonly PrompterService $prompter,

// Servers & sites
protected readonly ServerRepository $servers,
Expand Down Expand Up @@ -89,10 +79,9 @@ protected function configure(): void
/**
* Prepare console IO and initialize environment, inventory, and repositories.
*
* Sets the command's input/output properties, creates a SymfonyStyle IO helper,
* applies any custom paths provided via the `--env` and `--inventory` options,
* loads the corresponding files, and populates the servers and sites repositories
* from the loaded inventory.
* Initializes the I/O service with command context, applies any custom paths provided
* via the `--env` and `--inventory` options, loads the corresponding files, and populates
* the servers and sites repositories from the loaded inventory.
*
* @param InputInterface $input The current console input.
* @param OutputInterface $output The current console output.
Expand All @@ -101,9 +90,10 @@ protected function initialize(InputInterface $input, OutputInterface $output): v
{
parent::initialize($input, $output);

$this->input = $input;
$this->output = $output;
$this->io = new SymfonyStyle($input, $output);
//
// Initialize I/O service

$this->io->initialize($this, $input, $output);

//
// Initialize env service
Expand Down Expand Up @@ -142,14 +132,14 @@ protected function execute(InputInterface $input, OutputInterface $output): int

$envStatus = $this->env->getEnvFileStatus();
$color = str_starts_with($envStatus, 'No .env') ? 'yellow' : 'gray';
$this->writeln([
$this->io->writeln([
' <fg=cyan>Environment:</> ',
" <fg={$color}>{$envStatus}</>",
'',
]);

$inventoryStatus = $this->inventory->getInventoryFileStatus();
$this->writeln([
$this->io->writeln([
' <fg=cyan>Inventory:</> ',
' <fg=gray>'.$inventoryStatus.'</>',
'',
Expand Down
Loading