Why would I go through this tedious process to create this small NuGet of maybe gold, maybe silver, maybe just some invaluable thing.

Unless I try I wouldn’t know. And that’s how I start each time when I see I am repeating tasks.

As you type your day away, you turn around and see a small simple chunk of code that you think, hey, this guy here, he would be a handful in other places than just this lonely solution here. And Wham(yes just like the band), you decide to package it. But what good does it do, if you cannot easily share this package? And you decide to upload it to your package repository. But hey, what about the open-source project that you want to reuse the same functionality, and what about sharing it with other pals. Then you decide to upload it to a shared package repository.

Finally, you seem a bit relaxed and satisfied with your ingenious idea…And out of nowhere, you notice an issue within the package, nothing that will rain down hell on you, but something that you consider could be better handled. And you decide to create a new version, but hey now, will I do this each time manually, will I version, restore, build, pack and upload this new version of my package each time? Well, why not just teach it a lesson and wrap it in a nice little bow, and send it on its merry way.

So let’s now get into the more technical details.

Photo by Mika Baumeister on Unsplash

NuGet Version, Restore, Build, Pack and Upload

Let’s break it down into smaller steps

This workflow will be shown with an example that can be used quite easily with any CI/CD tool. But in this example here I will be showing it with GitLab CI. The tools that will are used will be GitLab CI, Docker, GitVersion, .NET, and last but not least a package repository of your own choice.

With keeping up the naming conventions of GitLab CI this will be broken down to stages:

  • Versioning the library.
  • Restoring, Building, and Packing the package.
  • Uploading the package to a package repository.

The application of the same process using Jenkins, Azure DevOps, BitBucket, GitHub Actions, and many others should be a simple process of following its tools conventions.

Versioning

Versioning is a topic that can be tackled in so many ways, by so many tools or scripted solutions. For the purpose of this, I will be using GitVersion. A simple tool that does what it says but not in so many words. It is an open-source tool, that actually manages to provide a way to version your solutions, with the simplicity of using your Git History. By tracking your history, it can generate versions based on tags, branches, commits, Pull Requests or Merge Requests, commit messages, and much more. We will not be deep-diving into this right now, so I will stop here. But simply said the command following will be generating a list of environmental variables, that can be injected into your CI tool of choice. And for our purpose, we will use the default generation NuGet version variable.

Certainly using this tool can be done in a number of ways, for this you would either need to add your tool on your own image or use one of the many available GitVersion images on docker hub, that can be used out of the box. Such as the Alpine Linux one, which is quite lightweight. And for our purposes we will be using: gittools/gitversion/5.5.1-linux-alpine.3.10-x64-netcoreapp3.1

Simple said this tool can be executed in a one-line command for the stage Version:

$> gitversion -output buildserver -showvariable NugetVersionV2

Pack it! (Which includes Restore, Build, and packaging the little guy.)

This is not something new that we need to get into, but .NET in all its wisdom has provided us with a myriad of ways to create a NuGet package.

And one of those that we are going to use is:

$> dotnet pack -p:IncludeSymbols=true /properties:configuration=Release /p:Version=$GitVersion_NuGetVersionV2

And let’s not forget for this we need to have .NET Core installed, or we can use a docker image that will give us the possibility to execute this command. And again, .NET has provided us a list of possibilities on that front also. So choose what you see fit. In this case, I am using one of the following docker images: /dotnet/core/sdk So decide what fits your use case best, and choose the image accordingly.

And finally getting rid of it

And by this, I mean put it safely in a repository for easy access from anywhere.

And again this stage can be executed in a number of ways. But the one I went with is:

$> dotnet nuget push */bin/Release/*.nupkg -k $NUGET_KEY -s $INTERNAL_REPOSITORY_ADDRESS/repository/$NUGET_REPOSITORY/

This final step can be executed on the same container as with the Pack It! stage. Because the command is part of .NET and it uploads a package to a NuGet type of repository.

And finally the wrap-up.

We can finish this off by providing a complete example of the Script:

A good approach would be if you pack this .yml file in a common location, for reuse of all your NuGet package repositories. By doing this, and bypassing only some variables in it, you maintain one location for the script and easy reuse.

And as the last sign off message, I would suggest checking this link out, The Other Tim - Harden your Gitlab CI pipeline with DevOps Principals. Where The Other Tim shows a good way to maintain your docker images, and provide a couple of layers of safety instead of depending on Docker Hub(and its newly introduced pull limit).