We are currently in the process of migrating our .NET 4.7.1 projects from NuGet packages.config to the new PackageReference system. This changes a few things. For example, included NuGet packages are no longer located in a packages folder relative to the solution, but in a global location, for example, D:\DATA\packages on my workstation.
Our projects also use PostSharp (https://www.postsharp.net/), which extends the MSBuild-based build process to post-process assemblies. That means the assembly generated by C# compiler is partially rewritten by PostSharp afterwards. You can find indication of this integration in NuGet's artifacts under /src/Lib/obj/Lib.csproj.nuget.g.props and /src/Lib/obj/Lib.csproj.nuget.g.targets. There you can see that a PostSharp-specific targets file PostSharp.targets is included. This file is taken from the global packages location D:\DATA\packages.
/src/Lib/obj/Lib.csproj.nuget.g.props
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="(- BROKEN LINK -)">
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">D:\Demo\src\Lib\obj\project.assets.json</ProjectAssetsFile>
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">D:\DATA\Packages</NuGetPackageRoot>
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">D:\DATA\Packages</NuGetPackageFolders>
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">4.6.0</NuGetToolVersion>
</PropertyGroup>
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
</PropertyGroup>
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)\postsharp\5.0.45\build\PostSharp.props" Condition="Exists('$(NuGetPackageRoot)\postsharp\5.0.45\build\PostSharp.props')" />
</ImportGroup>
</Project>
Now, building and testing via NCrunch works well on my local machine, but fails when using a Grid Node Server. On the Grid Node Server the PostSharp-specific post-build targets are not run, which causes the test to fail, because PostSharp didn’t rewrote the NotNullAttribute in my sample code.
I looked at the workspace used on the Grid Node Server and I suspect that there is a small re-configuration missing to make this work correctly. In my understanding NCrunch copies NuGet packages to the Grid Node Server into location <snapshot-dir>\.nuget, this is located at D:\Snapshots\.nuget on our server.
Now, the Grid Node Server workspace containing our project contains everything necessary, even the NuGet specific artifacts project.assets.json, Lib.csproj.nuget.g.targets and Lib.csproj.nuget.g.props. But looking at Lib.csproj.nuget.g.props we can find the culprit for our problem. The file still contains
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">D:\DATA\Packages</NuGetPackageRoot>
which refers to the location on my workstation, but doesn’t make sense on the Grid Node Server.
Since third-party (PostSharp) props and targets are included via
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)\postsharp\5.0.45\build\PostSharp.props" Condition="Exists('$(NuGetPackageRoot)\postsharp\5.0.45\build\PostSharp.props')" />
</ImportGroup>
using $(NuGetPackageRoot) a wrong folder location is used on Grid Node Servers.
Is my analysis correct, or did you provide MSBuid property NuGetPackageRoot via command line when building?
A sample project can be found here: https://www.zipshare.com/download/eyJhcmNoaXZlSWQiOiI1M2Y0NTZjMy04MWEyLTQ0MWMtOTc5Yy02NjRhNWE2MjJhNTciLCJlbWFpbCI6Im9sYWYua29iZXJAYW50b24tcGFhci5jb20ifQ==