Skip to content

Commit 32095ac

Browse files
authored
Split C# NuGet into library and tool packages (#6912)
PackAsTool=true causes NuGet to place DLLs in tools/ instead of lib/, making types unavailable at compile time for downstream PackageReference consumers. The OpenRewrite.csproj was both a library (SDK types like Recipe, CSharpVisitor) and a tool (Program.cs for the RPC server), so the packed .nupkg put everything in tools/ and was unusable as a dependency. Split into two projects: - OpenRewrite.CSharp (library) — all SDK types, packable with DLLs in lib/ via PackageReference - OpenRewrite.CSharp.Tool (tool) — just Program.cs with a ProjectReference to the library, packed with PackAsTool=true for dotnet tool install Also adds a csharpPublishLocal task for local NuGet feed development and simplifies the snapshot version logic to always use timestamps.
1 parent eec6719 commit 32095ac

5 files changed

Lines changed: 66 additions & 18 deletions

File tree

rewrite-csharp/build.gradle.kts

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -118,17 +118,13 @@ tasks.withType<Test> {
118118
// NuGet Version & Version File
119119
// ============================================
120120

121-
// Generate a NuGet-compatible version for CI builds
122-
// Snapshots use pre-release suffix: 8.73.0-snapshot.20260110143252
121+
// Generate a NuGet-compatible version
122+
// Snapshots use pre-release suffix with timestamp: 8.73.0-snapshot.20260110143252
123123
// Releases use clean version: 8.73.0
124-
val nugetVersion: String = if (System.getenv("CI") != null) {
125-
project.version.toString().replace(
126-
"-SNAPSHOT",
127-
"-snapshot.${LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))}"
128-
)
129-
} else {
130-
project.version.toString().replace("-SNAPSHOT", "-dev")
131-
}
124+
val nugetVersion: String = project.version.toString().replace(
125+
"-SNAPSHOT",
126+
"-snapshot.${LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))}"
127+
)
132128

133129
val generateVersionTxt by tasks.registering {
134130
group = "csharp"
@@ -154,11 +150,11 @@ listOf("sourcesJar", "processResources", "licenseMain", "assemble").forEach {
154150
// NuGet Publishing Tasks
155151
// ============================================
156152

157-
// Task to pack the C# project as a NuGet tool package
158-
// Version is injected via /p:Version so the .csproj is never modified
153+
// Task to pack C# projects as NuGet packages
154+
// Packs both the SDK library and the tool; version is injected via /p:Version
159155
val csharpPack by tasks.registering(Exec::class) {
160156
group = "csharp"
161-
description = "Pack C# project as NuGet package"
157+
description = "Pack C# projects as NuGet packages"
162158

163159
workingDir = csharpDir
164160
commandLine(
@@ -169,12 +165,13 @@ val csharpPack by tasks.registering(Exec::class) {
169165
)
170166

171167
inputs.dir(csharpDir.resolve("OpenRewrite"))
168+
inputs.dir(csharpDir.resolve("OpenRewrite.Tool"))
172169
inputs.property("version", nugetVersion)
173170
outputs.dir(csharpDir.resolve("dist"))
174171

175172
doFirst {
176173
csharpDir.resolve("dist").deleteRecursively()
177-
logger.lifecycle("Packing C# NuGet package (version: $nugetVersion)")
174+
logger.lifecycle("Packing C# NuGet packages (version: $nugetVersion)")
178175
}
179176
}
180177

@@ -201,6 +198,28 @@ val csharpPublish by tasks.registering(Exec::class) {
201198
}
202199
}
203200

201+
// Task to publish the C# SDK library to a local NuGet feed for cross-repo development.
202+
// Usage: ./gradlew :rewrite-csharp:csharpPublishLocal
203+
val csharpPublishLocal by tasks.registering {
204+
group = "csharp"
205+
description = "Pack and publish C# SDK library to local NuGet feed (~/.nuget/local-feed/)"
206+
207+
dependsOn(csharpPack)
208+
209+
val localFeed = file("${System.getProperty("user.home")}/.nuget/local-feed")
210+
211+
doLast {
212+
localFeed.mkdirs()
213+
csharpDir.resolve("dist").listFiles()
214+
?.filter { it.name.endsWith(".nupkg") }
215+
?.forEach { nupkg ->
216+
val target = localFeed.resolve(nupkg.name)
217+
nupkg.copyTo(target, overwrite = true)
218+
logger.lifecycle("Published ${nupkg.name} to ${localFeed.absolutePath}")
219+
}
220+
}
221+
}
222+
204223
// Wire into the main publish task only when the NuGet API key is available
205224
if (project.hasProperty("nugetApiKey")) {
206225
tasks.named("publish") {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net10.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
9+
<!-- NuGet package metadata -->
10+
<IsPackable>true</IsPackable>
11+
<PackAsTool>true</PackAsTool>
12+
<ToolCommandName>rewrite-csharp</ToolCommandName>
13+
<PackageId>OpenRewrite.CSharp.Tool</PackageId>
14+
<Version>0.0.0</Version>
15+
<Authors>Moderne</Authors>
16+
<Description>CLI tool for OpenRewrite C# language support (RPC server)</Description>
17+
<PackageProjectUrl>https://docs.openrewrite.org</PackageProjectUrl>
18+
<RepositoryUrl>https://github.com/openrewrite/rewrite</RepositoryUrl>
19+
<PackageTags>openrewrite;refactoring;csharp;dotnet</PackageTags>
20+
<NoPackageAnalysis>true</NoPackageAnalysis>
21+
</PropertyGroup>
22+
23+
<ItemGroup>
24+
<ProjectReference Include="../OpenRewrite/OpenRewrite.csproj" />
25+
</ItemGroup>
26+
27+
</Project>
File renamed without changes.

rewrite-csharp/csharp/OpenRewrite.sln

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ VisualStudioVersion = 17.0.31903.59
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenRewrite", "OpenRewrite\OpenRewrite.csproj", "{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}"
77
EndProject
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenRewrite.Tool", "OpenRewrite.Tool\OpenRewrite.Tool.csproj", "{B2C3D4E5-F6A7-8901-BCDE-F12345678901}"
9+
EndProject
810
Global
911
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1012
Debug|Any CPU = Debug|Any CPU
@@ -15,6 +17,10 @@ Global
1517
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|Any CPU.Build.0 = Debug|Any CPU
1618
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|Any CPU.ActiveCfg = Release|Any CPU
1719
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|Any CPU.Build.0 = Release|Any CPU
20+
{B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21+
{B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Debug|Any CPU.Build.0 = Debug|Any CPU
22+
{B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Release|Any CPU.ActiveCfg = Release|Any CPU
23+
{B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Release|Any CPU.Build.0 = Release|Any CPU
1824
EndGlobalSection
1925
GlobalSection(SolutionProperties) = preSolution
2026
HideSolutionNode = FALSE

rewrite-csharp/csharp/OpenRewrite/OpenRewrite.csproj

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<OutputType>Exe</OutputType>
54
<TargetFramework>net10.0</TargetFramework>
65
<ImplicitUsings>enable</ImplicitUsings>
76
<Nullable>enable</Nullable>
8-
<GenerateProgramFile>false</GenerateProgramFile>
97

108
<!-- NuGet package metadata (IsPackable overrides Microsoft.NET.Test.Sdk default) -->
119
<IsPackable>true</IsPackable>
12-
<PackAsTool>true</PackAsTool>
13-
<ToolCommandName>rewrite-csharp</ToolCommandName>
1410
<PackageId>OpenRewrite.CSharp</PackageId>
1511
<Version>0.0.0</Version>
1612
<Authors>Moderne</Authors>

0 commit comments

Comments
 (0)