Skip to content

C#: fix InstallRecipes echoing wildcard versions in response.Version#7697

Merged
macsux merged 1 commit into
mainfrom
update-pr-body
May 19, 2026
Merged

C#: fix InstallRecipes echoing wildcard versions in response.Version#7697
macsux merged 1 commit into
mainfrom
update-pr-body

Conversation

@natedanner
Copy link
Copy Markdown
Contributor

Summary

  • Fixed: the InstallRecipes RPC was returning the literal version-constraint string (*, *-*, etc.) as InstallRecipesResponse.Version instead of the resolved concrete SemVer. Downstream consumers (moderne-cli recipes-v5.csv, moderne-saas GraphQL) surfaced these as the "installed version" and had to work around it.
  • Root cause: dotnet add package <pkg> --version * preserves the wildcard verbatim in the csproj's <PackageReference>. The old ResolveVersionFromCsproj read from that attribute, so wildcards flowed through unchanged. Verified against real dotnet output (Version="*" is written literally).
  • Fix: new public helper MSBuildProjectHelper.GetResolvedPackageVersion(projectDir, packageName) reads obj/project.assets.json (NuGet's per-TFM resolution map written by restore) and returns the resolved version of a direct dependency. Reads from targets to match the convention already used by ReadResolvedPackages in the same file. Throws InvalidOperationException with specific diagnostics for: missing project.assets.json, package not a direct dep, or no matching resolved entry.
  • InstallRecipes call site (RewriteRpcServer.cs) now delegates to the helper; the old private ResolveVersionFromCsproj is removed along with the unused System.Xml.Linq import.
  • Regression coverage in OpenRewrite.Tests/Rpc/InstallVersionResolverTests.cs: theory rows for * and *-* against concrete-resolved fixtures, plus facts for case-insensitive package match, unknown-package throw, and missing-assets-json throw.

Test plan

  • dotnet test --filter InstallVersionResolverTests — 5/5 pass in ~10 ms.
  • ./gradlew :rewrite-csharp:csharpTest — 1936/1936 pass.
  • Mutation test: replacing the targets lookup with project.frameworks.<tfm>.dependencies.<pkg>.version (the original bug shape) causes the two wildcard rows + case-insensitive case to fail (3/5 failures). Confirms the tests actually cover the regression.
  • Verified against real dotnet add package Newtonsoft.Json --version "*" output: csproj receives Version="*"; obj/project.assets.json contains targets.<tfm>."Newtonsoft.Json/13.0.4" and libraries."Newtonsoft.Json/13.0.4"; helper returns 13.0.4.

Out of scope

  • Pre-existing _recipesProjectDir caching across InstallRecipes calls (no per-call cleanup, no concurrency control). Not introduced by this PR.
  • moderne-cli and moderne-saas workarounds that scan ~/.nuget/packages/ or post-process the version string; those become dead code once this fix ships.

`dotnet add package <pkg> --version *` preserves the wildcard verbatim in
the csproj's PackageReference, so reading it back from the csproj returned
`*` instead of the resolved concrete SemVer. Read the resolved version from
`obj/project.assets.json` (NuGet's per-TFM resolution map) via a new public
helper `MSBuildProjectHelper.GetResolvedPackageVersion`.
Copy link
Copy Markdown
Contributor

@macsux macsux left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm

@macsux macsux merged commit 0119a3c into main May 19, 2026
1 check passed
@macsux macsux deleted the update-pr-body branch May 19, 2026 17:07
@github-project-automation github-project-automation Bot moved this from In Progress to Done in OpenRewrite May 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

2 participants