Просмотр исходного кода

config cleanup, CLI consistency, doc updates

Tim Jones 3 дней назад
Родитель
Сommit
098f7dc408

+ 1 - 0
AGENTS.md

@@ -281,6 +281,7 @@ Default branches: feature work targets `staging`; releases flow `staging → mai
 
 - **E2E tests require the Docker image.** `just test-e2e` rebuilds it via `just build-web`. If you change anything in `RackPeek.Web`, `RackPeek.Domain`, or `Shared.Rcl`, the image must be rebuilt before E2E runs.
 - **Playwright browsers** are installed once via `just e2e-setup`. In CI they're cached under `~/.cache/ms-playwright`.
+- **Bumping the `Microsoft.Playwright` package invalidates the browser cache.** Each Playwright version pins a specific Chromium build (e.g. 1.58 → `chromium_headless_shell-1208`, 1.59 → `-1217`). After bumping, every E2E test fails fast with `PlaywrightException : Executable doesn't exist at .../chromium_headless_shell-NNNN`. Re-run `just e2e-setup` (or `~/.dotnet/tools/playwright install chromium`) to download the matching build before running the suite.
 - **Docker image tag** is `rackpeek:ci` locally (referenced by `Tests.E2e/Infra/PlaywrightFixture.cs:9`); the registry tag is `aptacode/rackpeek`.
 - **Debugging E2E**: temporarily set `Headless = false, SlowMo = 1500` in `Tests.E2e/Infra/PlaywrightFixture.cs`. **Always revert before commit** — CI requires headless.
 - **TreatWarningsAsErrors** — a stray `unused-variable` warning fails the whole build. Don't add `#pragma warning disable` to push through; fix the warning.

+ 0 - 80
RackPeek.Web/RackPeek.Web.csproj

@@ -16,86 +16,6 @@
         <ProjectReference Include="..\Shared.Rcl\Shared.Rcl.csproj"/>
     </ItemGroup>
 
-    <ItemGroup>
-        <_ContentIncludedByDefault Remove="Components\Components\Desktops\DesktopCardComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Components\Desktops\DesktopsListComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\FireWalls\FireWallCardComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\FireWalls\FireWallsListComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\FireWalls\FireWallsListPage.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Laptops\LaptopCardComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Laptops\LaptopsListComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Laptops\LaptopsListPage.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Routers\RouterCardComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Routers\RoutersListComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Routers\RoutersListPage.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Servers\Components\HardwareDependencyTreeComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Servers\Components\ResourceBreadCrumbComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Servers\Components\ServerCardComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Servers\Components\ServersListComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Servers\Components\ServiceCardComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Servers\Components\ServicesListComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Servers\Components\SystemCardComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Servers\Components\SystemDependencyTreeComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Servers\Components\SystemsListComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\AccessPoints\AccessPointCardComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\AccessPoints\AccessPointsListComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\AccessPoints\AccessPointsListPage.razor"/>
-        <_ContentIncludedByDefault Remove="Components\AccessPoints\AddAccessPointComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Components\HardwareDependencyTreeComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Components\ResourceBreadCrumbComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Desktops\AddDesktopComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Desktops\DesktopCardComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Desktops\DesktopsListComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Desktops\DesktopsListPage.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Firewalls\AddFirewallComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Firewalls\FirewallListComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Firewalls\FirewallListPage.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Hardware\HardwareDetailsPage.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Hardware\HardwareTreePage.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Laptops\AddLaptopComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Layout\MainLayout.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Layout\ReconnectModal.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Modals\ConfirmModal.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Modals\CpuModal.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Modals\DriveModal.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Modals\GpuModal.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Modals\HardwareSelectionModal.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Modals\NicModal.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Modals\PortModal.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Modals\RamModal.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Modals\StringValueModal.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Modals\SystemSelectionModal.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Pages\Error.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Pages\Home.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Pages\NotFound.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Routers\AddRouterComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Routers\RouterListComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Routers\RouterListPage.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Servers\AddServerComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Servers\ServerCardComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Servers\ServersListComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Servers\ServersListPage.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Services\AddServiceComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Services\ServiceCardComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Services\ServiceDetailsPage.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Services\ServicesListComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Services\ServicesListPage.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Switches\AddSwitchComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Switches\SwitchCardComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Switches\SwitchListComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Switches\SwitchListPage.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Systems\AddSystemComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Systems\SystemCardComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Systems\SystemDependencyTreeComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Systems\SystemsDetailsPage.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Systems\SystemsListComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Systems\SystemsListPage.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Ups\AddUpsComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Ups\UpsCardComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Ups\UpsListComponent.razor"/>
-        <_ContentIncludedByDefault Remove="Components\Ups\UpsListPage.razor"/>
-    </ItemGroup>
-
     <ItemGroup>
         <Content Include="..\.dockerignore">
             <Link>.dockerignore</Link>

+ 5 - 5
Shared.Rcl/CliBootstrap.cs

@@ -541,11 +541,11 @@ public static class CliBootstrap {
                 });
 
                 // Drives
-                laptops.AddBranch("drives", drives => {
-                    drives.SetDescription("Manage storage drives attached to Laptops.");
-                    drives.AddCommand<LaptopDriveAddCommand>("add").WithDescription("Add a drive to a Laptop.");
-                    drives.AddCommand<LaptopDriveSetCommand>("set").WithDescription("Update a Laptop drive.");
-                    drives.AddCommand<LaptopDriveRemoveCommand>("del").WithDescription("Remove a drive from a Laptop.");
+                laptops.AddBranch("drive", drive => {
+                    drive.SetDescription("Manage storage drives attached to Laptops.");
+                    drive.AddCommand<LaptopDriveAddCommand>("add").WithDescription("Add a drive to a Laptop.");
+                    drive.AddCommand<LaptopDriveSetCommand>("set").WithDescription("Update a Laptop drive.");
+                    drive.AddCommand<LaptopDriveRemoveCommand>("del").WithDescription("Remove a drive from a Laptop.");
                 });
 
                 // GPUs

+ 1 - 1
Tests/EndToEnd/CliCommandsWorkflowTests.cs

@@ -391,7 +391,7 @@ public class CliCommandsWorkflowTests(TempYamlCliFixture fs, ITestOutputHelper o
         Assert.Contains("added", output);
 
         (output, _) = await ExecuteAsync(
-            "laptops", "drives", "add", "ltp-dev-01",
+            "laptops", "drive", "add", "ltp-dev-01",
             "--type", "ssd",
             "--size", "1024"
         );

+ 1 - 1
Tests/EndToEnd/LaptopTests/LaptopCommandTests.cs

@@ -45,7 +45,7 @@ public class LaptopCommandTests(TempYamlCliFixture fs, ITestOutputHelper outputH
         Assert.Contains("Add a CPU", (await ExecuteAsync("laptops", "cpu", "add", "--help")).Item1);
 
         // Drives help
-        Assert.Contains("Manage storage drives", (await ExecuteAsync("laptops", "drives", "--help")).Item1);
+        Assert.Contains("Manage storage drives", (await ExecuteAsync("laptops", "drive", "--help")).Item1);
 
         // GPU help
         Assert.Contains("Manage GPUs", (await ExecuteAsync("laptops", "gpu", "--help")).Item1);

+ 1 - 1
Tests/EndToEnd/LaptopTests/LaptopErrorTests.cs

@@ -68,7 +68,7 @@ public class LaptopErrorTests(TempYamlCliFixture fs, ITestOutputHelper outputHel
         await ExecuteAsync("laptops", "add", "lap01");
 
         (var output, var _) = await ExecuteAsync(
-            "laptops", "drives", "set", "lap01", "3",
+            "laptops", "drive", "set", "lap01", "3",
             "--type", "ssd"
         );
 

+ 1 - 1
Tests/EndToEnd/LaptopTests/LaptopWorkflowTests.cs

@@ -50,7 +50,7 @@ public class LaptopWorkflowTests(TempYamlCliFixture fs, ITestOutputHelper output
 
         // Add Drive
         (output, yaml) = await ExecuteAsync(
-            "laptops", "drives", "add", "lap01",
+            "laptops", "drive", "add", "lap01",
             "--type", "ssd",
             "--size", "512"
         );

+ 4 - 4
docs/CommandIndex.md

@@ -123,10 +123,10 @@
       - [add](Commands.md#rpk-laptops-cpu-add) - Add a CPU to a Laptop
       - [set](Commands.md#rpk-laptops-cpu-set) - Update a Laptop CPU
       - [del](Commands.md#rpk-laptops-cpu-del) - Remove a CPU from a Laptop
-    - [drives](Commands.md#rpk-laptops-drives) - Manage storage drives attached to Laptops
-      - [add](Commands.md#rpk-laptops-drives-add) - Add a drive to a Laptop
-      - [set](Commands.md#rpk-laptops-drives-set) - Update a Laptop drive
-      - [del](Commands.md#rpk-laptops-drives-del) - Remove a drive from a Laptop
+    - [drive](Commands.md#rpk-laptops-drive) - Manage storage drives attached to Laptops
+      - [add](Commands.md#rpk-laptops-drive-add) - Add a drive to a Laptop
+      - [set](Commands.md#rpk-laptops-drive-set) - Update a Laptop drive
+      - [del](Commands.md#rpk-laptops-drive-del) - Remove a drive from a Laptop
     - [gpu](Commands.md#rpk-laptops-gpu) - Manage GPUs attached to Laptops
       - [add](Commands.md#rpk-laptops-gpu-add) - Add a GPU to a Laptop
       - [set](Commands.md#rpk-laptops-gpu-set) - Update a Laptop GPU

+ 9 - 9
docs/Commands.md

@@ -1845,7 +1845,7 @@ COMMANDS:
     summary            Show a summarized hardware report for all Laptops
     tree <name>        Display the dependency tree for a Laptop         
     cpu                Manage CPUs attached to Laptops                  
-    drives             Manage storage drives attached to Laptops        
+    drive              Manage storage drives attached to Laptops        
     gpu                Manage GPUs attached to Laptops                  
 ```
 
@@ -2018,13 +2018,13 @@ OPTIONS:
     -h, --help    Prints help information
 ```
 
-## `rpk laptops drives`
+## `rpk laptops drive`
 ```
 DESCRIPTION:
 Manage storage drives attached to Laptops
 
 USAGE:
-    rpk laptops drives [OPTIONS] <COMMAND>
+    rpk laptops drive [OPTIONS] <COMMAND>
 
 OPTIONS:
     -h, --help    Prints help information
@@ -2035,13 +2035,13 @@ COMMANDS:
     del <Laptop> <index>    Remove a drive from a Laptop
 ```
 
-## `rpk laptops drives add`
+## `rpk laptops drive add`
 ```
 DESCRIPTION:
 Add a drive to a Laptop
 
 USAGE:
-    rpk laptops drives add <laptop> [OPTIONS]
+    rpk laptops drive add <laptop> [OPTIONS]
 
 ARGUMENTS:
     <laptop>    The name of the Laptop
@@ -2052,13 +2052,13 @@ OPTIONS:
         --size    The drive capacity in GB:   
 ```
 
-## `rpk laptops drives set`
+## `rpk laptops drive set`
 ```
 DESCRIPTION:
 Update a Laptop drive
 
 USAGE:
-    rpk laptops drives set <Laptop> <index> [OPTIONS]
+    rpk laptops drive set <Laptop> <index> [OPTIONS]
 
 ARGUMENTS:
     <Laptop>    The Laptop name          
@@ -2070,13 +2070,13 @@ OPTIONS:
         --size    The drive capacity in Gb    
 ```
 
-## `rpk laptops drives del`
+## `rpk laptops drive del`
 ```
 DESCRIPTION:
 Remove a drive from a Laptop
 
 USAGE:
-    rpk laptops drives del <Laptop> <index> [OPTIONS]
+    rpk laptops drive del <Laptop> <index> [OPTIONS]
 
 ARGUMENTS:
     <Laptop>    The name of the Laptop          

+ 2 - 0
docs/development/dev-cheat-sheet.md

@@ -99,6 +99,8 @@ dotnet build
 playwright install
 ```
 
+> ⚠ **Re-run `playwright install` whenever the `Microsoft.Playwright` NuGet is bumped.** Each Playwright release pins a specific Chromium build (e.g. 1.58 ships `chromium_headless_shell-1208`, 1.59 ships `-1217`). If the cache is stale every test fails with `PlaywrightException : Executable doesn't exist at .../chromium_headless_shell-NNNN`. `just e2e-setup` covers this.
+
 Build Web image (required before running tests):
 
 ```bash

+ 44 - 1
docs/development/dev-setup.md

@@ -99,7 +99,50 @@ dotnet --version
 
 ### MacOS
 
-🏗️ Help wanted for guide on MacOS development environment setup.
+Setup tested on macOS (Apple Silicon and Intel). All dependencies install via Homebrew.
+
+#### Install .NET 10 SDK
+
+```shell
+brew install --cask dotnet-sdk
+```
+
+Verify:
+
+```shell
+dotnet --version
+```
+
+If `dotnet --version` reports a version below `10.0.x`, install the SDK explicitly:
+
+```shell
+brew install --cask dotnet-sdk@10
+```
+
+#### Install Docker Desktop
+
+Needed for running the Web UI locally (`just run-docker`) and for the E2E test suite (which builds the `rackpeek:ci` image via Testcontainers):
+
+```shell
+brew install --cask docker
+open -a Docker        # start the daemon; wait until the whale icon settles
+```
+
+Verify:
+
+```shell
+docker info
+```
+
+#### (Optional) Playwright browsers for E2E
+
+The first time you run E2E tests:
+
+```shell
+just e2e-setup
+```
+
+This installs the `Microsoft.Playwright.CLI` global tool and downloads the Chromium build pinned to the current Playwright NuGet version. **Re-run it whenever the `Microsoft.Playwright` package is bumped** — each Playwright version pins a specific Chromium build and stale caches cause every test to fail with `PlaywrightException : Executable doesn't exist at .../chromium_headless_shell-NNNN`.
 
 ### Windows