NuGet Release and Pre-Release pipeline

One of the big improvements that came with NuGet is the ability to easily work with third party libraries and, because of proper versioning, using them with relative safety in your software development projects.
With rise of dependency injection, nowadays libraries are not just third party pieces of software, they also become an important part of your own software projects. And this means that you need to have a way to store and share them within your team, but also have a sensible way of versioning them.

Using Semantic Versioning is the best approach, since it gives a clean and easy way for your team to use versions and have everyone understand the same thing when talking about major, minor and patch version numbers. Now you need to make this a part of your CI/CD pipeline.

Pre-Release version, aka the feature build

While creating a new version of the library, you will also want to test the changes to your library in the code that consumes said library. For this you need to have pre-release versions available in your NuGet repository.
There are several ways to influence the version number of a NuGet package, the most basic one being that the NuGet package takes the version of the assembly. It is also possible to create a custom NuSpec file, which contains several metadata properties of the NuGet package you intend to build.

Using the Project version

The easiest way to set this up, which will also make sure that the digital signature of your assembly has the intended version number, is to set the version information in the project file.
With C#, version is determined based on the following two parts in the project: VersionPrefix and VersionSuffix. The project file can also have a Version value. If this is set, the VersionPrefix and VersionSuffix are ignored. Make sure to use the VersionPrefix.
This should result in a pre-release version of a NuGet package, in the NuGet repository.
(Format: major.minor.patch-prereleaseversion)

This can be done in the Azure DevOps pipeline with the following yaml:
- task: DotNetCoreCLI@2
  inputs:
    command: 'pack'
    packagesToPack: '**/*.csproj'
    versioningScheme: 'off'
    buildProperties: 'VersionSuffix=$(Build.SourceBranchName)-$(Build.BuildId)'

Note that for the master-build, the command would look like this:
 - task: DotNetCoreCLI@2
  inputs:
    command: 'pack'
    packagesToPack: '**/*.csproj'
    versioningScheme: 'off'

Creating a new version

The workflow exists of:
  • determining the intended version number (is this a patch or minor version? Or even a major version)
  • creating your branch, writing and testing your code, then pushing it to the central Git repository.
  • build the code and push it to NuGet a s a prerelease
  • test the pre-release version
  • (fulfilling also team agreements with regards to pull request, code review, testing, etc...) merge to master and create final version for NuGet

 Verify existing version in a pipeline

Since versions need to be unique, it is useful to have a quick check if you are building the correct version. The version you are working on should not have a final version available in the NuGet repository.

The following PowerShell script will check the version against your NuGet repository.

$packageName = $Env:BUILDPROJECT;
$libraryProject = $Env:LIBRARYPROJECT
$nugetUrl = $Env:NUGETURL;

$versionNode = Select-Xml -Path "$(
$libraryProject).csproj" -XPath "//VersionPrefix" | Select-Object -first 1;
$version = $versionNode.node.InnerText;

$url = '
$nugetUrl/Packages(Id='''+ $($packageName) + ''',Version=''' + $($version) + ''')';
$existingpackage = $true;
try {
    Invoke-RestMethod $url;
} catch {
    if($_.Exception.Response.StatusCode.value__ -eq 404){
        $existingpackage = $false;
    }
}

if($existingpackage){
    Write-Error "$($version) already exists, halting!";
    exit 1;
}else{
    Write-Information "$($version) still available";
}

Comments

Popular posts from this blog

Using Azure Devops Service Connections in dashboard widgets

Running Azure DevOps container agents on OpenShift