Versioning and releasing multiple assemblies and their NuGet packages


#1

I have run into an issue with assembly versions vs. NuGet package versions and dealing with multiple assemblies (versioned differently) within a single package. I am sure this is a common issue, but I haven’t found any good solution, so I am hoping we can provide some guidance around this scenario. Let me explain.

Prism has a core PCL that is shared across all supported platforms. Prism supports 3 platforms and has a different NuGet package for each platform; UWP, Xamarin.Forms, and WPF. Prism also has support for different DI containers and uses the same NuGet packages for each platform but each assembly is versioned differently.

Let me see if I can clarify this a little:

  • Prism.Core.dll is a PCL that ships in the Prism.Core NuGetPackage. This assembly is versioned separately from the other assemblies n the overall product.
  • Prism.Wpf.dll is in the Prism.WPF NuGet package.
  • Prism.Windows.dll is in the Prism.Windows NuGet package.
  • Prism.Forms.dll is in the Prism.Forms NuGet package.

So far so good. nothing really complicated yet. But now, let’s introduce the support DI container packages.

  • Prism.Unity NuGet package has different assemblies for each platform and has dependencies on the platform specific packages mentioned above as well as the Prism.Core package.
  • Prism.Unity.Wpf.dll
  • Prism.Unity.Forms.dll
  • Prism.Unity.Windows.dll

Now, here is the issue. Let’s say that we have these versions:

Prism.Core.dll v1.0.0
Prism.Wpf.dll v1.2.1
Prism.Unity.Wpf.dll v3.0.0
Prism.Forms.dll v2.2.0
Prism.Unity.Forms v2.0.1
etc…

As you can see each assembly can be versioned differently. So how do we update the NuGet packages when only one assembly changes? We have a major issue trying to increment the NuGet package version, when only one assembly in the package has updated.

For example, let’s say that the PrismUnity.Forms.dll got a bug fix and went to v2.0.2, but the current Prism.Unity NuGet package is versioned at v3.0.0 because of the update to the Prism.Unity.Wpf.dll assembly. Also, when the Prism.Unity package it updated, it’s dependencies must be updated, and any other platform will be prompted for an update, even though that platform assembly may not have changed.

So the question is, how do you recommend versioning Nuget packages when it contains differently versioned assemblies for different platforms. Do we just increment the version of every assembly in the package to be in sync even though nothing may have changed in the code for that assembly?

I hope I explained that well enough. If not, please ask any clarifying questions.

Any ideas?


#2

I read that Prism.Unity is a high-level package that has dependencies on all of the other packages. Presumably, there are changes to the lower-level packages that don’t affect Prism.Unity directly, so Prism.Unity doesn’t need to change. In other cases, Prism.Unity will want to take a dependency on a change in one of more of the lower-level packages, and one or more of the Prism.Unity assemblies will also update. The question is whether assemblies that were not updated also need to change because the NuGet package is being updated. I don’t see why. Is anything breaking if you don’t update those assemblies?

JFYI: This isn’t really a ‘Governance’ topic. Governance is more about how the .NET Foundation functions as a foundation. So, elections would be an example.


#3

Actually, the dependencies are not the issue. Although, NuGet will not bring down a newer package with an install. For example; if Prism.Unity has a dependency on Prism.WPF v1.0 and then I updated Prism.WPF to v1.2; when I install the Prism.Unity package it will still only bring down Prism.WPF v1.0. But, that’s an issue with NuGet.

The heart of the issue is that the Prism.Unity package has 3 different platform assemblies which are all versioned differently. When only one of those assemblies update, how do you manage the NuGet package version?

Here is a scenario: let’s say the PrismUnity NuGet package is currently v3.0.0 and contains these assemblies

Prism.Unity.Wpf.dl v3.0.0
Prism.Unity.Windows v1.0.0
Prism.Unity.Forms v2.0.0

Notice how all assemblies are versioned differently. This makes sense, because not every assembly gets an update or bug fix.

Now, let’s say that we make an update to Prism.Unity.Windows and increment it to v2.0.0. What is the new package version?

Since developers always associate the NuGet package version to a direct match to an assembly version, this makes for a very confusing situation. Also, when we only update one assembly and publish a new package, the other platforms get prompted for an update even though they didn’t actually change.

What does everyone else do?

FYI: I changed the category :smile:


#4

You’ve really got a confusing block of packages and support verticals there before we even look at the version numbers. Am I understanding correctly that I need to choose a DI platform and a UI framework before I can decide which Prism top-level package to install? While that delivers a nice collection of thin packages with a cool dependency resolution graph, is that something that your average or below average developer is going to be able to navigate from a NuGet search?

I don’t think there is always a direct correlation between package version and library version. In the case of the “fat package” that you are describing that contains multiple DLLs, it would be preferred if they were all in sync with the version number of the package. However, I don’t think that’s realistic in all situations. This leads to a semver discussion: if you are updating Prism.Unity.Windows.dll to v2 - what breaking API change did you make? You should flag that to your package consumers that a breaking API change was made to one of the component libraries, driving the package version to 4.0.0 …and now things are skewing even further.

Is it realistic to make a breaking API change in Windows and NOT in Forms or WPF? Perhaps, but that is for you to manage.

In the case of ASP.NET, we are aligning all DLLs and packages versions on every release. That way there is no confusion, even if there are no changes, they are all pushed to the same version number with proper dependency constraints defined in the NuGet package to ensure that appropriate dependent packages are installed with the new package release.


#5

Your UI framework is chosen when you open VS and say File -> New. You do need to choose your preferred DI container though. (Unity, SturctureMap, Ninject, etc). This is why we want one single container package. So if you wanted to use Unity as your container, you would just add Prism.Unity and no matter what UI platform you are writing for, you get the correct version. What we don’t want to do is have a separate package for each platform for each container just for versioning (Prism.Unity.WPf, Prism.Unity.UWP, Prism.Unity.Forms, etc). Now image the same thing for the other five supported containers. Ouch!

Yes, it is realistic for a breaking change to happen in Forms and not WPF. These assemblies are specific to the platform, so some changes will never happen in one platform that may happen in another.

So it seems that reving them all to be the same is probably the best solution in this situation. Even in the case of breaking changes in one assembly and not in the other. We will just have to be clear in our release notes.

It also doesn’t help that NuGet don’t show the assemblies being referenced. Instead it just shows a package in the project References. Now there is no easy way to see what version the assemblies are in the referenced NuGet package.


.NET Foundation Website | Blog | Projects | Code of Conduct