The Problem

As you might have noticed Microsoft just recently published .NET Core 1.0 alongside Visual Studio 2017 etc (see: https://blogs.msdn.microsoft.com/dotnet/2017/03/07/announcing-net-core-tools-1-0/ ). With the update they also said good bye to the project.json project format and (re)introduced the .csproj based format. So an upgrade is in place.

Today I upgraded a larger solution (57+ projects) from the project.json based project format to the new (old) .csproj format. While that worked pretty well overall, I found one particular annoying problem: Packing a NuGet package for my libraries that uses a version suffix (i.e. the build number). This could looke like this in your NuGet browser: MyPackage.2.1.0-4711

While that worked perfectly fine with the prior versions of .NET Core tooling via ‚dotnet pack –version-suffix <mySuffix>‘, the new version fails to effectively do this. With the new tooling you get one NuGet package per project and that package will only include one DLL for this project. All referencens to other projects are defined in a .nuspec file within the package. So you have to put all your referenced libraries in separate NuGet packages and publish them in order for the dependant package to resolve them.

Now on my site we use a CI/CD pipeline based on Gitlab and build our packages with a suffix containing the pipeline ID from Gitlab. So it’s usually ‚<PackageName>.<SemVersion>-<PipelineID>. So for each new build all internal libraries are being tagged with that versionSuffix as well and are expected to be available by our published packages. However that started to fail once we switched to .NET Core 1.0 tooling and .csproj projects.

The reason is that the nuspec file which gets incorporated into the nupkg does not contain the versionSuffix when defining the dependencies required by the packaged library. So MyPackage.2.1.0-4711 is referencing AnotherPackage.2.1.0, whereas there only is AnotherPackage.2.1.0-4711 available in the private NuGet repository of ours.

Now why is that?

Explanation

It turns out that when restoring a project via ‚dotnet restore‘ a file called ‚project.assets.json‘ is created in the /obj subfolder of your project directory. That file includes everything that is required for the project to be build. Now when running ‚dotnet pack‘ this file is used to determine what needs to be put in your .nuspec file in the NuGet package. Since the restore only looked at the other locally referenced projects, it only added them with their direct version number (in this case „2.1.0“), becuase it obviously does not know about any Pipeline ID which has to be added as suffix.

Solution

To fix this you need to provide the suffix when restoring your project, so that it can be written into the project.assets.json file and be used by the ‚dotnet pack‘ command later on. To achive this you have to use the ‚dotnet msbuild‘ command with a specific set of parameters. In our case we used the following command instead of a simple ‚dotnet restore:

dotnet msbuild "/t:Restore" /p:VersionSuffix=$CI_PIPELINE_ID /p:Configuration=Release

Basically all dotnet commands are wrappers for calls to ‚msbuild‘ so „/t“ is a target definition and the other parameters are key:value pairs to set definable build options.

So when you now run ‚dotnet pack‘ the .nuspec file in your package will include all the correct references!

 

P.S.: Logo taken from https://github.com/campusMVP/dotnetCoreLogoPack