feat: Add destroy subcommand to CLI with UserOutput system#28
Merged
Conversation
Implement user-facing output functionality separate from internal logging with dual-channel strategy following Unix conventions: - stdout: final results and data for piping/redirection - stderr: progress updates, status messages, warnings, errors Add comprehensive unit tests with buffer writers for output capture and assertion. Co-authored-by: josecelano <58816+josecelano@users.noreply.github.com>
Add Commands enum with Destroy variant accepting environment parameter. Wire up destroy subcommand to call DestroyCommandHandler from application layer. Implement comprehensive CLI argument parsing tests. Integrate UserOutput for user-friendly progress messages and error handling. Co-authored-by: josecelano <58816+josecelano@users.noreply.github.com>
Fix needless_pass_by_value clippy warning by using &str instead of String. Add allow attribute for type_complexity in test helper. Run cargo fmt to ensure consistent code formatting. Co-authored-by: josecelano <58816+josecelano@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Add Clap subcommand configuration for destroy CLI
feat: Add destroy subcommand to CLI with UserOutput system
Oct 22, 2025
Member
Code Review UpdateI've reviewed the generated code and identified several architectural improvements needed. Rather than providing detailed feedback through PR comments, I'll handle the refactoring directly as it's more efficient than iterating through review cycles. The main areas I'll be addressing:
I'll push the improvements directly to maintain momentum on this PR. The core functionality is solid - these are primarily architectural refinements to align with the project's patterns and principles. |
Replace manual impl Default with derive attribute and #[default] annotation as suggested by clippy for better maintainability.
Improve separation of concerns by moving environment loading and state handling logic from presentation layer (CLI) to application layer: - DestroyCommandHandler now loads environment internally from EnvironmentName - CLI simplified to focus only on user interface concerns - Proper build directory path resolution using env.tofu_build_dir() - Eliminates circular dependency between CLI and command handler - Better testability and maintainability of business logic Breaking changes: - DestroyCommandHandler.execute() now takes EnvironmentName instead of Environment<S> - Constructor no longer requires OpenTofuClient (created internally) This follows clean architecture principles with proper layer separation.
…ntState - Add destroy() method to AnyEnvironmentState for unified state destruction - Add tofu_build_dir() method to AnyEnvironmentState for unified directory access - Update DestroyCommandHandler to use new methods with Result error handling - Add StateTypeError integration with Clone derive for error propagation - Remove 24 lines of repetitive match patterns across two locations - Add comprehensive test coverage for new methods and error cases
…ently - Remove Result wrapper from tofu_build_dir method - now returns PathBuf directly - Include Destroyed state in pattern matching like all other states - Simplify caller code in DestroyCommandHandler (no more error handling needed) - Update tests to reflect the simplified interface - Improve consistency: getter methods should return same result regardless of state - Let caller decide how to use the path based on their specific needs
…tring - Add LXD_PROVIDER_NAME constant to domain::environment module - Replace hardcoded 'lxd' string in tofu_build_dir() with constant reference - Improves maintainability and follows existing pattern with other constants - All 847 tests pass with comprehensive E2E validation
…architecture - Create new src/presentation/ layer for presentation concerns - Move user_output.rs from shared/ to presentation/ layer - Update all import paths from shared::user_output to presentation::user_output - Add proper presentation layer module documentation - Update lib.rs to include presentation module in DDD architecture - Update documentation references to reflect new file location - Maintains proper DDD separation: presentation handles user-facing output The user_output module represents presentation layer logic in DDD and belongs with other presentation concerns rather than shared utilities.
- Replace Box<dyn Error> with specific DestroyCommandError enum using thiserror - Add comprehensive error variants for different failure scenarios - Implement tiered help system with brief tips + detailed .help() method - Include actionable troubleshooting guidance following error handling conventions - Preserve error chains with #[source] attributes for full traceability - Provide clear, user-friendly error messages with specific instructions Features: - InvalidEnvironmentName: Validates environment name format with examples - DestroyOperationFailed: Handles destroy command execution failures - Environment context: Includes environment name and data directory paths - Detailed help: Platform-specific commands and recovery procedures Error handling follows docs/contributing/error-handling.md conventions: - Clarity: Unambiguous error messages with specific context - Traceability: Full error chains preserved for debugging - Actionability: Clear instructions for resolution
… error handling - Separate CLI parsing from business logic in presentation/cli/ - Create modular command execution system in presentation/commands/ - Implement unified CommandError with tiered help system - Add LoggingConfig abstraction decoupled from CLI parsing - Reduce app.rs to thin bootstrap (452 → 38 lines) - Create centralized help system in src/help.rs - Follow module organization guidelines with proper separation of concerns This completes the DDD architectural refactoring for clean separation between presentation, application, and domain layers.
…ates - Enhanced codebase-architecture.md with presentation layer documentation - Added architecture requirements to issue templates - Renamed TEMPLATE.md to SPECIFICATION-TEMPLATE.md for clarity - Renamed TASK-TEMPLATE.md to GITHUB-ISSUE-TEMPLATE.md for clarity - Updated template references in roadmap-issues.md These improvements address architectural gaps that caused AI assistants to implement CLI functionality in wrong DDD layers.
Fixes CI linting failure by adding 'reprovisioning' to project-words.txt. This word appears in docs/features/hybrid-command-architecture/README.md from main branch when PR is merged for CI testing.
josecelano
approved these changes
Oct 24, 2025
Member
|
ACK 87ac5f6 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
This PR implements the
destroysubcommand in the CLI with a new UserOutput system for user-facing messages, completing the UI layer for the destroy command workflow.Changes
UserOutput System (
src/shared/user_output.rs)Implemented a dual-channel output system following Unix conventions and modern CLI best practices (cargo, docker, npm):
VerbosityLevelenum: Five levels (Quiet, Normal, Verbose, VeryVerbose, Debug) with proper orderingUserOutputstruct: Dual writers separating concerns:torrust-tracker-deployer destroy env 2>/dev/nullcaptures only resultsCLI Integration (
src/app.rs)Added destroy subcommand with complete integration:
Commandsenum: NewDestroyvariant accepting environment parameterhandle_destroy_command()function that:DestroyCommandHandlerfrom application layerExample Usage
Testing
Code Quality
cargo fmtDependencies
Full end-to-end testing with actual infrastructure requires the
--keepflag from Issue #21 to preserve E2E test environments. The CLI is functionally complete and ready for use once that dependency is resolved.Related Issues
Documentation
See
docs/issues/23-add-clap-subcommand-configuration.mdfor full specification anddocs/research/UX/console-app-output-patterns.mdfor channel strategy research.Original prompt
This section details on the original issue you should resolve
<issue_title>Add Clap Subcommand Configuration</issue_title>
<issue_description># Add Clap Subcommand Configuration
Type: Task
Priority: High
Parent Epic: #10 - UI Layer Destroy Command
Dependencies: #21 - MUST BE COMPLETED FIRST (E2E Infrastructure Preservation)
Estimated Effort: 3-4 hours
📋 Issue Overview
Implement the
destroysubcommand in the CLI with basic functionality and UserOutput scaffolding. This creates the user-facing interface that calls the DestroyCommandHandler from the application layer.🔗 Dependencies
Blocking Dependency: Issue #21 (Fix E2E Infrastructure Preservation)
This issue CANNOT be implemented until Issue #21 is completed because:
--keepflag--keepto provision infrastructurelxc list | grep e2e-provision)Without Issue #21 completed, the manual testing workflow is broken and this destroy CLI implementation cannot be properly validated.
🎯 Goals
destroysubcommand to Clap configurationDestroyCommandHandlerfrom application layerVerbosityLevelenum andUserOutputstructUserOutput📦 Scope
Clap Subcommand Structure
Add to
src/app.rs:UserOutput Integration
VerbosityLevelenum (Quiet, Normal, Verbose, VeryVerbose, Debug)UserOutputstruct with methods for different message typesUserOutputfor essential destroy command messagesExample Usage
Example Output (Normal verbosity level)
✅ Acceptance Criteria
Prerequisites: Issue #21 (Fix E2E Infrastructure Preservation) must be completed before this can be fully tested and accepted.
destroysubcommand added to Clap configurationenvironmentparameterVerbosityLevelenum implemented with 5 levels (Quiet, Normal, Verbose, VeryVerbose, Debug)UserOutputstruct implemented with dual writers and proper channel separationDestroyCommandHandlerfrom application layerManual Testing Procedure
--keepflag functionality is required for this testing procedure.Step 1: Set up test infrastructure using E2E tests
Step 2: Test the new destroy CLI command
S...
Fixes #23
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.