Discovering NuGet packages for assembly references

Topics: General
Apr 9, 2013 at 6:30 PM
Consider a system that consists of 30+ solutions and hundreds of projects. Several years ago, one would have a "lib" folder or equivalent where 3rd library modules were stored. Now consider the need to migrate those libraries to NuGet.

Manually one would delete a module in the "lib" folder, build all the solutions and find missing references. One would then add NuGet packages for each of the missing references. There is a risk that one may replace the module with an newer version that is incompatible with the one being replaced.

It may be more reliable and convenient to automate the process. Thus, the process may look as follows:
  1. A user selects a "Discover Packages" for a given project.
  2. For each reference, if the reference already comes from a nuget package, ignore it.
  3. Otherwise, for that reference, search the NuGet repositories for an assembly with that version, if found, remove the reference and add the NuGet package to the project.
Running such a discovery process on a whole solution with tens of projects may greatly reduce the time and effort to migrate existing libraries from a "lib" folder to NuGet packages. Keep in mind that some modules in the "lib" folder isn't in NuGet yet, but may become available in the future. So it would be a good maintenance tool.
Apr 12, 2013 at 4:09 PM
A few of our enterprise users requested this feature for ProGet Client Tools. One had even developed a proof of concept script that did this (mostly adding to packages.config, then letting ProGet sync the packages).

However, after some analysis we now strongly advise against automating this process, even when with ProGet Client's conservative dependency resolution, opt-outs, and no binding redirects. The primary reason is that it introduces far too much risk for virtually no gain (the "lib" folder works fine, it's just ugly and inconvenient). And goes far beyond "breaking the projects and wasting everyone's time".

Remember that you have absolutely no assurance that the package you're requesting from is the package you actually want. There is no validation or verification, and thus many packages are not "official" (i.e. uploaded/maintained by the actual project author) and for all you know, that random pdf library that's auto added to your project could have a backdoor that sends credit-card looking information to a server in china.

So, our advice is to suck it up, validate each package you add by hand, and slowly transition your project to NuGet.
Apr 12, 2013 at 4:20 PM
Edited Apr 13, 2013 at 12:37 AM
Having a tool to assist the discovery across the solution, in particularly large ones, allows one to evaluate the packages once, approve them once and then replace existing references with the package. I do not see the risk in that.

Further, many enterprises use private repositories to prevent developers from using unauthorised packages. And usually, its these organisations that have large solutions and can benefit the most from such a discovery feature.

Project breakage is likely if you do this without giving it much thought, which is actually more likely when you "suck it up" and doing it manually. Manual labour doesn't guarantee a better quality process or product.
Apr 12, 2013 at 4:25 PM
Edited Apr 12, 2013 at 4:27 PM
Good point, I should have contextualized that with "going directly to", which is what what our enterprise users were looking for... since they didn't know what dependencies their devs have put in /lib over the years. But if you already have the package in a private repository -- then that's a totally different story.

The manual process is absolutely necessary, however, in validating the packages you pull from (and what I meant by "suck it up").
Apr 13, 2013 at 10:27 AM
I wrote a tool to do exactly this as part of NuGet.Extensions :

Its (imaginatively) called "nugetify". It does most of what you want, however it:

1) Is currently only built against NuGet 1.7 (not a real problem as you can run multiple versions of NuGet side-by-side)
2) Does not constrain to version.

The constrain to version thing can be fixed in part by using another tool in the NuGet.Extensions set called "findassembly". You can run this against your lib directory, and it will tell you which packages contain the assemblies in the directory. You can then stage the correct version once you know the package (again, theres a command for that called "clone") and you will then have the right versions on an internal feed.

It is then a case of calling "nugetify" on the solutions one by one, and checking the package resolution is correct.

We have done literally hundreds of solution upgrade from a central lib directory to using NuGet, and once we had this tool it became pretty trivial.