Build/Test Issues

Azure Function Project Build Fails in NCrunch Only

Started by Careidas77 on 4,866 views

Since a week or so, one project in a solution I have (Visual Studio 2022 Enterprise) has started to fail after changing Visual Studio version from Pro to Enterprise. I don't imagine this in itself affects NCrunch, but I had to reinstall both VS and NCrunch and maybe som new SDK or whatever was added or uppdated in the process. Anyway, the NCrunch build fails with this error:

..\..\..\..\Program Files\dotnet\sdk\7.0.200\Sdks\Microsoft.NET.Sdk\targets\Microsoft.PackageDependencyResolution.targets (266, 5): The "ResolvePackageAssets" task failed unexpectedly.
System.InvalidCastException: [A]NuGet.ProjectModel.LockFile cannot be cast to NuGet.ProjectModel.LockFile. Type A originates from 'NuGet.ProjectModel, Version=6.3.2.9, Culture=neutral, PublicKeyToken=31bf3856ad364e35' in the context 'LoadFrom' at location 'C:\Program Files\dotnet\sdk\6.0.406\Sdks\Microsoft.NET.Sdk\tools\net472\NuGet.ProjectModel.dll'. Type B originates from 'NuGet.ProjectModel, Version=6.5.0.136, Culture=neutral, PublicKeyToken=31bf3856ad364e35' in the context 'LoadFrom' at location 'C:\Program Files\dotnet\sdk\7.0.200\Sdks\Microsoft.NET.Sdk\tools\net472\NuGet.ProjectModel.dll'.
at Microsoft.NET.Build.Tasks.LockFileCache.GetLockFile(String path)
at Microsoft.NET.Build.Tasks.ResolvePackageAssets.CacheWriter..ctor(ResolvePackageAssets task)
at Microsoft.NET.Build.Tasks.ResolvePackageAssets.CacheReader.CreateReaderFromDisk(ResolvePackageAssets task, Byte[] settingsHash)
at Microsoft.NET.Build.Tasks.ResolvePackageAssets.CacheReader..ctor(ResolvePackageAssets task)
at Microsoft.NET.Build.Tasks.ResolvePackageAssets.ReadItemGroups()
at Microsoft.NET.Build.Tasks.ResolvePackageAssets.ExecuteCore()
at Microsoft.NET.Build.Tasks.TaskBase.Execute()
at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext()


All other building attempts (DevOps, local etc.) work fine - it's only the NCrunch build that fails.

I have a global.json file that specifies the SDK to be 6.0.100. Allowing roll-forward or completely removing the global.json file makes everything compile with NCrunch again. There's nothing in the solution itself, as far as I can tell that targets the 7.0.200 SDK version. In fact, originally the latest SDK available in my system was v.7.0.102, and the error message was reflecting this. After installing the latest SDK version, the error message followed to reflect this change as well.

Hence, I gather "something" is ignoring the global.json resolving the latest available SDK in the system, which happens to clash with the SDK 6 version specified in the global.json file.

This problem only occurs specifically in one project in the solution, that is an Azure Function project. All other projects are building just fine, in the same solution.

All projects in the solution are targeting dotnet 6.

Edited

Hi, thanks for sharing this issue.

Could you confirm for me if this is a project load issue (under NCrunch) or a project build issue?

Also, could you submit a bug report after the issue appears? The log may yield some useful information about what is happening under the hood.
Hi, thanks for getting back to me :)

It's reported by NCrunch to be a status = build failure. I submitted a report, as requested. Named it "Build failure in 'ResolvePackageAssets'" and put a link to this thread as reference.
Thanks for sending through the bug report. Could you try adding your global.json file to your NCrunch solution-level 'Additional files to include' setting and let me know if this makes any difference?

Also - can you confirm if this build issue appears every time for this particular project? Or does it seem to be intermittent and the project still manages to occasionally build?
The build fails every time. It does not seem to be (hasn't been so far) an intermittent problem. Including the global.json file through the "Additional files to include" option does not have any visual impact. The problem persists - build fails - and the error message and stack trace remains identical each time the build fails, both before and after adding the global.json file to NCrunch.

I also tried re-initializing NCrunch after adding the global.json file, but to no avail.

Edited

Thanks for these extra details.

From the log, it's not clear to me why MSBuild is using the wrong version of the platform when building this project inside the NCrunch workspace.

Are you able to reproduce this issue in a small stripped-down project that you can share with me? If I can get it to happen in my environment, I should be able to figure out what's going on here. You can submit zipped projects and solutions to me through the NCrunch contact form.
I will give it a shot. Can I try anything else that would enlighten us, if I can't reproduce the error in an isolated solution?
Careidas77 wrote:I will give it a shot. Can I try anything else that would enlighten us, if I can't reproduce the error in an isolated solution?


I don't have any suggestions right now in terms of settings or configuration. The next step is to start pulling apart your build to try and understand why it's behaving in this way. If we can't get a sample solution that reproduces this, we'll need to start trying to get more information about what your build is doing (i.e. extracting more detailed logs than the bug report will give us out of the box).
I managed to get a "working" minimum example together, that reproduces the error (at least for me f(^_ ^); I uploaded a zip file with a solution.
Careidas77 wrote:I managed to get a "working" minimum example together, that reproduces the error (at least for me f(^_ ^); I uploaded a zip file with a solution.


Nice work! For some reason it didn't come through on my side .. did the form give you confirmation? Is the zipped size under 10MB? (You can split it up if you have to)
I tried resubmitting the zip file through the form under Support - Contact, but when I hit submit, I end up on a 404 page -> https://www.ncrunch.net/error/http404

What can I do instead?
Careidas77 wrote:I tried resubmitting the zip file through the form under Support - Contact, but when I hit submit, I end up on a 404 page -> https://www.ncrunch.net/error/http404

What can I do instead?


This tends to happen if it's over the 10MB limit (sorry, this thing needs an upgrade).

Are you able to split it into smaller packages, or maybe submit it without derived binaries?
I see. Kind of my bad, i guess f(^_^); - removed the obj and bin folders and resubmitted only 14 KB zipped project files. Thanks for the feedback!

Edited

Careidas77 wrote:I see. Kind of my bad, i guess f(^_^); - removed the obj and bin folders and resubmitted only 14 KB zipped project files. Thanks for the feedback!


Thanks! I've received the package and reproduced the problem exactly as you've described. I'll need to pull this thing apart. I'll let you know when I have more information.
Thanks for your patience with this issue. I've managed to more or less get to the bottom of it now, and although I haven't yet found a way to resolve the problem in the NCrunch codebase, there is a solid workaround you can use.

In your NCrunch 'Custom environment variables' setting, you need to set two environment variables:
DOTNET_MSBUILD_SDK_RESOLVER_SDKS_DIR = C:\Program Files\dotnet\sdk\6.0.100\Sdks (or the equivalent 'Sdks' directory for the dotnet SDK you are targeting)
DOTNET_MSBUILD_SDK_RESOLVER_SDKS_VER = 6.0.100 (or the equivalent version to match the above environment variable)

This will force MSBuild to resolve the dotnet SDK according to your chosen version, disregarding other logic.

The root of the issue is a component inside MSBuild/VS called Microsoft.DotNet.MSBuildSdkResolver. This component implements logic that considers a range of variables including preview SDKs, configuration files, VS, and the global.json file. The component has a special super magic check that performs a memory test to see if Visual Studio is responsible for the build. If so, it behaves differently. We don't have a feasible way to fake the memory test and the environment variables above are the only way to override the behaviour. We could probably duplicate the behaviour of this component under NCrunch (by parsing the global.json file) and performing the SDK selection ourselves by overriding the environment variables (which actually we do already for some specific cases), but the problem with this approach is that MS change the component all the time and we can't guarantee we'll get it right for all versions.

So in summary, if you're using global.json to specify an SDK version and NCrunch isn't rolling well with it, just specify the above environment variables. This is the best way to ensure a correct result in the build.
Thank you for the info - no worries :) Your software is so awesome, and I think your support turnaround is excellent as well.

I'll use the workaround. Is there somewhere I can keep track of the releases to understand if there will eventually a fix will be released? Not that I actually need it if the workaround works - like you said, it's a pretty solid one.

For information (I think you already know and understand this, but anyway): The global.json file mostly exists to support CI/CD.
Careidas77 wrote:Thank you for the info - no worries :) Your software is so awesome, and I think your support turnaround is excellent as well.

Thanks :)

Careidas77 wrote:
I'll use the workaround. Is there somewhere I can keep track of the releases to understand if there will eventually a fix will be released? Not that I actually need it if the workaround works - like you said, it's a pretty solid one.


We try to be very thorough with the release notes in each build. I realise skimming them is a pain, but if we do implement a fix for this, it'll definitely be in the notes.

Careidas77 wrote:
For information (I think you already know and understand this, but anyway): The global.json file mostly exists to support CI/CD.



The environment variable workaround should also work for the NCrunch console tool. If you use the shared version of the 'Custom environment variables' setting, it should automatically be picked up by the console tool as the setting will be shared.
I'm not sure I understand the mechanics behind setting the env variables with NCrunch, as suggested. Am I to understand that this setting, when done using the NCrunch Configuration tool > General > Custom environment variables affects all instances of NCrunch? It's certainly had that effect with my current attempt.

Since I contribute to several different projects, in turn using diffferent dotnet SDKs, I kind of need to be able to configure this setting project-locally, to target different SDKs with NCrunch builds as well, for different solutions (what global.json is meant to achieve).

Does setting this environment variable in the manner described also affect MSBuild on an OS global level, or what is the actual scope? NCrunch-global?

Remco wrote:
The environment variable workaround should also work for the NCrunch console tool. If you use the shared version of the 'Custom environment variables' setting, it should automatically be picked up by the console tool as the setting will be shared.

Your comment suggest to me that the above mentioned project-local setting should be possible, i.e. there's a "shared version" and some "local version" of the environment variables setting, but I don't know how to handle that. Can you explain what I need to do, or point me to the correct section in the documentation, please?

Edited


Your comment suggest to me that the above mentioned project-local setting should be possible, i.e. there's a "shared version" and some "local version" of the environment variables setting, but I don't know how to handle that. Can you explain what I need to do, or point me to the correct section in the documentation, please?


Sorry, I should have clarified. I get so used to working in advanced configuration mode that I tend to forget the simple mode is on by default. Inside the configuration windows you'll see a checkbox at the top for 'Use Simplified Configuration Settings'. Turn this off, and you'll be able to set this at solution level so it won't affect your other projects.

Post a reply

Log in to reply.