Using NuGet in an automated build and branched environment - visual-studio-2010

We’re on a closed network without Internet access so we’re currently using a file share as a NuGet repository. We do a lot of merging between a development branch and a main branch and occasionally setup a one-off branch for a hotfix or large functionality that will extend beyond our normal release cycles.
What we’ve found is that when we add a NuGet package to a project it puts a file path in the .csproj file for where the package is located. This works fine until we merge into another branch in TFS and then kick off a build. The builds do not pull down the same files from source control (keeping dev and main completely separate in that regards) so the package path is not found and the build fails.
We’ve come up with one solution we know will work but is utterly painful and one proposed solution that we need to investigate further. One solution is to put the packages folder into a common location that every build will include in its workspace and manually modify each .csproj file to point to that location for its packages.
The solution we need to investigate is using NuGet without committing packages to source control. What we need to determine is if NuGet.exe will create the folder structure needed by the .csproj file to find the package.
Are there better solutions to using NuGet in a branching environment that uses automated builds?

What you could do is create a local NuGet repository that is reachable by http:// that can be easily used in both branch situations. Checkout how to create a local NuGet repository here

Related

How do I load code into a specified directory using Nuget?

I have the situation where our code base is like so:
/Gui/
/Product1/
/Calc engine/
/Core/
/Product2/
All of these projects are loaded into a Global solution file in Visual Studio.
I want to extract Core to it's own repo and allow different branches of this repo to load different versions of it. I cannot just use references to the binaries as engineers want to be able to debug the core code when running the Products so I have to be able to bring the entire Core codebase in.
Originally, I intended to use git submodules but I am investigating whether Nuget might be a better solution. I have removed /Core/ to it's own repo and created a Nuget package of the Core directory (it contains about 20 different C# projects).
Is there a way I can input this Nuget package into the Global Solution? It would need to put the code into the same directory as it used to rather than a package director.
Is there a way I can input this Nuget package into the Global Solution? It would need to put the code into the same directory as it used to rather than a package director.
You can change the Package Management to "Pakcage.config" in Options\Nuget Package Manager. The package will be stored in solution directory.
and right-click the solution in solution explorer then click "Manage Nuget Packages for Solution"

TFS check-in error: Could not find a part of the path

Our team works on a project with TFS as source control. Sometimes that I want to check-in some errors happen.
D:\CustomManager.1.0.7184.35750\lib\net461\CustomManager.dll: Could not find a part of the path 'D:\CustomManager.1.0.7184.35750\lib\net461\CustomManager.dll'.
I gotta go to the Packages folder and make a new folder. after that, I have to copy the previous version of the package in that and then rename it to solve the case. This way is a little annoying because sometimes after that, new errors will show with different versions.
Additional information: This error will only be shown when I update the NuGet packages.
Is there a simple way to fix this?
Seems you directly checked libraries(dlls) in to TFS and manage version control of them.
It's not a recommend way, there are multiple downsides such as it's never exactly clear which projects are using which versions of which assemblies. It's a maintenance nightmare.
Suggest you use Nuget to handle these libraries in TFS. You should compile your code, package it in Nuget and publish it. For multiple projects you can upgrade their nuget references when appropriate, or stick with the older versions if they need to. If you need to reference a known-good, stable version, you just make sure your project is configured to pull a specific version from NuGet.
TFS use Package Management that hosts NuGet, npm, and Maven packages alongside all your other TFS assets: source code, builds, releases, etc, also be able to handle the external packages.
You could add external packages to a TFS Package Management feed. When you restore the packages, select the feed. All need packages will be restored entirely. To achieve this, just use Push NuGet packages to specify the packages you want to publish and the target feed location.
More details please refer Get started with NuGet Package Management in TFS
Update:
Keep looking for old packages, this will not happen if you already referred the latest dll in project. Please double check this part.
In your situation, if you want to check the dll in source control, you should add dlls in the solution/project and use relative path. Otherwise, tfs server may not find path.
For cache issue, suggest you to clear TFS cache then restart VS, and check in again, this may do the trick.

This project references NuGet packages that are missing on this computer (TFS)

I'm using TFS for the first time and attempting a build. I'm getting the error:
This project references NuGet package(s) that are missing on this computer. use NuGet Package Restore to download them.
I realize that there are many similar posts on StackOverflow and I've searched through quite a few of them. What I've gathered is that the two boxes under Package Restore in Package Manager Settings should be checked (but that this is also irrelevant now because they're checked by default). I verified that mine were both checked anyway.
The next piece of advice I considered is deleting the /packages folder from the Source Control version of my application. There is no packages folder there OR in my local (pre migration to TFS) version of the application. Instead, there's a ../packages/ folder (up one level) from the application folder. It seems that, at some point, I've opted to store the packages for all of my applications in the same folder? If so, where is this setting and what do I need to change it to either in my local version or in Source Control Explorer?
Thanks!

Bundling non-Nuget packages in Bamboo

I have been trying to find an "elegant" way to integrate non-NuGet package with my Bamboo builds.
There's a plethora of stacks on the topic of adding non-NuGet packages into NuGet bundles:
managing non-nuget dlls along with nuget packages
Creating NuGet package with reference to a non-NuGet reference
Trying to add non-.NET libraries to NuGet package
and the list goes on. There's also many a stack about using NuGet in Bamboo and that part works smoothly.
None of these deal with the situation of having an automated build environment, which may be sitting on some other remote server, running Bamboo.
Specifically, I'm trying to automate Xamarin.iOS deployments to HockeyApp.
The steps are:
Coding and local testing in VS2015 on Windows and with Mac for iPhoneSimulator
Merge into deployment branch and push to Bitbucket server
Bamboo picks up the push and kicks off build
Build checks out deployment branch
Runs NuGet downloads
Starts compile for Ad-Hoc/iPhone environment, creating IPA
Kicks off the HockeyApp deployment (there's a free addon for that)
Nearly all the steps are in place, except for the one where I have 2 dependencies which the commercial vendor (Syncfusion) has for unknown reasons decided to bundle into their "Studio" product, from where my Visual Studio project/solution has to refer to them by location outside of my project directory.
As a result, my Bamboo build fails with not-found DLLs, because they're missing as they would have to come in somewhere between 5. and 6. above.
I don't want to copy the binaries and then check/commit/push them into my repository, as that's considered a Bad Thing. My Bamboo Plan already successfully grabs NuGet packages before the actual build without having to drag binaries along.
Simply copying the DLLs on to the Bamboo build machine (i.e. where the remote agent is running) was one idea, but the problem is that the VS/MSBuild project file now has hard-wired directories - so, I'd have to install the whole Syncfusion Studio, or emulate their directory structure just for those 2 DLLs.
So I would need to adjust the .csproj references in an automated fashion. Not sure how I would do that, except with Yet Another Task and Script.
Apart from yelling at Syncfusion (which I've already done) about making all their DLLs available through NuGet (because some are, and those I'm successfully receiving in step 5. above), does anybody have a suggestion how to get this missing step to work?
For expediency sake, I have now added the libraries to the repository in a separate sub-directory.
It's not how I wanted to do it, but as the 2 libraries were a mere 200-300KB each and as there just didn't seem to be a simpler solution it solved the issue for now.
Specifically:
Leave .dll in .gitignore
Copy libraries you need into local sub-directory, e.g. LocalLibs/
add specific libraries with git add -f LocalLibs/speciallib.dll so that only these become a part of the repo
Change the project reference in Visual Studio to point to the local libraries, instead of their main install location
Verify that builds still work from within Visual Studio but also with MSBuild
I may revisit this and update if a better way comes along, especially if the libraries are significantly larger, such that you definitely would not want to add them to your repository.

Can NuGet use per-project package download paths within the same solution?

Consider this repo/file structure for our solution...
Shared Repo (Checked out to D:/Shared/trunk)
├───Shared1.dll Project
└───Shared2.dll Project
App1 Repo (Checked out to C:/Code/App1/Trunk)
├───App1 Project (Refs Shared1.dll project)
├───App1.dll Project (Refs Shared1.dll and Shared2.dll projects)
└───App1.sln
App2 Repo (Checked out to C:/Code/App2/Trunk)
├───App2 Project (Refs Shared1.dll project)
├───App2a.dll Project (Refs Shared1.dll and Shared2.dll projects)
├───App2b.dll Project (Refs Shared1.dll and App2a.dll projects)
└───App2.sln
To make working with the code easier, we bring in the Shared projects directly into the application's solutions, meaning for instance if you open App1.sln, this would be your project tree...
App1.sln
├───Shared1.dll Project
├───Shared2.dll Project
├───App1 Project (Refs Shared1.dll project)
└───App1.dll Project (Refs Shared1.dll and Shared2.dll projects)
As you can see, the two Shared DLLs are from a separate repository but are included in this solution. Visual Studio handles this without any issue, prompting you that you are updating multiple repos when you perform a commit against the solution. That's fine and is exactly what we want.
The issue we're having however is with NuGet. From what we understand, the NuGet.config (and the hierarchy/precedence of reading/applying them) is relative to the solution file, and therefore the projects' NuGet references are updated accordingly. This causes issues in that the references to the NuGet packages in Shared1.dll an Shared2.dll are relative to App1.sln when you're working in App1.sln, meaning if someone else is working in App2.sln and hasn't checked out their two trunks relative to each other exactly the same way you have, the references break.
Our work-around for this is to always check out all three trunks into the same folder as siblings, then put the packaging folder as another sibling, adding '../packages' in the NuGet.config next to each solution. This ensures the references never break, but forces the location of the checkouts which can be a problem.
C:/Code/
├───Shared Trunk
├───App1 Trunk
├───App2 Trunk
└───packages
However, if we could specify per-project package download locations, we could put the packaging folders relative to the projects themselves meaning it wouldn't matter where you check them out to. They would always find the packages they need. Yes, this means that in our example, there would be duplicate package downloads, but space on disk isn't the issue. Maintenance of the code is.
C:/Code/
├───Shared Trunk
│ └─sharedpackages
├───App1 Trunk
│ └─app1packages
└───App2 Trunk
└─app2packages
Again, what we want is when opening App1.sln, we want packages for Shared1.dll and Shared2.dll to go in 'sharedpackages' folder but packages used by App1 and App1.dll to go in app1packages.
So... is this possible? Can you specify different NuGet package download paths per project regardless of which solution they are in?
I'm in the same situation as /u/MarquelV.
From my investigation insofar into the options provided by nuget (at least up to ver. 3.5) for tackling this sort of scenario, I concluded that one has to completely ignore the graphical tools for nuget inside Visual Studio (at least as far as installing/restoring packages is concerned) and to also disable automatic package restore (Tools -> Options -> Nuget etc). Then resort to invoking nuget.exe from the command line whenever the need arises to install/restore packages specifying the folder in which the packages should be placed - this point is important because the graphical interfaces for nuget in visual studio are bend on storing packages in a "global" repository (typically right next to the .sln file of the solution).
In my projects I create an .nuget folder coupled with nuget.exe inside each and every project and reference dlls thusly.
Last but not least each and every project needs to restore packages by using nuget via the .csproj like so:
<Target Name="BeforeBuild">
<Exec Command=".\.nuget\nuget.exe restore .\packages.config -PackagesDirectory .\packages"/>
</Target>
The thing to take away from all this is that the graphical tools for nuget and the automatic package restoration (Tools -> Options -> Nuget) cannot be relied upon in order to achieve the goals described here.
I recently faced a similar issue. In my case I was combining projects from smaller solutions into a larger one. The projects were still referencing the packages in their subfolders, and I did not want to change those references and break the smaller solutions. I was able to solve it by symlinking the project packages path to the solution-level path.
mklink /J .\packages ..\packages
This effectively tricks the project into thinking it is using a more local version of packages when it was actually using the one from the larger solution.
It's not exactly the same situation, but close enough that I hope it can help someone.

Resources