Wednesday, July 22, 2015

Ingredients for well-designed OWIN middleware components - Part 5

In the fourth installment of this series I proposed a pattern for postponing expensive operations from inside your middleware component until the OWIN pipeline has been constructed. In this post, I'm going to talk about aligning package dependency versions. Why? Well, in my experience a well-designed middleware component may end up resulting in more than a single NuGet package. 

Ingredient 6: Automatic package version alignment
I'm not talking about its public dependencies (which you've obviously internalized), but about other output from the same solution. For instance, imagine your middleware component supports extension points or external services in the form of an IPlugin or IWhateverDependency that you can pass through your component's settings:

public class MyPlugin : IPlugin

appBuilder.UsePiercer(new PiercerSettings().Using(new MyPlugin());

Now, you could include the contract of those extensions, the IExtension interface, as part of the NuGet package that brings in the middleware component. But as an extension developer, that would require you to directly reference the middleware component. If you carefully design your component, I would put that extension interface in a dedicated NuGet package post-fixed with Extensions or something alike.

Assuming you use automatic versioning through GitVersion like I did in Piercer, you then have the problem of NuGet dependencies to solve. Since your middleware needs to take an implementation of the extension interface, it needs a dependency on the NuGet package that exposes the dependency. In Piercer I already demonstrated how to automatically version the assemblies using GitVersion, but that doesn't adopt the versions of the extensions package in the .nupec of the middleware package. As I assume you don't want to update the .nuspec manually, I wrote a little PSake task you can use in your build script.

task ConsolidateNuspecDeps {

  Write-Host "Updating all NuGet dependencies on $NuGetPackageBaseName.* to version ""$NuGetVersion""" {
    Get-ChildItem $SrcDir -Recurse -Include *.nuspec | % {

      $nuspecFile = $_.fullName;
      Write-Host "    $nuspecFile updated"
      $tmpFile = $nuspecFile + ".tmp"
      Get-Content $nuspecFile | `
          %{$_ -replace "(", "`${1} version=""$NuGetVersion""/>" } | `
      Out-File -Encoding UTF8 $tmpFile
      Move-Item $tmpFile $nuspecFile -force

It will take two Powershell variables; $NuGetPackageBaseName to identity the items from the .nuspec's element that are part of the same set, and the $NuGetVersion to use for the final version. Notice that if you don't want to use specific versions, you're free to use a range like [1.0, 2.0) instead.