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
110 changes: 40 additions & 70 deletions app/Console/Site/SiteAddCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,8 @@ protected function configure(): void

$this
->addOption('domain', null, InputOption::VALUE_REQUIRED, 'Domain name')
->addOption('source', null, InputOption::VALUE_REQUIRED, 'Site source: git or local')
->addOption('repo', null, InputOption::VALUE_REQUIRED, 'Git repository URL (for git sites)')
->addOption('branch', null, InputOption::VALUE_REQUIRED, 'Git branch name (for git sites)')
->addOption('repo', null, InputOption::VALUE_REQUIRED, 'Git repository URL')
->addOption('branch', null, InputOption::VALUE_REQUIRED, 'Git branch name')
->addOption('server', null, InputOption::VALUE_REQUIRED, 'Server name');
}

Expand All @@ -59,7 +58,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int

[
'domain' => $domain,
'siteSource' => $siteSource,
'repo' => $repo,
'branch' => $branch,
'server' => $server,
Expand Down Expand Up @@ -96,18 +94,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int
// Show command replay
// ----

$hintOptions = [
$this->showCommandReplay('site:add', [
'domain' => $domain,
'source' => $siteSource,
'repo' => $repo,
'branch' => $branch,
'server' => $server->name,
];

if ($siteSource !== 'local') {
$hintOptions['repo'] = $repo;
$hintOptions['branch'] = $branch;
}

$this->showCommandReplay('site:add', $hintOptions);
]);

return Command::SUCCESS;
}
Expand All @@ -119,7 +111,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
/**
* Gather site details from user input or CLI options.
*
* @return array{domain: string, siteSource: string, repo: ?string, branch: ?string, server: ServerDTO}|null
* @return array{domain: string, repo: string, branch: string, server: ServerDTO}|null
*/
protected function gatherSiteDeets(): ?array
{
Expand Down Expand Up @@ -154,71 +146,49 @@ protected function gatherSiteDeets(): ?array
}

//
// Select site source
// Gather git details
// ----

/** @var string $siteSource */
$siteSource = $this->io->getOptionOrPrompt(
'source',
fn (): string => (string) $this->io->promptSelect(
label: 'Deploy from:',
options: ['git' => 'Git Repository', 'local' => 'Local files'],
default: 'git'
)
$defaultRepo = $this->git->detectRemoteUrl() ?? '';

/** @var string|null $repo */
$repo = $this->io->getValidatedOptionOrPrompt(
'repo',
fn ($validate) => $this->io->promptText(
label: 'Git repository URL:',
placeholder: 'git@github.com:user/repo.git',
default: $defaultRepo,
required: true,
validate: $validate
),
fn ($value) => $this->validateSiteRepo($value)
);

$isLocal = $siteSource === 'local';
if ($repo === null) {
return null;
}

//
// Gather git-specific details
// ----
$defaultBranch = $this->git->detectCurrentBranch() ?? 'main';

$repo = null;
$branch = null;

if (!$isLocal) {
$defaultRepo = $this->git->detectRemoteUrl() ?? '';

/** @var string|null $repo */
$repo = $this->io->getValidatedOptionOrPrompt(
'repo',
fn ($validate) => $this->io->promptText(
label: 'Git repository URL:',
placeholder: 'git@github.com:user/repo.git',
default: $defaultRepo,
required: true,
validate: $validate
),
fn ($value) => $this->validateSiteRepo($value)
);

if ($repo === null) {
return null;
}

$defaultBranch = $this->git->detectCurrentBranch() ?? 'main';

/** @var string|null $branch */
$branch = $this->io->getValidatedOptionOrPrompt(
'branch',
fn ($validate) => $this->io->promptText(
label: 'Git branch:',
placeholder: $defaultBranch,
default: $defaultBranch,
required: true,
validate: $validate
),
fn ($value) => $this->validateSiteBranch($value)
);

if ($branch === null) {
return null;
}
/** @var string|null $branch */
$branch = $this->io->getValidatedOptionOrPrompt(
'branch',
fn ($validate) => $this->io->promptText(
label: 'Git branch:',
placeholder: $defaultBranch,
default: $defaultBranch,
required: true,
validate: $validate
),
fn ($value) => $this->validateSiteBranch($value)
);

if ($branch === null) {
return null;
}

return [
'domain' => $domain,
'siteSource' => $siteSource,
'repo' => $repo,
'branch' => $branch,
'server' => $server,
Expand Down
16 changes: 4 additions & 12 deletions app/DTOs/SiteDTO.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,15 @@
* Create a SiteDTO containing the site's domain, repository, branch, and associated servers.
*
* @param string $domain The site's domain name (e.g. example.com).
* @param string|null $repo The repository URL for git sites, null for local sites.
* @param string|null $branch The repository branch for git sites (e.g. main), null for local sites.
* @param string $repo The repository URL for git sites.
* @param string $branch The repository branch for git sites (e.g. main).
* @param array<int, string> $servers Ordered list of server hostnames or addresses associated with the site.
*/
public function __construct(
public string $domain,
public ?string $repo,
public ?string $branch,
public string $repo,
public string $branch,
public array $servers,
) {
}

/**
* Check if this is a local site (no git repository).
*/
public function isLocal(): bool
{
return $this->repo === null;
}
}
24 changes: 9 additions & 15 deletions app/Repositories/SiteRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -167,41 +167,35 @@ private function assertInventoryLoaded(): void
* Serialize a SiteDTO into an associative array suitable for inventory storage.
*
* @param SiteDTO $site The site DTO to serialize.
* @return array<string, mixed> Associative array with keys `domain`, `servers`, and optionally `repo`/`branch` for git sites.
* @return array<string, mixed> Associative array with keys `domain`, `repo`, `branch`, and `servers`.
*/
private function dehydrateSiteDTO(SiteDTO $site): array
{
$data = [
return [
'domain' => $site->domain,
'repo' => $site->repo,
'branch' => $site->branch,
'servers' => $site->servers,
];

// Only include repo/branch for git-based sites
if (!$site->isLocal()) {
$data['repo'] = $site->repo;
$data['branch'] = $site->branch;
}

return $data;
}

/**
* Create a SiteDTO from raw inventory data.
*
* @param array<string,mixed> $data Raw associative array from inventory.
* @return SiteDTO A SiteDTO where `domain` is a string (empty if missing), `repo` and `branch` are nullable strings (null for local sites), and `servers` is an array of strings.
* @return SiteDTO A SiteDTO where `domain`, `repo`, and `branch` are strings (empty if missing), and `servers` is an array of strings.
*/
private function hydrateSiteDTO(array $data): SiteDTO
{
$domain = $data['domain'] ?? '';
$repo = $data['repo'] ?? null;
$branch = $data['branch'] ?? null;
$repo = $data['repo'] ?? '';
$branch = $data['branch'] ?? '';
$servers = $data['servers'] ?? [];

return new SiteDTO(
domain: is_string($domain) ? $domain : '',
repo: is_string($repo) ? $repo : null,
branch: is_string($branch) ? $branch : null,
repo: is_string($repo) ? $repo : '',
branch: is_string($branch) ? $branch : '',
servers: is_array($servers) ? array_values(array_filter($servers, is_string(...))) : [],
);
}
Expand Down
18 changes: 6 additions & 12 deletions app/Traits/SitesTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,18 +110,12 @@ protected function selectSite(?array $sites = null): SiteDTO|int
*/
protected function displaySiteDeets(SiteDTO $site): void
{
$details = ['Domain' => $site->domain];

if ($site->isLocal()) {
$details['Source'] = 'Local';
} else {
$details = [
...$details,
'Source' => 'Git',
'Repo' => $site->repo,
'Branch' => $site->branch,
];
}
$details = [
'Domain' => $site->domain,
'Source' => 'Git',
'Repo' => $site->repo,
'Branch' => $site->branch,
];

if (count($site->servers) > 1) {
$details['Servers'] = $site->servers;
Expand Down