.NET Core

How to build and host a NuGet package using VS2017 and .NET Standard in VSTS

Creating a NuGet package in Visual Studio 2017 and getting it to build/deploy to Visual Studio Team Services was more difficult than I expected. Here’s how I did it.

NOTE: MAJOR UPDATE OF THIS POST AVAILABLE

I’m deprecating this post 🙂 I’ve pretty much re-written this post to make use of the latest VSTS functionality and to support both .NET Standard 2 and .NET Core 2. Check it out!

Build and Deploy a .NET Core 2.0 or .NET Standard 2.0 NuGet Package using VSTS

Pre-requisites

  • Visual Studio 2017. Anything from Community edition onwards is fine
  • Visual Studion Team Services (VSTS) account
  • A destination for your NuGet packages. MyGet is fine but I’m using VSTS

Package management in VSTS is free for up to 5 users. To get this functionality you first have to enable the trial. If you have 5 or less users you won’t be charged.

https://marketplace.visualstudio.com/items?itemName=ms.feed

Background

I had a small library, written in .NET Core. I wanted to re-use this library in another project so I decided to create a NuGet package.

The code was had no dependencies (it’s relatively simple) so it was a perfect candidate for .NET Standard. Continuing to use .NET Core would have been fine as well.

In my solution, I would also include the relevant xUnit tests as an additional project.

It looked something like this (except with more files)

2017-03-23_22-13-21

Lastly, I wanted to setup the build & deploy to the package feed within Visual Studio Team Services (VSTS).

Once I started setting up VSTS I realized I had a bunch of problems.

Problem 1: Incrementing Versions

With my NuGet package it’s important that the version number increments. It cannot exist already and we can’t go backwards.

Problem 2: Where’s the AssemblyInfo.cs?!?

In Visual Studio 2017, when you create a .NET Core or a .NET Standard library, there is no AssemblyInfo.cs file. The version information is instead kept within the csproj.

There are many add-ons for VSTS that allow you to change the details in AssemblyInfo but these wouldn’t work. What do I do??

Here’s what the csproj XML looks like. Note that if you leave the version at 1.0.0, it won’t display the version tag.

Problem 3: What version would I use?

In theory we have four components of the version number: major.minor[.build[.revision]]. For example: 12.4.30.2

Where would I get the major and minor versions?

The build number could come but VSTS but what exactly would I use?

VSTS can provide the build number but how I get it?

Ugh…

Problem 4: NuGet Packager

The NuGet Packager item in VSTS wasn’t working. I forget the details but suffice to say I couldn’t get it to work.

Solution

Here’s what I did to get it all working.

Project configuration in Visual Studio 2017

In VS2017, I went into the project properties, Package settings and set the following:

  • Clicked Generate NuGet package on build. This is important as it meant I could avoid using the NuGet packager in VSTS
  • Entered a description. This will show in the package feed
  • Make sure all the other info, such as author, company, etc was correct

2017-03-23_21-24-43

VSTS Packages

I had to create a package feed by going into:

  • My project in VSTS
  • Build & Release tab
  • Packages option
  • Clicked New feed, filled out the details
  • Clicked Connect to feed. This gave me a URL I would use later in VSTS

2017-03-23_21-33-23

Powershell Script

I added the following file to my project. A few key things:

  • It takes two parameters
    • Path to the csproj
    • The version generated by VSTS
  • It users the major, minor and revision number
  • It generates the build number by using the date. It was a way of getting a unique, incrementing value that would remain under 65,534
  • Once it has the details it opens the XML, inserts the build number
  • Writes to the console, which is useful to see in the logs

Build Process

At a high level I created a build process as follows:

  • Ran dotnet restore.
  • Powershell script to set the csproj version
  • Build block for the solution. Key things to note were:
    • Set the Visual Studio Version to 2017
    • Clicked the Clean checkbox, to be safe
  • Test Assemblies, to run my unit tests
  • NuGet Publisher

I also added some configuration in the build process

Configuration – Variables

I added two variables – for the major and minor versions. I will set this manually going forward. The build does not increment these.

2017-03-23_21-48-52

Configuration – Options

Under options I entered the following Build number format

$(MajorVersion).$(MinorVersion).$(Date:yyyyMMdd)$(Rev:.r)

This would produce a value such as 2.5.20170324.8.

This value is great for me, in VSTS, to see all my builds but it’s no good for an actual version number as the date is too long. I also needed something unique.

I also set the Default agent queue to Hosted VS2017

2017-03-23_21-47-20.jpg

dotnet restore

Nothing fancy about this. I just called the restore command.

I originally forgot to do this and was getting all sorts of errors, saying it was missing basic things like System.Date.

2017-03-23_21-35-28

Powershell script to set the csproj

Remember how I added the ps1 file to the root of my project? Here’s how I would use it.

Note that I could have added this code directly in VSTS but, by having the ps1 file in source, I can manage it using source control

Assuming my project was called MySimpleLibrary, here’s how it would be configured:

  • Entered a Display name of “PowerShell Script to set csproj version”
  • Set the Script Path to MySimpleLibrary/SetCsProjVersion.ps1
  • Passed two arguments as follows $(Build.SourcesDirectory)/MySimpleLibrary/ MySimpleLibrary.csproj $(Build.BuildNumber)
    • The first argument is the path to the csproj, of the code project
    • The second is the build number
  • Working folder is set to MySimpleLibrary

Note: I couldn’t just pass the revision number variable $(Rev:.r) as a parameter here. It wouldn’t let me use it here. That’s why I passed the ENTIRE build number and then parsed it. If you want a different build number format (i.e. you want to add the build name or branch name), it’s just a matter of tweaking the Powershell script. I’m pretty sure I could have passed the major and minor versions as separate variables to my script.

2017-03-23_21-38-25.jpg

Build solution

This is standard. The only changes are:

  • Set the Visual Studio Version to Visual Studio 2017
  • Clicked the Clean Just to be safe – not required

2017-03-23_21-55-27.jpg

Test assemblies

Standard item. No changes

NuGet Publisher

The only thing I did here was select Internal NuGet feed and pasted the URL from the Packages tab

2017-03-23_21-59-42.jpg

End Result – it works!

It worked! The package builds and deploys successfully. All I had to do was add the package feed URL within Visual Studio.

Hope this helps.

2017-03-23_22-08-14

15 comments

  1. First and foremost, thank you for this article. It provided the most information in sorting out how to build and publish a package in VSTS.
    Following your steps, I noticed something had occurred that I cannot find an explanation for. A build that I just performed had the build number 1.0.20170414.3. When I published the package, the version of the package ended up as 1.0.2155.3. What does the value of 2155 represent? I would guess it somehow represents the date (in comparing the date from some of the images in the article). Why did it convert though?

    Like

    1. That is correct and intentional. The powershell script transforms the date, specifically the month. Was a bit of a hack to get it working.

      In a version number, the build portion (the third number) can be a maximum of 65K. 20170414 is too big. In the powershell script I summed up the:
      * Year i.e. 2017
      * (Month * 31) i.e. 4 * 31 = 124 <– the hacky bit
      * Day i.e. 14

      Therefore the total is 2155.

      $splitNumber = $newVersion.Split(".")
      if( $splitNumber.Count -eq 4 )
      {
      $majorNumber = $splitNumber[0]
      $minorNumber = $splitNumber[1]
      $revisionNumber = $splitNumber[3]

      # I need to keep my build number under the 65K int limit, hence this hack of a method
      $myBuildNumber = (Get-Date).Year + ((Get-Date).Month * 31) + (Get-Date).Day
      $myBuildNumber = $majorNumber + "." + $minorNumber + "." + $myBuildNumber + "." + $revisionNumber

      Yes, it does suck that the build has that nice format of 1.0.20170414.3 but the actual package has a different version to what you see in the package.

      P.S. you're welcome – glad it helped.

      Like

    1. I don’t know why you can’t see it. I just opened my .NET standard project in VS2017, right clicked the project, selected Properties and there is a “Package” option. If you can’t get it working click the Contact menu option and send me some screenshots.

      Like

  2. Great job and thank you for sharing. Any chance you could update this to work with .NET Standard 2.0 and the latest VSTS release? I’ve tried to get NuGet restore to work but it keeps throwing errors.

    Like

  3. Hi Ben,
    Thanks for your post! I have fews questions about our build definition ! Currently I’m using a custom XAML build definition and the followings kinds of problems prevent me from migrating to non-xaml build definition.

    Do you think it’s possible to increment the version number (+1) instead of using the current data ?
    And consequently do you think it’s possible to create a PowerShell script to save the new version number directly in TFS (update then commit .csproj programmatically) ?
    My latest question is regarding the “.symbols.nupkg”, how would you implement it in your use case?

    Thanks again for your very interesting article.

    Like

    1. Hi,

      I strongly suspect it is possible to increment the version number with a Powershell script but I don’t know for sure. As for the symbols.nupkg, sorry I don’t know.

      This article was written a while ago. Quite a bit has changed. I’m actually meeting up with someone from Microsoft purely to discuss versioning of builds & packages in VSTS. If I learn anything new I’ll post it on my blog.

      Ben

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s