Replace Spectre.Console.Cli with AOT-trimmable alternative#171
Conversation
Co-authored-by: Copilot <copilot@github.com>
Code Review — PR #171: Replace Spectre.Console.Cli with System.CommandLineOverall the migration is well-structured and the architectural decisions are sound. The plan to preserve Spectre.Console for rendering while swapping only the CLI parsing layer is the right call, and the new Bugs / Correctness Issues[BLOCKER] var serviceProvider = services.BuildServiceProvider();
// ... no using/await using
return await RunAsync(serviceProvider, ...);
await using var serviceProvider = services.BuildServiceProvider();
return await RunAsync(serviceProvider, ...);The same leak exists in [BLOCKER] serviceCollection.AddSingleton<IAnsiConsole>(testConsole); // not TryAdd
serviceCollection.TryAddSingleton<IAnsiConsole>(testConsole);Or better, build a fresh [HIGH] Help detection doesn't handle flags before if (args.Length > 0 && (args[0] is "-h" or "--help" or "-?")) // root help
if (args.Length > 1 && (args[1] is "-h" or "--help" or "-?")) // subcommand helpThis only inspects
Users expect var hasHelp = args.Any(a => a is "-h" or "--help" or "-?");
var firstNonFlag = args.FirstOrDefault(a => !a.StartsWith('-'));
// then branch on subcommand vs root[MEDIUM] /// Single character delimiter to use in CSV output.
public required string CSVDelimiter { get; init; }
[LOW] Dead null-coalescing after args!.Where(s => !s.Equals("--test"))!.ToArray() ?? Array.Empty<string>()
SecurityNothing concerning. No command injection risk, no hard-coded credentials, no insecure defaults introduced. Convention AdherenceMissing XML docs on public
Bare catch
{
return "";
}A bare Nullable
Test CoverageCoverage looks solid. All 83+ existing tests were migrated and two new One gap worth flagging: there is no test that verifies Spec / Test-Plan CheckPR description states "0 warnings, 0 errors" and "537 passed, 0 failed". The two new tests ( No user-facing behaviour change is claimed; that appears accurate from the diff. Summary
The migration strategy is sound and the test harness design is clean. Fix the two blockers and the help-scanning issue before merging — the rest can follow in a clean-up PR. |
|
@claude - Please see the following and action accordingly:
|
|
Claude finished @FrankRay78's task in 17m 43s —— View job Implemented PR Review FixesAll changes applied, built (0 warnings), and pushed. Here's what was done:
Build: 0 errors, 0 warnings
|
… on local IDisposable' Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
- ServiceProvider now disposed with `await using` in both Program.Main and CommandLineTestHost.RunAsync (supersedes Copilot Autofix `using`) - CommandLineTestHost.RunAsync uses TryAddSingleton for IAnsiConsole to avoid duplicate registrations on re-use - CSVDelimiter changed to char in SpeedTestCommandSettings; Option<string> retained for CLI parsing with a single-char validator - Dead `?? Array.Empty<string>()` removed after ToArray() in Program.Main - bool? changed to bool in ListServersCommandSettings; null checks removed in ListServersCommand.ExecuteAsync - XML docs added to SpeedTestCommand.ExecuteAsync and ListServersCommand.ExecuteAsync - Bare catch blocks replaced with catch (Exception) in CustomHelpProvider.GetDefaultValue and ListServersCommand.DisplayServersWithLatency - CLAUDE.md documents intentional --help position behaviour Co-authored-by: Frank Ray <FrankRay78@users.noreply.github.com>
… on local IDisposable' Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Summary
Replaces
Spectre.Console.CliwithSystem.CommandLineto enable AOT compilation and trimming of the NetPace CLI.Spectre.Console.Cli uses reflection-based command binding that isn't compatible with .NET's AOT/trim requirements. This PR swaps the CLI framework to
System.CommandLine(which is AOT-friendly) while preservingSpectre.Consoleitself for rich terminal rendering (tables, markup, progress bars). Test infrastructure migrates fromCommandAppTesterto a newCommandLineTestHostthat drives the realRootCommandthroughIServiceCollection, keeping tests close to production wiring.The branch also re-integrates main's
IClientInfoProvider/ Hostname-IP feature (#167) into the new DI setup, and fills in two Error_Values regression tests for the Default and Minimal output formats that had orphan.verified.txtfiles on main but no matching test methods.Spec
N/A — internal framework migration, no user-facing behavior change.
Changed Files
src/NetPace.Console/Program.cs— rewritten to useSystem.CommandLinewithMicrosoft.Extensions.DependencyInjection; replacesTypeRegistrar/TypeResolverwhich are deletedsrc/NetPace.Console/Commands/SpeedTestCommand.cs,ListServersCommand.cs, theirSettingsclasses — refactored to no longer depend onSpectre.Console.Cli.AsyncCommandor attribute-based bindingsrc/NetPace.Console/CustomHelpProvider.cs— new help renderer, styling aligned with Spectre.Consolesrc/NetPace.Console.Tests/CommandLineTestHost.cs— new test host that runs realProgram.RunAsync; registersClientInfoProviderStubby default viaTryAddSingletonsrc/NetPace.Console.Tests/NetPaceConsoleTests.*.cs— migrated fromTypeRegistrar/CommandAppTestertoServiceCollection/CommandLineTestHostsrc/NetPace.Console.Tests/NetPaceConsoleTests.Default.cs,NetPaceConsoleTests.Minimal.cs— ported from main plus added the two missingShould_Not_Include_IPAddress_Or_Hostname_..._With_Stub_Providing_Error_Valuestests that had orphan expectation files on mainSpeedTestCommandconstructor now takesIClientInfoProvider;Program.csDI registersClientInfoProvider(real) andClientInfoProviderStub(test)New Artifacts
None.
Test Plan
dotnet build src/NetPace.sln— 0 warnings, 0 errorsdotnet test src/NetPace.sln— 537 passed, 0 failed, 0 skipped (was 535 before this PR — added 2 new Error_Values tests)#if FALSEblocks remain)