Skip to content

Migrate System.CommandLine 2.0-beta4 to 3.0-preview - #8

Merged
einari merged 1 commit into
mainfrom
chore/update-system-commandline-3.0-preview
Aug 14, 2026
Merged

Migrate System.CommandLine 2.0-beta4 to 3.0-preview#8
einari merged 1 commit into
mainfrom
chore/update-system-commandline-3.0-preview

Conversation

@einari

@einari einari commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Summary

The daily automated Update Packages workflow has been failing every day trying to bump System.CommandLine from 2.0.0-beta4.22272.1 to the 3.0.0-preview line in Directory.Packages.props. That's a breaking API rewrite between the 2.x beta line and the 3.x preview line, so the bump alone (with no code changes) fails dotnet build with ~24 compiler errors in Source/Generator/Program.cs (CS1739, CS0117, CS1061, ...). Because the workflow only commits on a successful build, nothing was ever pushed to mainmain has stayed safely on 2.0.0-beta4 while the workflow silently failed day after day.

This PR does the migration deliberately:

  • Bumps System.CommandLine in Directory.Packages.props to 3.0.0-preview.7.26381.103 (the latest 3.0.0-preview build currently on NuGet.org, confirmed via dotnet package search System.CommandLine --prerelease).
  • Ports Source/Generator/Program.cs (the only consumer of the API, shared into Source/Generator.Build via a source-file glob include) to the reworked 3.0-preview surface, preserving the exact same CLI options/behavior:
    • Option<T> construction no longer accepts a description: named parameter. Description is now a plain settable property (inherited from the Symbol base class), and IsRequired was renamed to Required.
    • getDefaultValue: is replaced by the DefaultValueFactory property (Func<ArgumentResult, T>).
    • RootCommand.AddOption(...) is replaced by the Options.Add(...) collection property.
    • Command.SetHandler(...) is replaced by Command.SetAction(...), which hands the action a ParseResult (+ CancellationToken for the async overload) instead of pre-bound option values — values are now pulled out explicitly via parseResult.GetValue(option).
    • RootCommand.InvokeAsync(args) is replaced by a two-step rootCommand.Parse(args)parseResult.InvokeAsync().

The exact API shape was confirmed by decompiling the installed 3.0.0-preview.7.26381.103 package (via ilspycmd) rather than guessing from memory, since the 3.0-preview surface has moved across preview builds.

Test plan

  • dotnet build at the repo root succeeds with zero errors (previously ~24 CS**** errors across Generator.csproj and Generator.Build.csproj).
  • No test/Specs project exists in this solution, so none to run.
  • Manual smoke test of the built protocol-generator tool:
    • --help output shows the same options, required flags, defaults, and descriptions as before.
    • Running with no arguments produces the same "Option '--assembly' is required." / "Option '--output' is required." errors + help text + exit code 1.
    • Running against a nonexistent assembly path exercises the existing HandleCommand catch block, printing Error: Assembly not found: ... and exiting 1 (same as before).
    • A full run against a real built assembly (Backend.dll) with default --base-namespace/--skip-segments successfully generates the expected service interfaces and DTOs.

🤖 Generated with Claude Code

Bumps System.CommandLine from 2.0.0-beta4.22272.1 to
3.0.0-preview.7.26381.103, which unblocks the daily automated
"Update Packages" workflow that has been failing to apply this exact
bump (dotnet build failed with ~24 CS errors after the version bump
alone).

Ports Source/Generator/Program.cs to the reworked 3.0-preview API:
- Option<T> construction no longer takes a description: named
  parameter; Description is now a settable property inherited from
  Symbol, and IsRequired is renamed to Required.
- getDefaultValue: is replaced by the DefaultValueFactory property
  (Func<ArgumentResult, T>).
- RootCommand.AddOption is replaced by the Options.Add(...)
  collection property.
- Command.SetHandler is replaced by Command.SetAction(...), which
  receives a ParseResult (and CancellationToken for the async
  overload) instead of bound option values; values are now read via
  parseResult.GetValue(option).
- RootCommand.InvokeAsync(args) is replaced by parsing first
  (rootCommand.Parse(args)) and then invoking the resulting
  ParseResult (parseResult.InvokeAsync()).

Verified with dotnet build (clean, no errors) and manual smoke tests
of the built protocol-generator tool: --help output, missing required
option handling, and a full generation run all match prior behavior.
No test/spec project exists in this repo to run.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@einari
einari merged commit 78838a8 into main Aug 14, 2026
@einari
einari deleted the chore/update-system-commandline-3.0-preview branch August 14, 2026 09:57
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