From 40138e63c8abd9251ba0914fc62f6f7d7007dd9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Breu=C3=9F?= Date: Fri, 15 May 2026 12:16:48 +0200 Subject: [PATCH] feat: Phase 5.5 wire meta-package to ship the analyzer as a dev-only NuGet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pre-5.5 the Testably.Abstractions.Migration nupkg was a 7K placeholder DLL with no analyzer payload — installing it did nothing. Source/Testably.Abstractions.Migration/Testably.Abstractions.Migration.csproj now declares the analyzer + codefix DLL paths as packed `` items into `analyzers/dotnet/cs/` so Roslyn auto-discovers them on install. Marked as a dev-only tool via DevelopmentDependency=true so NuGet does not propagate the package as a transitive dependency of consumers (auto-applies PrivateAssets=all on the consumer side). The empty placeholder lib DLL is intentionally retained: it satisfies NuGet's NU5017 ("no content") check which is elevated to an error by TreatWarningsAsErrors=true. Pack runs separately from build (Pipeline/Build.Pack.cs): - The meta-package csproj sets GeneratePackageOnBuild=false. Earlier iterations used ProjectReferences to the analyzer projects to ensure they were built before pack; that consistently created a duplicate MSBuild graph node for each analyzer under parallel CI builds (Linux + macOS), racing on bin/.../*.deps.json and failing GenerateDepsFile with "file in use". Aligning the property envelope via SetTargetFramework did not eliminate the race in practice. - Nuke's Pack target now invokes `dotnet pack --no-build` after Compile. Because Compile has already produced every analyzer DLL via the test / playground project references, Pack only needs to bundle the existing bin output — no additional builds are triggered, no race possible. - Pack runs against the .slnx (not the project) so $(SolutionDir) resolves for the README pack target; only the meta-package is IsPackable=true so it is the only project actually packed. The package intentionally does NOT add a PackageReference to Testably.Abstractions.Testing. The migration package is a one-shot tool (install → migrate → uninstall); pulling the target lib transitively would mask the missing reference until the user removes the migration package, at which point the migrated tests would stop compiling. Consumers must reference Testably.Abstractions.Testing themselves. --- Pipeline/Build.Pack.cs | 24 ++++++++++++ .../Testably.Abstractions.Migration.csproj | 38 +++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/Pipeline/Build.Pack.cs b/Pipeline/Build.Pack.cs index cc58dba..c7205e1 100644 --- a/Pipeline/Build.Pack.cs +++ b/Pipeline/Build.Pack.cs @@ -5,7 +5,9 @@ using Nuke.Common; using Nuke.Common.IO; using Nuke.Common.ProjectModel; +using Nuke.Common.Tools.DotNet; using Nuke.Common.Utilities.Collections; +using static Nuke.Common.Tools.DotNet.DotNetTasks; using static Serilog.Log; // ReSharper disable AllUnderscoreLocalParameterName @@ -59,6 +61,28 @@ partial class Build AbsolutePath packagesDirectory = ArtifactsDirectory / "Packages"; packagesDirectory.CreateOrCleanDirectory(); + // Pack the meta-package separately from the slnx build. The meta-package + // csproj disables GeneratePackageOnBuild because adding ProjectReferences + // to the analyzer projects from the meta-package was found to create a + // duplicate MSBuild graph node for those analyzers under parallel CI + // builds, racing on bin/.../deps.json files and failing GenerateDepsFile + // with "file in use". Packing here with NoBuild after Compile sidesteps + // the race entirely: the slnx build has already produced every analyzer + // DLL the meta-package needs to bundle into analyzers/dotnet/cs/. Pack + // runs against the .slnx (not the csproj) so $(SolutionDir) resolves for + // the README pack target; only the meta-package is IsPackable=true so it + // is the only project actually packed. + DotNetPack(s => s + .SetProject(Solution.Path) + .SetConfiguration(Configuration) + .EnableNoLogo() + .EnableNoRestore() + .EnableNoBuild() + .SetVersion(MainVersion.FileVersion + MainVersion.PreRelease) + .SetAssemblyVersion(MainVersion.FileVersion) + .SetFileVersion(MainVersion.FileVersion) + .SetInformationalVersion(MainVersion.InformationalVersion)); + List packages = new(); foreach (Project project in new[] { diff --git a/Source/Testably.Abstractions.Migration/Testably.Abstractions.Migration.csproj b/Source/Testably.Abstractions.Migration/Testably.Abstractions.Migration.csproj index 3efdca8..aa1514a 100644 --- a/Source/Testably.Abstractions.Migration/Testably.Abstractions.Migration.csproj +++ b/Source/Testably.Abstractions.Migration/Testably.Abstractions.Migration.csproj @@ -2,6 +2,44 @@ Testably.Abstractions.Migration + + true + + false + + + + + +