October 12, 2017
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.
The besic pipeline from source code to nuget package is:
The basic requirements were:
git tag -a 1.2.3 -m "New release of amazing things"
git push --follow-tags
Deployment builds (where a release is deployed to nuget.org) use version numbers for the package including the tag and the build number.
For instance, if the tag is “1.2.3” and the appveyor build number (a continuously incrementing number) is 999, then the version number of the package would be “1.2.3.999”
Non deployed builds including build/test/packaging should occur for commits that are not tagged. These builds should be versioned in a way that is clearly distinguished from the release builds.
For example, when code is pushed to GitHub (origin), a build should occur in appveyor. If the appveyor build number was 888, and the git commit hash was ab1cd23, the build version number would be 0.0.0.888-ab1cd23
The following are constraints or behaviours of the systems being used:
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.
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
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