Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to enforce same nuget package version across multiple c# projects?

Tags:

c#

nuget

I have a bunch of small C# projects which use a couple of NuGet packages. I'd like to be able to update version of a given package automatically. More then that: I'd like to be warned if a project uses different version from the others.

How do I enforce same version dependency across multiple C# projects?

like image 917
Igor Gatis Avatar asked Nov 07 '14 01:11

Igor Gatis


People also ask

How do I consolidate a NuGet package?

Click on “Manage NuGet Packages for Solution…” to open a slightly extended dialog to manage your NuGet packages: Browse, Installed and Updates work like the menus in the “default” NuGet packages dialog but contain all projects of this solution. The big addition is the Consolidate tab.

Can a NuGet package contain multiple projects?

If you have more than one project in VS and your Pack file is dependant on another project then both need to be packed. Pack the dependency first, then pack your project. When adding the package using NuGet Package manager make sure your source is not nuget.org but instead your testing folder.


1 Answers

As I haven't found another way to enforce this, I've written a unit test which will fail if different package versions are being found in any packages.config in any subfolder. As this might be useful for others, you'll find the code below. You'll have to adapt the resolution of the root folder done in GetBackendDirectoryPath().

using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Xml;  using NUnit.Framework;  namespace Base.Test.Unit {     [TestFixture]     public class NugetTest     {         private const string PACKAGES_CONFIG_FILE_NAME = "packages.config";         private const string BACKEND_DIRECTORY_NAME = "DeviceCloud/";          private const string PACKAGES_NODE_NAME = "packages";         private const string PACKAGE_ID_ATTRIBUTE_NAME = "id";         private const string PACKAGE_VERSION_ATTRIBUTE_NAME = "version";          /// <summary>         /// Tests that all referenced nuget packages have the same version by doing:         /// - Get all packages.config files contained in the backend         /// - Retrieve the id and version of all packages         /// - Fail this test if any referenced package has referenced to more than one version accross projects         /// - Output a message mentioning the different versions for each package          /// </summary>         [Test]         public void EnforceCoherentReferences()         {             // Act             IDictionary<string, ICollection<PackageVersionItem>> packageVersionsById = new Dictionary<string, ICollection<PackageVersionItem>>();             foreach (string packagesConfigFilePath in GetAllPackagesConfigFilePaths())             {                 var doc = new XmlDocument();                 doc.Load(packagesConfigFilePath);                  XmlNode packagesNode = doc.SelectSingleNode(PACKAGES_NODE_NAME);                 if (packagesNode != null && packagesNode.HasChildNodes)                 {                     foreach (var packageNode in packagesNode.ChildNodes.Cast<XmlNode>())                     {                         if (packageNode.Attributes == null)                         {                             continue;                         }                          string packageId = packageNode.Attributes[PACKAGE_ID_ATTRIBUTE_NAME].Value;                         string packageVersion = packageNode.Attributes[PACKAGE_VERSION_ATTRIBUTE_NAME].Value;                          if (!packageVersionsById.TryGetValue(packageId, out ICollection<PackageVersionItem> packageVersions))                         {                             packageVersions = new List<PackageVersionItem>();                             packageVersionsById.Add(packageId, packageVersions);                         }                          //if (!packageVersions.Contains(packageVersion))                         if(!packageVersions.Any(o=>o.Version.Equals(packageVersion)))                         {                             packageVersions.Add(new PackageVersionItem()                             {                                 SourceFile = packagesConfigFilePath,                                 Version = packageVersion                             });                         }                          if (packageVersions.Count > 1)                         {                             //breakpoint to examine package source                         }                     }                 }             }              List<KeyValuePair<string, ICollection<PackageVersionItem>>> packagesWithIncoherentVersions = packageVersionsById.Where(kv => kv.Value.Count > 1).ToList();              // Assert             string errorMessage = string.Empty;             if (packagesWithIncoherentVersions.Any())             {                 errorMessage = $"Some referenced packages have incoherent versions. Please fix them by adapting the nuget reference:{Environment.NewLine}";                 foreach (var packagesWithIncoherentVersion in packagesWithIncoherentVersions)                 {                     string packageName = packagesWithIncoherentVersion.Key;                     string packageVersions = string.Join("\n  ", packagesWithIncoherentVersion.Value);                     errorMessage += $"{packageName}:\n  {packageVersions}\n\n";                 }             }              Assert.IsTrue(packagesWithIncoherentVersions.Count == 0,errorMessage);             //Assert.IsEmpty(packagesWithIncoherentVersions, errorMessage);         }          private static IEnumerable<string> GetAllPackagesConfigFilePaths()         {             return Directory.GetFiles(GetBackendDirectoryPath(), PACKAGES_CONFIG_FILE_NAME, SearchOption.AllDirectories)                 .Where(o=>!o.Contains(".nuget"));         }          private static string GetBackendDirectoryPath()         {             string codeBase = Assembly.GetExecutingAssembly().CodeBase;             var uri = new UriBuilder(codeBase);             string path = Uri.UnescapeDataString(uri.Path);             return Path.GetDirectoryName(path.Substring(0, path.IndexOf(BACKEND_DIRECTORY_NAME, StringComparison.Ordinal) + BACKEND_DIRECTORY_NAME.Length));         }      }      public class PackageVersionItem     {         public string SourceFile { get; set; }         public string Version { get; set; }          public override string ToString()         {             return $"{Version} in {SourceFile}";         }     } } 
like image 71
Philippe Avatar answered Oct 04 '22 18:10

Philippe