Programming Seeking Understanding
The blog of Mark Cheeseman

Continuous Delivery For A Nuget Package Using Appveyor

This post outlines some of the details involved in setting up a continuous delivery pipeline for a nuget package. The primary goal was to be able to deploy a new version of a package with a command from a development machine. It is based on experiences in setting up Hdq.Lib. The primary tools used are Appveyor for building and testing and Nuget.org as the package repository.

Pipeline

The besic pipeline from source code to nuget package is:

  1. Solution containing C# project and corresponding test project
  2. Local git repository
  3. Github repository
  4. Appveyor (build, run tests, create nuget package, deploy nuget package)
  5. nuget.org (package repository)


Requirements

The basic requirements were:

git tag -a 1.2.3 -m "New release of amazing things"
git push --follow-tags

Constraints

The following are constraints or behaviours of the systems being used:


Setup

Most of the setup from Visual Studio solution through to Github repository is not difficult, simply being a standard GitHub repository setup. Appveyor and Nuget are where most of the interesting work lies.

Nuget

There are plenty of helpful guides to getting started with nuget. The two I found most helpful were:

A high level summary of the process (for more detail see Create and publish a package) is:

nuget spec
nuget pack projectname.csproj

This can be tested from the dev machine. If you do happen to try this take note that once a version number for a project is used, while it is possible to delete that version of the package from nuget.org, it is not possible to ever use that version number again. For testing purposes, the version number can be temporarily changed from ‘$version’ to something like ‘0.0.0.1’.

nuget push packageName.versionNumber.nupkg api-key-here -Source https://www.nuget.org/api/v2/package

Appveyor

Creating an Appveyor account and connecting it to your GitHub repository is pretty much as simple as following their Getting Started. If you get this far, commits to the GitHub master branch will cause Appveyor to build the project and run the tests. Most of the subsequent setup I performed using the project “SETTINGS” user interface online. The settings allows for an appveyor.yml file to be exported. This file can then be add to the project and becomes the project definition, replacing whatever is defined by the settings UI.

The main alterations to the default settings involve getting the versioning to work and deployment to nuget. Following is my appveyor.yml, with comments liberally added to explain what is happening.

# By default the version is set to the same thing as non-deployed builds.
# However, this is always overwritten using Update-AppveyorBuild below.
version: 0.0.0.{build}
image: Visual Studio 2017
# Package should use the Release, not Debug configuration.
configuration: Release
# Following is a powershell script that sets the version.
# If the build is triggered by a repo tag, then the version number 
# gets set to something appropriate for a deployed build (e.g. 1.2.3.456)
# Otherwise, the verison number gets set to something like 0.0.0.456-er43f3
init:
- ps: >-
    if ($env:APPVEYOR_REPO_TAG -eq "true")

    {
      Update-AppveyorBuild -Version "$($env:APPVEYOR_REPO_TAG_NAME).$($env:APPVEYOR_BUILD_NUMBER)"
    }

    else

    {
      Update-AppveyorBuild -Version "0.0.0.$($env:APPVEYOR_BUILD_NUMBER)-$($env:APPVEYOR_REPO_COMMIT.substring(0,7))"
    }
assembly_info:
# Patch true ensures that the assemblies version number 
# gets set to the build version number
  patch: true
  file: '**\AssemblyInfo.*'
  assembly_version: '{version}'
  assembly_file_version: '{version}'
  assembly_informational_version: '{version}'
# The nuget package always get published to the project feed. 
# This allows it to be downloaded and tested.
nuget:
  project_feed: true
before_build:
# Before building, restore any nuget libraries required.
- cmd: nuget restore Hdq.Lib.sln
# Build specifies that the nuget package must be published.
build:
  publish_nuget: true
  verbosity: normal
# The following is the details allowing for appveyor to push the 
# new version of the package to nuget.org.
deploy:
- provider: NuGet
  api_key:
    secure: j5g0Htw7zXZ/iAMHi68yb+9AZIO2bno642h/Djfe62Ux4ZiHIVNg0SpiIgI/BtqG
  artifact: /.*\.nupkg/
# Only deploy to nuget.org when the build was triggered by a tag.
  on:
    APPVEYOR_REPO_TAG: true