Deploying to NuGet Manually and Using GitHub Actions

May 23, 2020

I’ve been playing with GitHub Actions in order to create some kind of basic pipeline for a little NuGet library that I created. In this post, I’ll describe the manual process, and then one option for automating that process.

Manual process

The manual process is actually not too bad. I know that CI/CD is the latest TDD (that is, the thing that everyone wants to agree is a good thing); and I’m not saying it’s a bad thing - I am, however, saying that if you have a limited amount of time, and no product to deploy, your time may be better spent creating one, rather than creating a deployment pipeline for something that doesn’t exist. Having a deployment process that’s written down in a text file has its downsides, but people will first judge your software by it’s quality, not by the method it arrived on the server.

Having said that, one thing that automating this whole process does give you, is a guarantee that all the tests are passing before it gets published.

The first step in deploying a NuGet package is to configure the properties of the project. You can have VS generate the NuGet package for you (Generate NuGet package on build), or you can do so yourself. Either way, you’ll need to update the version number:

github actions 1

Assuming that you didn’t ask VS to generate on build, your next step is to switch to the Release profile, build and the “Pack” the project:

github actions 2

Pack will produce a .nupkg file, which you’ll find in your bin folder:

github actions 3

This assumes that you’ve previously created the NuGet package in NuGet; if you have then log-in to and select to upload a new package:

github actions 4

Point it to your lastest.nupkg, and the package is published.

That whole process takes around 2 - 3 minutes, maybe less.

GitHub Actions

So, we’ve got a relatively smooth manual deployment pipeline, and I had a bit of a diatribe at the start of this post about how great manual deployments are. You may be wondering why I’m trying to automate this. In fact, there are two big advantages to an automated deployment (apart from the fact that I just wanted to play with GitHub actions!):

1. You're guaranteed to have your tests pass before deployment.
2. There's a record of the deployment, and what was deployed.

Specifically, GitHub actions has the following advantages over most other deployment pipelines:

1. It's free.

Setting up a New Pipeline

To start with, navigate to the Actions tab under your repository in GitHub:

github actions 5

Here, you’re presented with a list of pre-built workflows - some relate more to what you may be doing than others. Basically, GitHub uses a language analyser to try and work out what language you’re using for your project and gives you options based on that.

The default workflow does a build, and then runs the tests, so let’s set that one up first:

github actions 6

You’re then taken to a YAML editor (unfortunately, YAML seems to be the language of choice for GitHub Actions):

github actions 7

Let’s make a mental note of the “marketplace” on the right hand side, but for now, let’s just save this, and see what happens.

github actions 8

We can now test this by navigating to Actions, and generating a push:

github actions 9

If your build fails (like mine) you can have a look in the logs:

github actions 10

You can drill into each section, and see the error; for example:

github actions 11

To fix the issues, you can edit the build directly in GitHub, and then re-try the build. I’m planning a follow-up post to this on some techniques for debugging these things.

Once that’s working, we want to publish to NuGet. Let’s have a look if there’s anything already out there:

github actions 12

The Marketplace has hundreds of pre-built worfklows that you can just incorporate into your own. Simply copy the supplied YAML. For my project, it looks like this:

name: .NET Core	
	branches: [ master ]
	branches: [ master ]
	runs-on: ubuntu-latest
	- uses: actions/checkout@v2
	- name: Setup .NET Core
	uses: actions/setup-dotnet@v1
	dotnet-version: 3.1.101
	- name: Install dependencies
	run: dotnet restore ./WebSiteMeta/
	- name: Build
	run: dotnet build --configuration Release --no-restore ./WebSiteMeta
	- name: Test
	run: dotnet test --no-restore --verbosity normal ./WebSiteMeta
	- name: Publish NuGet
	uses: rohith/[email protected]
	# Filepath of the project to be packaged, relative to root of repository
	PROJECT\_FILE\_PATH: WebSiteMeta/WebSiteMeta.Scraper/WebSiteMeta.Scraper.csproj
	# NuGet package id to check against version changes, defaults to project name
	#PACKAGE\_NAME: # optional
	# Filepath containing version info, relative to root of repository
	#VERSION\_FILE\_PATH: # optional
	# Regex pattern to extract version info in a capturing group
	#VERSION\_REGEX: # optional, default is <Version>(.\*)<\\/Version>
	# Static version, useful for external providers like Nerdbank.GitVersioning
	#VERSION\_STATIC: # optional
	# Flag to enable / disable git tagging
	TAG\_COMMIT: false # optional, default is true
	# Format of the git tag, \`[\*]\` gets replaced with version
	#TAG\_FORMAT: # optional, default is v\*
	# API key for the NuGet feed
	NUGET\_KEY: ${{secrets.NUGET\_API\_KEY}} # optional

If you’re interested how the secret was generated, then have a look at this earlier post.

Profile picture

A blog about one man's journey through code… and some pictures of the Peak District

© Paul Michaels 2024