After my previous post on upgrading my project to compile with .NET Core, I found some unexpected issues compiling my NuGet package.

Previously, I’d used NuGet to do the packing of the package, using this task:

Task Compile.NuGet -Depends Requires.NuGet, Requires.BuildType,
        Requires.BuildDir, Compile.Assembly, Configure.PackagesFolder {

    $nugetFolder = join-path $packagesFolder Niche.CommandLine
    mkdir $nugetFolder | Out-Null

    $csprojFile = resolve-path .\src\Niche.CommandLine\Niche.CommandLine.csproj

    exec {
        & $nugetExe pack $csprojFile -version $semver10 
            -outputdirectory $packagesFolder -basePath $buildDir 
            -properties Configuration=$buildType
    }
}

Unfortunately, this approach broke in nasty ways after I’d updated the projects to .NET Core - there seems to be a nuget.exe incompatibility with the new .csproj format. Worse than that, the error message itself is completely unhelpful:

Unable to cast object of type 'System.String' to type 'NuGet.Frameworks.NuGetFramework'.

I easily found a number of different ways to make the packaging work (the most often cited were dotnet pack and msbuild /t:pack), but none of them seemed to allow easy control over the version number used. It seemed odd to me that such a simple thing could be so difficult to achieve.

Eventually, I discovered a key pair of facts:

  • The dotnet pack command uses msbuild under the hood and will pass on property values defined with /property when msbuild is run.
  • The version of a NuGet package can be specified within a .csproj file by defining the property PackageVersion within the project file.

Putting these two together, I was able to control the version number of a generated package by defining PackageVersion on the command line:

dotnet pack sample.csproj /property:PackageVersion=4.3.2

Updating my psake build script, I modified the Compile.NuGet task to this:

Task Compile.NuGet -Depends Requires.DotNet, Requires.BuildType,
        Requires.BuildDir, Compile.Assembly, Configure.PackagesFolder {

    $nugetFolder = join-path $packagesFolder Niche.CommandLine
    mkdir $nugetFolder | Out-Null

    $csprojFile = resolve-path .\src\Niche.CommandLine\Niche.CommandLine.csproj

    exec {
        & $dotnetExe pack $csprojFile
             --output $packagesFolder
            /property:PackageVersion=$semver20 
            /property:Configuration=$buildType 
            /fileLogger
            /flp:verbosity=detailed`;logfile=$buildDir\Niche.CommandLine.nuget.log
    }
}

Note that I’ve also changed the packaging task to use the SemVer 2.0 version - in the interim between writing these two blog posts, Nuget.org has announced full support for the new version of semantic versioning! The sticking point has always been that older NuGet clients might crash on version numbers using SemVer 2.0 - they’ve worked out how to identify those clients and will hide pre-release SemVer 2.0 packages from those clients. Nice.

Comments

blog comments powered by Disqus
Next Post
Sharpen The Saw #17  30 Oct 2017
Prior Post
Sharpen The Saw #16  23 Oct 2017
Related Posts
Coverage History with Psake  18 Nov 2017
Tracking time with Psake  11 Nov 2017
The day my Psake build broke  04 Nov 2017
.NET Core with Psake  21 Oct 2017
Test Coverage Reporting with Psake  07 Oct 2017
Test Coverage with Psake  30 Sep 2017
NuGet packaging with Psake  23 Sep 2017
Semantic versioning with Psake  16 Sep 2017
Versioning with Psake  09 Sep 2017
Launch Scripts for Psake  02 Sep 2017
More powershell posts »
Related Pages
October 2017 archive