Skip to content

Add recipeInstallDir to CSharpRewriteRpc so callers control the recipe project location#7819

Open
shanman190 wants to merge 2 commits into
mainfrom
csharp/recipe-install-dir
Open

Add recipeInstallDir to CSharpRewriteRpc so callers control the recipe project location#7819
shanman190 wants to merge 2 commits into
mainfrom
csharp/recipe-install-dir

Conversation

@shanman190
Copy link
Copy Markdown
Contributor

Problem

The C# RPC server always creates its recipe project (the Recipes.csproj against which dotnet add package resolves recipe NuGet packages) under a private temp directory. Because dotnet discovers NuGet.config by walking up from the project directory, a caller (e.g. the Moderne CLI) had no way to inject a package feed via a generated NuGet.config — there was nowhere to put it that dotnet would find.

Solution

Bring the C# RPC up to parity with the JavaScript, Python, and Go RPC servers, which already expose recipeInstallDir / --recipe-install-dir. The C# server now creates Recipes.csproj in a caller-supplied directory when one is provided (otherwise the previous temp-dir behavior is unchanged), so a NuGet.config co-located in that directory is honored by dotnet's project-directory config discovery.

  • CSharpRewriteRpc.Builder.recipeInstallDir(Path) appends --recipe-install-dir= to the server command (tool-path, csproj, and explicit-entry paths)
  • Program.cs parses --recipe-install-dir= and threads it through RunAsync
  • RewriteRpcServer creates the recipe project under that directory when set

The change is additive and backward-compatible: the new constructor/builder/RunAsync parameters default to the prior behavior.

Context

Unblocks the Moderne CLI mod config recipes nuget install feature so it can resolve recipes from a configured artifact repository (the CLI writes a NuGet.config into the install dir). npm/pip/go deliver their configured feed via environment variables and need no server change; nuget is file-based, hence this hook.

Testing

  • C# tool/server and Java :rewrite-csharp:compileJava build clean.
  • C# unit tests pass. The CsprojParseTests RPC integration tests require RPC_TEST_SERVER_CLASSPATH (or ./gradlew :rewrite-csharp:rpcTestClasspath) and fail identically on main in a bare checkout — unrelated to this change.

…e project location

The recipe project — where `dotnet add package` resolves recipe NuGet packages —
was always created under a private temp directory. Because dotnet discovers
NuGet.config by walking up from the project directory, a caller had no way to
inject a package feed via a generated NuGet.config.

Mirror the JavaScript RPC's recipeInstallDir/--recipe-install-dir pattern: the C#
server now creates Recipes.csproj in a caller-supplied directory when one is
provided (otherwise the previous temp-dir behavior), so a co-located NuGet.config
is honored by dotnet's config discovery.

- CSharpRewriteRpc.Builder.recipeInstallDir(Path) appends --recipe-install-dir=
  to the server command (tool-path, csproj, and explicit-entry paths)
- Program.cs parses --recipe-install-dir= and threads it through RunAsync
- RewriteRpcServer creates the recipe project under that directory when set
@shanman190 shanman190 self-assigned this May 29, 2026
@github-project-automation github-project-automation Bot moved this to In Progress in OpenRewrite May 29, 2026
@okundzich
Copy link
Copy Markdown
Member

okundzich commented May 29, 2026

what was the user visible effect prior to this change? What was broken and fixed with this? We have MS build demos going on next week, so would like to inform the team going there if something has materially changed.

EnsureRecipesProject unconditionally wrote a nuget.config (nuget.org + local-feed)
into the recipe project dir when ~/.nuget/local-feed exists. Now that the project
dir can be a caller-supplied recipeInstallDir, that overwrote a caller's config
(e.g. an exclusive configured feed).

Make the local feed additive instead: BuildRecipesNuGetConfig creates the
public + local-feed config only when none exists, and otherwise appends only the
local feed to the existing <packageSources> (idempotently, preserving the caller's
sources and any <clear/>). Local-dev-only; no-ops in production where local-feed
is absent.
@shanman190
Copy link
Copy Markdown
Contributor Author

This is needed to help support the CLI when installing recipes from private sources only. We need to be able to apply some changes to the temporary install project that is created for each recipe install, but unlike all of the other RPC implementations, C# was missing this mechanism.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

2 participants