Last night I run into a problem with GitVersion and dotnet pack command while running my builds on VSTS

The probem came up when I tried to specify a version number I’d like the package to have. There are answers on SO telling me how to do it and I’ve used it in the past. But this time it did not work for some reason, so I had to investigate.

Here is the way it worked for me.
To begin, edit your *.csproj file and make sure your package information is there:

<PropertyGroup>
    <OutputType>Library</OutputType>
    <PackageId>MyPackageNaem</PackageId>
    <Authors>AuthorName</Authors>
    <Description>Some description</Description>
    <PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
    <PackageReleaseNotes>This is a first release</PackageReleaseNotes>
    <Copyright>Copyright 2017 (c) Trailmax. All rights reserved.</Copyright>
    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>

Make sure that you don’t have any <Version> or <VersionPrefix> elements in there – these will break your stuff.

Then when you do your dotnet pack specify /p:Version=7.7.7 as a parameter to the command. i.e. dotnet pack --Configuration Release --Output d:/tmp /p:Version=7.7.7.

Assembly version number

You can specify assembly verion number in your *.csproj file or via old-school [assembly: AssemblyVersion("1.2.3.4")] assembly attribute. Both will work in Core projects. However GitVersion does not know how to update version number in your csproj file but works pretty well with AssemblyInfo.cs file. By default Core projects do not come with AssemblyInfo.cs file and you need to create one yourself.

To save some effort for multiple projects in the same solution you can create AssemblyInfo.cs file next to your *.sln file and add this file as a reference to all your projects.

Here is a sample of AssemblyInfo.cs:

using System;
using System.Reflection;

[assembly: System.Reflection.AssemblyCompanyAttribute("Trailmax")]
[assembly: System.Reflection.AssemblyProductAttribute("MyAwesome.Project")]
[assembly: System.Reflection.AssemblyTitleAttribute("MyAwesome.Project")]

[assembly: System.Reflection.AssemblyConfigurationAttribute("Release")]
[assembly: System.Reflection.AssemblyDescriptionAttribute("MyAwesome.Project")]

[assembly: AssemblyVersion("1.2.3.4")]
[assembly: AssemblyInformationalVersion("1.2.3")]
[assembly: AssemblyFileVersion("1.2.3.4")]

To add as link right click on your project: Add -> Existing Item -> select SolutionInfo.cs file -> Instead of Add select Add as Link.

Or you can add this to your csproj file:

<ItemGroup>
    <Compile Include="..\SolutionInfo.cs" Link="SolutionInfo.cs" />
</ItemGroup>

After that is done you can tell GitVersion to update this SolutionInfo.cs file with the new versions.

GitVersion pushes various formats for version numbers into envrionment variables and that can be used as part of dotnet pack command.

The Whole Thing

There is GitVersion addon for VSTS – install it and add it as a first step on your build pipeline. Point it to update your SolutionInfo.cs file.

Then when you need to create a package add another .Net Core build step. Put the command to be pack and add /p:VersionPrefix=$(GitVersion.NuGetVersion) to the arguments list.

Following my previous post, I’m building Asp.Net Core web application and I’m running my tests in XUnit. Default VSTS template for Asp.Net Core application runs the tests but it does not publish any results of test execution, so going into Tests results panel can be sad:

And even if you have a task that publishes test results after dotnet test, you will not get far.

As it turns out command dotnet test does not publish any xml files with tests execution results. That was a puzzle for me.

Luckily there were good instructions on XUnit page that explained how to do XUnit with Dotnet Core properly. In *test.csproj file you need to add basically the following stuff:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp1.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="xunit" Version="2.3.0-beta2-build3683" />
    <DotNetCliToolReference Include="dotnet-xunit" Version="2.3.0-beta2-build3683" />
  </ItemGroup>

</Project>

Make sure you don’t miss the DotNetCliToolReference line – this is the key here.

Run dotnet restore and dotnet xunit inside the folder with this project. If you try to run this command outside of this folder you’ll get an error.

Command dotnet xunit has an option to output test results as XML file: dotnet xunit -xml .\test-results.xml.

Because this needs to be executed inside of the tests folder we can’t use “.Net Core” build task from VSTS – there is no option to configure what is the base execution folder. Instead you can just add “Command Line” task to execute what we need and from the correct folder:

Add “Command Line” task. As Tool option give it dotnet, for arguments say xunit -xml ./test-results.xml and make sure you specify the working folder – for my case that was src/Tests.

After that add “Publish Test Results”, tell it to use XUnit format, the rest of the default parameters worked for me.

And BOOM! We have tests results published at the end of the build:

Yesterday Nuget server was down for couple hours. That wasn’t nice. I got stuck for a bit, because I blew up my environment and needed to re-download all the packages again. And some of them were not in the local cache. And just the same night Mr. Mark Seemann blogged that auto-restore in Nuget is considered harmful. And I could not disagree with Mark. Amount of time I’ve spent on trouble-shooting missing packages or package restore in the last year mounts to probably a week. Most of that time was spent for package restore on build servers. And just for these little shits I had to dig very deep into TFS build template, modify it, so it can restore packages before attempting to build it. It was not a nice experience.

Anyway, long story short. Today I decided to give that advice a go and check in packages for one medium sized project hosted on TFS. I went to Source Control Explorer, added existing folder of packages, it added a big number of files and then I checked-in.

Build server crunched for a moment and failed the build: references are not found. Strange. Connected to the build server and discovered that TFS by default ignored *.DLL files but included all other crap that comes with nuget packages (xml files, readme.md, source code, etc.). That was strange. After a bit of digging I found that TFS has a list of file-types that it looks for.

Continue reading