Repository navigation
feat(cli): add --version - #195
Conversation
`projgraph --version` and `-v` failed with "Unexpected option" because no application version was configured. The CLI now prints the package version, e.g. 1.2.0-beta.1, without the +commit build metadata the SDK appends to the informational version. The version is read from the CLI assembly rather than through Spectre's UseAssemblyInformationalVersion, which reads the entry assembly (the test host under tests) and keeps the build metadata. Program's app configuration moves into Program.Configure, so the new test runs the real configuration against a TestConsole instead of Spectre's cached default console. The AOT smoke suite also compares --version between the native and JIT builds. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 Changes recommended
There are build/runtime safety issues in the new code (unused using and a null-forgiving reflection path that can crash --version) that should be addressed before approval.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adds first-class CLI version reporting by configuring Spectre.Console.Cli’s application version from the CLI assembly’s informational version (with +<commit> build metadata trimmed), and extends test coverage to ensure the option works and remains Native AOT–safe.
Changes:
- Configure
projgraph’s application version (enabling-v, --version) using the CLI assembly’sAssemblyInformationalVersionAttribute, trimming build metadata. - Refactor CLI command registration into
Program.Configureso tests can run real app configuration against aTestConsole. - Add integration + AOT smoke tests for
--version/-v, and document the option in the CLI README.
File summaries
| File | Description |
|---|---|
| tests/ProjGraph.Tests.Smoke.Aot/CliParityTests.cs | Adds AOT parity coverage for --version output presence and parity. |
| tests/ProjGraph.Tests.Integration.Cli/VersionOptionTests.cs | Adds integration tests asserting --version/-v succeed and print a plain SemVer without + metadata. |
| src/ProjGraph.Cli/README.md | Documents projgraph --version after installation. |
| src/ProjGraph.Cli/Program.cs | Sets application version and extracts shared CLI configuration into Program.Configure; adds version trimming helper. |
Review details
- Files reviewed: 4/4 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| var version = typeof(Program).Assembly | ||
| .GetCustomAttribute<AssemblyInformationalVersionAttribute>()!.InformationalVersion; | ||
| var metadataStart = version.IndexOf('+', StringComparison.Ordinal); | ||
| return metadataStart < 0 ? version : version[..metadataStart]; | ||
| } |
There was a problem hiding this comment.
Fixed in 160abd9. The SDK always generates the attribute, but the impact was wider than --version: Configure runs for every command, so a missing attribute would have broken them all. GetPackageVersion now takes the assembly and falls back to GetName().Version (2.3.4 for 2.3.4.5) before trimming the build metadata. GetPackageVersion_WithoutInformationalVersionAttribute_FallsBackToTheAssemblyVersion covers it with a dynamic assembly that has no attributes; before the fix it failed with the NullReferenceException you described.
| using ProjGraph.Cli; | ||
| using Spectre.Console.Cli; | ||
| using Spectre.Console.Testing; | ||
| using System.Reflection; | ||
| using System.Text.RegularExpressions; |
There was a problem hiding this comment.
It was unused in the reviewed commit. The fallback test added in 160abd9 now needs it (AssemblyName), so it stays. For the record, CS8019 is a hidden diagnostic, so it doesn't fail the build under TreatWarningsAsErrors.
… attribute Program.Configure runs for every command, so the null-forgiving attribute lookup would have failed all of them, not only --version, in a build without AssemblyInformationalVersionAttribute. GetPackageVersion now takes the assembly and falls back to its version. A test covers the fallback with a dynamic assembly that has no attributes; the test's System.Reflection using is needed for it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Summary
projgraph --version(and-v) failed withUnexpected option 'version'because no application version was configured. It has never worked, including in v1.1.0. I noticed it while checking thev1.2.0-beta.1install.Program.cs: sets the application version from the CLI assembly'sAssemblyInformationalVersionAttribute, without the+<commit>build metadata.--helpnow lists-v, --version.UseAssemblyInformationalVersion(), which readsAssembly.GetEntryAssembly()(the test host under tests) and keeps the+37abcac…suffix.Program.Configure: the app configuration moves out of theMainlambda into this method, with no behaviour change. The test then runs the real configuration against aTestConsole, not throughProgram.Main, becauseStrictParsingTestsmust stay the only test that reaches Spectre's cached default console.projgraph --versionafter the install command.Tests
VersionOptionTests(--versionand-v): exit code 0, a plain package version with no+metadata, starting with the CLI assembly's version. It failed first with the sameUnexpected optionerror as the published beta.CliParityTests.Version_ShouldMatchReference: native vs JIT parity, because the version comes from an assembly attribute the AOT build must keep.Test plan
dtk dotnet test ProjGraph.slnx: 1180 passeddotnet publish -r linux-x64(Native AOT) with-p:Version=1.2.0-beta.2: prints1.2.0-beta.2for--versionand-vVersion_ShouldMatchReference, bothHelp_*tests andStats_UnknownOptionpassaot-smokeCI job🤖 Generated with Claude Code