TFS Build and the Missing Newtonsoft
I do not normally create or edit the builds for my team. So this was a fun adventure, creating a simple build.
I used a picture of an amethyst on my desk for this post because I feel it represents how I felt about this endeavor. On the surface it seemed so simple, but if you go deeper it can get complex. Much like crystals.
This is not a post on how to use TFS. TFS is very powerful and flexible, you need more than a blog to learn it. Like most of my posts this is focused on one specific problem.
I needed to create a build for a solution of console applications. It seemed really simple, build the solution and copy the debug folder to one of our UAT servers.
Not So Simple
I really thought this would be simple. I started on my new build definition and added the tasks I thought would get the job done.
- Get sources
- Visual Studio Build
- Windows Machine File Copy for each console application in the solution
Get sources handles your mapping from TFS to your build server (server path to Local path under $(build.sourcesDirectory). I want to point this out for something that is used later. In my case the actual solution (sln) file is in one place as it is part of a greater project, and the source is in another sub folder.
I had to add two mappings; the sln and the source. The project lead suggested that is it always best to keep the naming to be close to what is in TFS. I mapped the sln to CORP.Project.SubProject.Applications.sln. I mapped the source folder to CORP.Project.SubProject.Applications
The Problem Appears
The problem that appeared seemed simple enough. In the form of a warning, and as an error.
- Warning MSB3245: Could not resolve this reference. Could not locate the assembly “Newtonsoft.Json, Version=22.214.171.124, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL”. Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.
- Error CS0246: The type or namespace name ‘Newtonsoft’ could not be found (are you missing a using directive or an assembly reference?)
I checked my source and sure enough I had Newtonsoft in my references. Of course I knew it worked locally. When I built the applications locally I could run them on other machines. So obviously I build server needed something more.
NugetRestore Task to the Rescue?
Before I go on I should address some basic items in the Get sources task, specifically the mapping. For this solution
This task has a few fields, but only a couple are required. So I only filled in the required fields. I used the path to the sln file based on the $(build.sourcesDirectory) variable; $(build.sourcesDirectory)\CORP.Project.SubProject.Applications.sln. I had it use NuGet.org and disabled local cache. I did not put in a destination directory.
The build failed with the same errors. Of course I did some searching and the solution and the answer was basically to restore the packages or put them on the server.
For me the fix was to set that destination folder, and set it properly. I tried a few directory settings but the one that worked was to use $(build.sourcesDirectory)\packages
After that the whole process worked perfectly.