Skip to content

refactor: site and server CRUD improvements - #60

Merged
loadinglucian merged 3 commits into
mainfrom
refactor/site-server-crud
Nov 1, 2025
Merged

refactor: site and server CRUD improvements#60
loadinglucian merged 3 commits into
mainfrom
refactor/site-server-crud

Conversation

@loadinglucian

@loadinglucian loadinglucian commented Oct 31, 2025

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Added --force flag to skip domain-typing safety during site deletion
    • Interactive domain-typing confirmation for site deletion (cancels on mismatch)
  • Improvements

    • Site creation: renamed options typesource, serversserver and switched to single-server selection
    • Unified, aligned detail display for sites/servers and minor CLI formatting enhancements (headers, separators, spacing)
    • Safer empty-list handling for site listing
  • Refactor

    • Helper APIs reorganized and docblocks clarified for command helpers and IO rendering

@coderabbitai

coderabbitai Bot commented Oct 31, 2025

Copy link
Copy Markdown
Contributor

Caution

Review failed

The pull request is closed.

Walkthrough

Centralizes formatted detail output in IOService and updates helpers/commands: SiteAdd now selects a single server, SiteDelete adds a typed-domain confirmation with a --force flag, SiteList uses ensureSitesAvailable and prints separators, and server/site detail renderers now call IOService::displayDeets; minor formatting added to ServerDelete output.

Changes

Cohort / File(s) Summary
Server Commands
app/Console/Server/ServerDeleteCommand.php
Adds an extra blank line after displaying server details (formatting only).
Site Add
app/Console/Site/SiteAddCommand.php
Adds use ServerHelpersTrait; renames CLI options typesource and serversserver; replaces multi-server flow with single selectServer() and passes servers: [$server->name] into SiteDTO; updates source prompts/hints.
Site Delete
app/Console/Site/SiteDeleteCommand.php
Adds --force option to skip typed-domain confirmation; changes confirmation prompt to “Are you absolutely sure?” (default false); requires typed domain unless forced; returns appropriate exit codes on mismatch/cancel and reflects force in hints.
Site List
app/Console/Site/SiteListCommand.php
Updates command description; outputs header h1('List Sites'); uses ensureSitesAvailable() to obtain sites or propagate return code; enumerates sites with separators between entries.
Services
app/Services/IOService.php
Adds public function displayDeets(array $details): void to render aligned key/value details, supporting scalar and array values and early-return on empty input.
Server Helpers Trait
app/Traits/ServerHelpersTrait.php
Refactors displayServerDeets() to build a details map and call IOService::displayDeets; adds SiteDTO import; minor spacing change in selectServer().
Site Helpers Trait
app/Traits/SiteHelpersTrait.php
Adds `ensureSitesAvailable(): array
Site Validation Trait
app/Traits/SiteValidationTrait.php
Adds imports for ProcessService, ServerRepository, SiteRepository and updates trait docblock with @property annotations (no logic changes).

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant SiteAddCmd as SiteAddCommand
    participant ServerHelpers as ServerHelpersTrait
    participant IO as IOService

    User->>SiteAddCmd: run site:add
    SiteAddCmd->>ServerHelpers: selectServer()
    ServerHelpers-->>SiteAddCmd: ServerDTO
    SiteAddCmd->>IO: prompt for source & inputs
    SiteAddCmd->>SiteAddCmd: build SiteDTO (servers: [server.name])
    SiteAddCmd->>IO: displayDeets(site details)
    IO-->>User: show aligned key/value details
Loading
sequenceDiagram
    participant User
    participant SiteDelCmd as SiteDeleteCommand
    participant SiteHelpers as SiteHelpersTrait
    participant IO as IOService

    User->>SiteDelCmd: run site:delete
    SiteDelCmd->>SiteHelpers: selectSite()
    SiteHelpers-->>SiteDelCmd: SiteDTO or int(code)

    alt returned int (error/early)
        SiteDelCmd-->>User: exit with code
    else SiteDTO
        alt --force present
            SiteDelCmd->>IO: delete and displayDeets(result)
            IO-->>User: show result
        else no --force
            SiteDelCmd->>IO: prompt "Are you absolutely sure? Type domain:"
            User-->>IO: typed domain
            alt typed == domain
                SiteDelCmd->>IO: delete and displayDeets(result)
                IO-->>User: show result
            else mismatch
                IO-->>User: warning; SiteDelCmd-->>User: exit (no deletion)
            end
        end
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Pay attention to:
    • Call sites affected by SiteHelpersTrait::selectSite() return-type change and removal of selectServers().
    • Correct handling of int return codes from ensureSitesAvailable()/selectSite() in callers.
    • IOService::displayDeets formatting edge cases (empty arrays, nested arrays, long keys).
    • SiteDelete typed-confirm logic and exit code propagation.

Possibly related PRs

  • bigpixelrocket/deployer-php#60 — overlaps in IOService::displayDeets and refactors to Site/Server helper display logic; likely direct overlap.
  • bigpixelrocket/deployer-php#25 — changes to ServerRepository/ServerDTO that align with trait/command integrations introduced here.
  • bigpixelrocket/deployer-php#46 — refactors site/server commands and helper traits, overlapping SiteAdd/SiteList/SiteDelete changes.

Poem

🐇 I hop through traits and tidy deets,
I pick one server where crowding meets,
"Type your domain!" — a careful beat,
Aligned outputs, neat retreat.
Thump-thump, the rabbit signs off sweet.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The pull request title "refactor: site and server CRUD improvements" directly aligns with the changeset. The PR contains significant refactoring across multiple site-related commands (SiteAddCommand, SiteDeleteCommand, SiteListCommand) and server-related code (ServerDeleteCommand, ServerHelpersTrait), along with improvements to underlying traits and services that support these CRUD operations. The title is specific and descriptive—it clearly identifies the domain (site and server operations) and the nature of the changes (CRUD improvements through refactoring) without being vague or overly broad. It appropriately reflects the primary focus areas without requiring enumeration of every file modified.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c998fb0 and 595bff4.

📒 Files selected for processing (1)
  • app/Services/IOService.php (1 hunks)

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (2)
app/Console/Site/SiteDeleteCommand.php (2)

53-55: Import SiteDTO instead of using the inline FQCN

Per the PHP guidelines for this repo, classes should be pulled in via use statements (only core exceptions stay fully qualified). Please add use Bigpixelrocket\DeployerPHP\DTOs\SiteDTO; at the top and use SiteDTO here.

As per coding guidelines


65-80: Route --force through getOptionOrPrompt

Retrieved command rules ask us to pair every option with getOptionOrPrompt so interactive sessions can supply values when the flag isn’t given up front. Please wrap the force flag in that helper (with an appropriate confirm prompt) instead of calling $input->getOption() directly.

Based on learnings

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f991a56 and 97b52bd.

📒 Files selected for processing (8)
  • app/Console/Server/ServerDeleteCommand.php (1 hunks)
  • app/Console/Site/SiteAddCommand.php (7 hunks)
  • app/Console/Site/SiteDeleteCommand.php (3 hunks)
  • app/Console/Site/SiteListCommand.php (2 hunks)
  • app/Services/IOService.php (1 hunks)
  • app/Traits/ServerHelpersTrait.php (3 hunks)
  • app/Traits/SiteHelpersTrait.php (3 hunks)
  • app/Traits/SiteValidationTrait.php (1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.php

📄 CodeRabbit inference engine (.cursor/rules/00-main.mdc)

**/*.php: Eliminate single-use methods: inline if a method is called only once
Cache computed values: initialize expensive calculations in the constructor
Avoid method call overhead: prefer direct property access when appropriate

**/*.php: Adhere to PSR-12, enable strict_types, and leverage PHP 8.x features (union types, match, attributes, readonly)
Use explicit return types, including generic-like annotations where applicable (e.g., Collection<int, User>)
Prefer Symfony components (e.g., Filesystem, Process) over native PHP functions for testability
Always import classes via use statements; only use root FQDNs for core exceptions (e.g., \InvalidArgumentException, \RuntimeException). Do not use inline FQDNs for non-root namespaces
Create objects via $container->build(ClassName::class) everywhere except DTOs, value objects, and pure data structures
Use minimalist DocBlocks documenting description, parameters, and return types for classes and functions
Follow the specified comment structure with section headers/subheaders and spacing; remove obsolete comments with removed code

Files:

  • app/Services/IOService.php
  • app/Console/Server/ServerDeleteCommand.php
  • app/Console/Site/SiteListCommand.php
  • app/Console/Site/SiteDeleteCommand.php
  • app/Traits/SiteHelpersTrait.php
  • app/Traits/SiteValidationTrait.php
  • app/Traits/ServerHelpersTrait.php
  • app/Console/Site/SiteAddCommand.php
**/*Service.php

📄 CodeRabbit inference engine (.cursor/rules/01-architecture.mdc)

**/*Service.php: Services must perform no console I/O and should accept/return plain PHP types
Services are dependency-injected via constructor and encapsulate business logic, external APIs, and file operations
Stateful services should use lazy loading and explicit initialization methods (e.g., load(), initialize()) and document requirements

Files:

  • app/Services/IOService.php
**/*{Command,Service}.php

📄 CodeRabbit inference engine (.cursor/rules/01-architecture.mdc)

All dependencies should be expressed in constructor signatures; avoid circular dependencies

Files:

  • app/Services/IOService.php
  • app/Console/Server/ServerDeleteCommand.php
  • app/Console/Site/SiteListCommand.php
  • app/Console/Site/SiteDeleteCommand.php
  • app/Console/Site/SiteAddCommand.php
**/*Command.php

📄 CodeRabbit inference engine (.cursor/rules/01-architecture.mdc)

**/*Command.php: Commands handle user interaction (I/O), orchestration, styling, error formatting, and prompts using SymfonyStyle
Commands must not contain business logic; delegate to Services
Commands must not invoke other commands (no proxy commands)

Files:

  • app/Console/Server/ServerDeleteCommand.php
  • app/Console/Site/SiteListCommand.php
  • app/Console/Site/SiteDeleteCommand.php
  • app/Console/Site/SiteAddCommand.php
**/*ValidationTrait.php

📄 CodeRabbit inference engine (.cursor/rules/03-commands.mdc)

**/*ValidationTrait.php: Validation methods for prompts/options must accept mixed and return ?string error or null (do not throw exceptions).
Naming: use validateInput() for prompt/option validators returning ?string; use validate() to throw exceptions for heavy I/O validations.

Files:

  • app/Traits/SiteValidationTrait.php
🧠 Learnings (10)
📓 Common learnings
Learnt from: CR
Repo: bigpixelrocket/deployer-php PR: 0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-24T20:01:06.209Z
Learning: Applies to src/Command/**/*Command.php : Option naming: --server/--site select existing resources; --name defines a new resource property; follow the provided table for common options.
📚 Learning: 2025-09-22T11:10:21.459Z
Learnt from: CR
Repo: deployer-plus/deployer-php PR: 0
File: .cursor/rules/01-architecture.mdc:0-0
Timestamp: 2025-09-22T11:10:21.459Z
Learning: Applies to app/**/Command/**/*.php : Use SymfonyStyle consistently for all user-facing console output

Applied to files:

  • app/Console/Server/ServerDeleteCommand.php
📚 Learning: 2025-10-24T20:01:06.209Z
Learnt from: CR
Repo: bigpixelrocket/deployer-php PR: 0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-24T20:01:06.209Z
Learning: Applies to src/Command/**/*Command.php : Option naming: --server/--site select existing resources; --name defines a new resource property; follow the provided table for common options.

Applied to files:

  • app/Console/Site/SiteListCommand.php
  • app/Console/Site/SiteDeleteCommand.php
  • app/Traits/SiteHelpersTrait.php
  • app/Traits/ServerHelpersTrait.php
  • app/Console/Site/SiteAddCommand.php
📚 Learning: 2025-10-24T20:01:06.209Z
Learnt from: CR
Repo: bigpixelrocket/deployer-php PR: 0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-24T20:01:06.209Z
Learning: Applies to src/Command/**/*Command.php : Use only OPTIONS (no positional arguments) to enable getOptionOrPrompt across the board.

Applied to files:

  • app/Console/Site/SiteDeleteCommand.php
📚 Learning: 2025-10-24T20:01:06.209Z
Learnt from: CR
Repo: bigpixelrocket/deployer-php PR: 0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-24T20:01:06.209Z
Learning: Applies to src/Command/**/*Command.php : Pair all options with getOptionOrPrompt to support both non-interactive and interactive usage.

Applied to files:

  • app/Console/Site/SiteDeleteCommand.php
📚 Learning: 2025-10-24T20:01:06.210Z
Learnt from: CR
Repo: bigpixelrocket/deployer-php PR: 0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-24T20:01:06.210Z
Learning: Applies to src/Command/**/*Command.php : Boolean flags must use VALUE_NONE; data inputs must use VALUE_REQUIRED; only --yes has a short flag (-y).

Applied to files:

  • app/Console/Site/SiteDeleteCommand.php
📚 Learning: 2025-10-24T20:01:06.209Z
Learnt from: CR
Repo: bigpixelrocket/deployer-php PR: 0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-24T20:01:06.209Z
Learning: Applies to src/Command/**/*Command.php : Use getValidatedOptionOrPrompt to validate both CLI options and interactive prompts; return Command::FAILURE when validation returns null.

Applied to files:

  • app/Traits/SiteHelpersTrait.php
📚 Learning: 2025-09-22T11:10:21.459Z
Learnt from: CR
Repo: deployer-plus/deployer-php PR: 0
File: .cursor/rules/01-architecture.mdc:0-0
Timestamp: 2025-09-22T11:10:21.459Z
Learning: Applies to app/**/Command/**/*.php : Commands must not duplicate orchestration logic—extract to shared Services

Applied to files:

  • app/Traits/ServerHelpersTrait.php
📚 Learning: 2025-09-22T11:10:21.459Z
Learnt from: CR
Repo: deployer-plus/deployer-php PR: 0
File: .cursor/rules/01-architecture.mdc:0-0
Timestamp: 2025-09-22T11:10:21.459Z
Learning: Applies to app/**/Command/**/*.php : Commands receive Services via constructor injection

Applied to files:

  • app/Traits/ServerHelpersTrait.php
📚 Learning: 2025-10-24T20:01:06.209Z
Learnt from: CR
Repo: bigpixelrocket/deployer-php PR: 0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-24T20:01:06.209Z
Learning: Applies to **/BaseCommand.php : BaseCommand handles shared initialization/configuration/orchestration only; do not implement individual I/O operations here.

Applied to files:

  • app/Console/Site/SiteAddCommand.php
🧬 Code graph analysis (8)
app/Services/IOService.php (1)
app/Traits/KeyHelpersTrait.php (1)
  • displayKeyInfo (28-36)
app/Console/Server/ServerDeleteCommand.php (1)
app/Services/IOService.php (1)
  • writeln (463-469)
app/Console/Site/SiteListCommand.php (2)
app/Services/IOService.php (2)
  • h1 (506-512)
  • writeln (463-469)
app/Traits/SiteHelpersTrait.php (2)
  • ensureSitesAvailable (29-47)
  • displaySiteDeets (95-118)
app/Console/Site/SiteDeleteCommand.php (3)
app/Traits/SiteHelpersTrait.php (2)
  • selectSite (54-90)
  • displaySiteDeets (95-118)
app/DTOs/SiteDTO.php (1)
  • SiteDTO (7-32)
app/Services/IOService.php (6)
  • hr (517-523)
  • writeln (463-469)
  • promptText (200-218)
  • error (498-501)
  • getOptionOrPrompt (84-132)
  • promptConfirm (260-276)
app/Traits/SiteHelpersTrait.php (4)
app/Repositories/ServerRepository.php (1)
  • all (104-114)
app/Repositories/SiteRepository.php (1)
  • all (93-103)
app/DTOs/SiteDTO.php (2)
  • SiteDTO (7-32)
  • isLocal (28-31)
app/Services/IOService.php (2)
  • displayDeets (543-566)
  • writeln (463-469)
app/Traits/SiteValidationTrait.php (3)
app/Repositories/ServerRepository.php (1)
  • ServerRepository (15-195)
app/Repositories/SiteRepository.php (1)
  • SiteRepository (15-208)
app/Services/ProcessService.php (1)
  • ProcessService (12-49)
app/Traits/ServerHelpersTrait.php (2)
app/DTOs/SiteDTO.php (1)
  • SiteDTO (7-32)
app/Services/IOService.php (1)
  • displayDeets (543-566)
app/Console/Site/SiteAddCommand.php (3)
app/Traits/ServerHelpersTrait.php (1)
  • selectServer (54-90)
app/Services/IOService.php (3)
  • writeln (463-469)
  • getOptionOrPrompt (84-132)
  • promptSelect (304-322)
app/DTOs/SiteDTO.php (1)
  • isLocal (28-31)
🪛 GitHub Actions: Rector
app/Services/IOService.php

[error] 547-547: Rector dry-run would have changed the file: The diff shows a change to the max call for alignment using FunctionFirstClassCallableRector. Command 'vendor/bin/rector --dry-run' reported changes would be made (1 file would be changed) and exited with code 2.

🔇 Additional comments (3)
app/Console/Server/ServerDeleteCommand.php (1)

65-65: Approve formatting improvement for better output separation.

Adding the blank line after server details improves readability by providing visual separation between the display section and subsequent messages. This aligns with the PR's consolidation of output formatting and follows the established spacing pattern in the command.

This change is consistent with the learnings about using SymfonyStyle consistently for user-facing console output, and fits the broader PR objective of "consolidating output formatting into IOService."

app/Traits/SiteValidationTrait.php (2)

7-10: LGTM: Clear dependency documentation through imports.

The explicit imports improve IDE support and static analysis by making the trait's dependencies on ServerRepository, SiteRepository, and ProcessService discoverable. These align with the actual property access throughout the trait methods.


14-18: LGTM: Proper trait dependency documentation.

The @Property annotations follow PHP best practices for documenting trait dependencies and enable IDE autocomplete and static analysis. The property names ($proc, $servers, $sites) are consistent with their usage throughout the trait methods, making the contract between trait and consuming classes explicit.

Comment thread app/Console/Site/SiteAddCommand.php
Comment thread app/Console/Site/SiteAddCommand.php
Comment thread app/Console/Site/SiteDeleteCommand.php
Comment thread app/Services/IOService.php
@loadinglucian
loadinglucian merged commit 5c612de into main Nov 1, 2025
4 checks passed
@loadinglucian
loadinglucian deleted the refactor/site-server-crud branch November 1, 2025 09:25

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
app/Console/Site/SiteAddCommand.php (1)

40-40: Add legacy option aliases for backward compatibility.

The option renames (--type→--source, --servers→--server) will break existing scripts and documentation. Add deprecated aliases to maintain compatibility while using new internal names.

Also applies to: 43-43

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 97b52bd and c998fb0.

📒 Files selected for processing (1)
  • app/Console/Site/SiteAddCommand.php (7 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.php

📄 CodeRabbit inference engine (.cursor/rules/00-main.mdc)

**/*.php: Eliminate single-use methods: inline if a method is called only once
Cache computed values: initialize expensive calculations in the constructor
Avoid method call overhead: prefer direct property access when appropriate

**/*.php: Adhere to PSR-12, enable strict_types, and leverage PHP 8.x features (union types, match, attributes, readonly)
Use explicit return types, including generic-like annotations where applicable (e.g., Collection<int, User>)
Prefer Symfony components (e.g., Filesystem, Process) over native PHP functions for testability
Always import classes via use statements; only use root FQDNs for core exceptions (e.g., \InvalidArgumentException, \RuntimeException). Do not use inline FQDNs for non-root namespaces
Create objects via $container->build(ClassName::class) everywhere except DTOs, value objects, and pure data structures
Use minimalist DocBlocks documenting description, parameters, and return types for classes and functions
Follow the specified comment structure with section headers/subheaders and spacing; remove obsolete comments with removed code

Files:

  • app/Console/Site/SiteAddCommand.php
**/*Command.php

📄 CodeRabbit inference engine (.cursor/rules/01-architecture.mdc)

**/*Command.php: Commands handle user interaction (I/O), orchestration, styling, error formatting, and prompts using SymfonyStyle
Commands must not contain business logic; delegate to Services
Commands must not invoke other commands (no proxy commands)

Files:

  • app/Console/Site/SiteAddCommand.php
**/*{Command,Service}.php

📄 CodeRabbit inference engine (.cursor/rules/01-architecture.mdc)

All dependencies should be expressed in constructor signatures; avoid circular dependencies

Files:

  • app/Console/Site/SiteAddCommand.php
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
Repo: bigpixelrocket/deployer-php PR: 0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-24T20:01:06.242Z
Learning: Applies to src/Command/**/*Command.php : Option naming: --server/--site select existing resources; --name defines a new resource property; follow the provided table for common options.
📚 Learning: 2025-10-24T20:01:06.242Z
Learnt from: CR
Repo: bigpixelrocket/deployer-php PR: 0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-24T20:01:06.242Z
Learning: Applies to src/Command/**/*Command.php : Option naming: --server/--site select existing resources; --name defines a new resource property; follow the provided table for common options.

Applied to files:

  • app/Console/Site/SiteAddCommand.php
📚 Learning: 2025-10-24T20:01:06.242Z
Learnt from: CR
Repo: bigpixelrocket/deployer-php PR: 0
File: .cursor/rules/03-commands.mdc:0-0
Timestamp: 2025-10-24T20:01:06.242Z
Learning: Applies to **/BaseCommand.php : BaseCommand handles shared initialization/configuration/orchestration only; do not implement individual I/O operations here.

Applied to files:

  • app/Console/Site/SiteAddCommand.php
🔇 Additional comments (3)
app/Console/Site/SiteAddCommand.php (3)

86-98: Clear naming improvement for site source selection.

The rename from siteType to siteSource improves clarity, and the prompt label "Deploy from:" is more intuitive than the previous approach.


177-186: Command hint correctly reflects updated options.

The hint options are properly updated to use the new option names (source, server) and correctly pass the single server name, maintaining consistency with the command's new interface.


9-9: ServerHelpersTrait respects dependency injection—no action needed.

The trait accesses $this->servers and $this->io, both of which are properly injected in BaseCommand's constructor as protected readonly properties (lines 47 and 51). SiteAddCommand extends BaseCommand and inherits these dependencies, so all required dependencies are explicitly expressed in the constructor signature via the parent class. No hidden dependencies or circular references exist.

Comment on lines +60 to 64
$server = $this->selectServer();

if (is_int($server)) {
return $server;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify selectServer() return values for proper error handling.

The current code correctly propagates the integer status from selectServer(). However, ensure that selectServer() returns Command::FAILURE (not Command::SUCCESS) when no servers are available, so the command doesn't exit successfully without adding a site.


🏁 Script executed:

#!/bin/bash
# Check selectServer() implementation to verify return values
ast-grep --pattern $'function selectServer($$$) {
  $$$
}'

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Find ServerHelpersTrait file
fd -t f "ServerHelpersTrait" --type f

Length of output: 33


🏁 Script executed:

#!/bin/bash
# Search for selectServer function definition
rg -n "function selectServer" --type php -A 20

Length of output: 1437


🏁 Script executed:

#!/bin/bash
# Also search for selectServer calls to understand usage
rg -n "selectServer" --type php -B 2 -A 2

Length of output: 1092


🏁 Script executed:

#!/bin/bash
# Find ensureServersAvailable() implementation
rg -n "function ensureServersAvailable" --type php -A 15

Length of output: 1157


🏁 Script executed:

#!/bin/bash
# Look for any warnings or messages about "no servers" or "must add"
rg -n "must add\|no servers" --type php -i -B 2 -A 2

Length of output: 0


Fix ensureServersAvailable() to return Command::FAILURE when no servers exist.

The verification confirms a critical issue: ensureServersAvailable() in app/Traits/ServerHelpersTrait.php:43 returns Command::SUCCESS when no servers are available. This causes the command to exit with status 0 (success) despite failing to add a site. The method should return Command::FAILURE instead. Update line 43 from return Command::SUCCESS; to return Command::FAILURE; and correct the docblock on line 52.

🤖 Prompt for AI Agents
In app/Traits/ServerHelpersTrait.php around line 43 (and docblock at line 52),
change the early return when no servers are available from Command::SUCCESS to
Command::FAILURE so the calling command exits with a failure status; also update
the docblock on line 52 to reflect that the method returns int
(Command::SUCCESS|Command::FAILURE) or clearly state it returns a Command exit
code instead of implying success.

repo: $repo,
branch: $branch,
servers: $selectedServers
servers: [$server->name]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Clarify single-server design decision.

The change from multi-server to single-server selection is significant. While this may simplify the UX, users who previously added a site to multiple servers in one command will now need multiple invocations.

Is this intentional? Will users be able to add the same site to multiple servers easily, or is this a breaking change that should be documented?


🌐 Web query:

Check if there's a follow-up command or feature planned for multi-server site management in deployer-php

💡 Result:

Do you mean the Deployer (deployer.org / deployerphp) project or the “Deployer for Git” WordPress plugin — or another "deployer-php" repo? If you tell me which repository or provide a link, I’ll search the project issues/roadmap and report any planned follow-up command/feature for multi‑server site management (with citations).


I need to search the repository more specifically. Let me explore the codebase to understand the design decision and look for any documentation or issues about multi-server support.


---

🏁 Script executed:

```shell
#!/bin/bash
# Search for multi-server references and DTO definitions
rg -n "SiteDTO|servers" --type=php -A2 -B2 | head -50

Length of output: 3150


🏁 Script executed:

#!/bin/bash
# Check for any comments or TODOs about multi-server support
rg -n "TODO|FIXME|multi.*server|multi-server" --type=php | head -30

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Look for git history or comments explaining the change
git log -n 20 --oneline -- app/Console/Site/SiteAddCommand.php 2>/dev/null || echo "Git history not available"

Length of output: 169


🏁 Script executed:

#!/bin/bash
# Search for issues or feature discussions in common locations
find . -type f \( -name "*.md" -o -name "CHANGELOG*" -o -name "TODO*" -o -name ".github" \) -exec grep -l "multi.*server\|SiteAdd" {} \; 2>/dev/null | head -10

Length of output: 0



---

🏁 Script executed:

```shell
#!/bin/bash
# Find and inspect SiteDTO definition
fd "SiteDTO" --type=f | head -5

Length of output: 20


🏁 Script executed:

#!/bin/bash
# Get full SiteAddCommand.php to see complete context
cat app/Console/Site/SiteAddCommand.php | head -200

Length of output: 5569


🏁 Script executed:

#!/bin/bash
# Search for other site commands to see if multi-server is handled elsewhere
fd "Site.*Command.php" --type=f | xargs ls -la 2>/dev/null

Length of output: 258


🏁 Script executed:

#!/bin/bash
# Look for Site management services that might handle multi-server
rg -n "class.*Service.*Site\|function.*addSite\|function.*createSite" --type=php -A3 | head -40

Length of output: 0



---

🏁 Script executed:

```shell
#!/bin/bash
# Inspect SiteDTO structure
cat app/DTOs/SiteDTO.php

Length of output: 936


🏁 Script executed:

#!/bin/bash
# Find and inspect SiteRepository.create() method
rg -n "class SiteRepository\|function create\|public function create" --type=php -A15 app/Repositories/SiteRepository.php 2>/dev/null | head -60

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Check SiteDeleteCommand to see if it handles multi-server deletes
cat app/Console/Site/SiteDeleteCommand.php

Length of output: 3215


🏁 Script executed:

#!/bin/bash
# Look at git diff for the refactor commit to understand what changed
git show 97b52bd --stat 2>/dev/null | head -30

Length of output: 733



---

🏁 Script executed:

```shell
#!/bin/bash
# Get the actual diff of SiteAddCommand from the refactor to see what changed
git show 97b52bd -- app/Console/Site/SiteAddCommand.php 2>/dev/null | head -150

Length of output: 4894


🏁 Script executed:

#!/bin/bash
# Search for any edit/update site command or mechanism
fd "SiteUpdateCommand\|SiteEditCommand\|updateSite\|editSite" --type=f

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Search for any way to modify existing sites (add servers, etc.)
rg -n "class.*Site.*\|update.*site\|edit.*site\|add.*server.*site" --type=php -i | grep -v "test\|Test" | head -20

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Check if there are any comments in code about multi-server or server list
rg -n "servers|multiple.*server" app/Console/Site/ --type=php -B2 -A2 | head -40

Length of output: 302


Document the single-server limitation or provide a migration path.

The refactor intentionally changed --servers (plural, multi-select) to --server (singular), removing the ability to add a site to multiple servers in one command. While this simplifies the UX, it's a breaking change with no documented workaround.

Either document this limitation explicitly in help text or CHANGELOG, or add a site:update command to modify servers after creation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant