Ultimate pipeline for NuGet packages

nuget packages

Here I explain how to create the ultimate pipeline for NuGet packages with Azure DevOps as the end of my previous posts:

Scenario

In my repository in Azure DevOps, I have a solution with multiple project in .NET Core and each of them is a package that I want to publish in the Artifacts (for internal purpose) and then on NuGet.org. I can have test projects for each package. Some projects may have as dependencies other packages from my artifacts and not only from NuGet. Also, I want to add version to the packages automatically.

Connect Azure DevOps to NuGet.org

First, to connect Azure DevOps to the NuGet.org, we have to create an API key in NuGet.org. So, go to your account on NuGet.org and from the menu on your account select API keys. So, you will see a screen like the following screenshot.

Create a new API key in NuGet.org - Ultimate pipeline for NuGet packages
Create a new API key in NuGet.org

Then, fill the form and select Push and Push new packages and package version. Click on Create. Now, with the key go to the Azure DevOps and click on Project settings. So, click on Service connections and click on New connection button. Now, from the list select NuGet.

Create a new service connection
Create a new service connection

So, in the new draw Edit service connection, select

  • ApiKey
  • Feed URL https://api.nuget.org/v3/index.json
  • Paste the ApiKey
  • Choose a Service connection name (in my case Nuget Website)

Then, click on the Save button.

Create\Edit a service connection for NuGet.org in Azure DevOps - Ultimate pipeline for NuGet packages
Create\Edit a service connection for NuGet.org in Azure DevOps

Now, we have a connection between Azure DevOps and NuGet.org to use to publish our packages.

Create a new pipeline

Now, it is time to create the pipeline.

Add variables

First, I want to create the variables in order to have the versioning of the packages. For that, in the Variables section of the pipeline I’m adding the following variables:

NameReasonValue
buildConfigurationWhat kind of build we want? I’m specified this because the pipeline could have problem to find the right directory during the processRelease
MajorMajor version of the package (it must be a number)1
MinorMinor version of the package0
PackageVersionThis create the package version based on the other values$(Major).$(Minor).$(Patch)$(PackageVersionType)
PackageVersionTypeI can use this variable to add more info in the package version such as -prerelease, -alfa, -beta and so on.
PatchHere Azure DevOps checks the version of the next package incrementing the Minor version$[counter(format(‘{0}.{1}’, variables[‘Major’], variables[‘Minor’]), 0)]
Variables to use in your pipeline

What you see in the Variables section something like the following screenshot.

Variables for the pipeline - Ultimate pipeline for NuGet packages
Variables for the pipeline

After that, I have to add the section in the pipeline. So, I use the Assistant for that.

Restore packages

First, I have to restore the packages from Nuget.org and from my Artifacts. So, in the Assistant select .NET Core. Then, select:

  • Command: restore
  • Feeds to use: select your Azure Artifact feed (in my case PureSourceCode)

Then, click on Add.

The result YAML is

- task: DotNetCoreCLI@2
  displayName: Restore packages
  inputs:
    command: 'restore'
    feedsToUse: 'select'
    vstsFeed: 'your-feed'

Build the project

Now, add a new .NET Core and select the following options:

  • Command: build
  • Path to project(s): **/*.csproj
  • Arguments: --configuration $(buildConfiguration)
Build the project
Build the project
- task: DotNetCoreCLI@2
  displayName: Build project
  inputs:
    command: 'build'
    projects: '**/*.csproj'
    arguments: '--configuration $(buildConfiguration)'

Run tests

So, to run the test add a new .NET Core and select the following options:

  • Command: test
  • Path to project(s): **/*[Te]ests/*.csproj (to build all the project that have a word Tests in the its name)
  • Arguments: --configuration $(buildConfiguration) --no-build
Run tests
- task: DotNetCoreCLI@2
  displayName: Run tests
  inputs:
    command: 'test'
    projects: '**/*[Te]ests/*.csproj'
    arguments: '--configuration $(buildConfiguration) --no-build'

Prepare the package

Now, I have to prepare the package. So, add a new .NET Core and select:

  • Command: pack
  • Path to csproj or nuspec file(s) to pack: **/.csproj
  • Configuration to Package: $(BuildConfiguration) (this is the default option)
  • Package Folder: $(Build.ArtifactStagingDirectory) (this is the default option)
  • Automatic package versioning: select from the dropdown list Use an environment variable
  • Environment variable: PackageVersion
  • Additional build properties: -t:pack

Then, add this one.

Pack the package
Pack the package
- task: DotNetCoreCLI@2
  displayName: Prepare the package
  inputs:
    command: 'pack'
    packagesToPack: '**/*.csproj'
    versioningScheme: 'byEnvVar'
    versionEnvVar: 'PackageVersion'
    arguments: '-t:pack'

Publish the package in the Artifacts

Now, I want to push the package in the Artifacts. Add a new .NET Core and select the following options:

  • Command: nuget push
  • Path to NuGet package(s) to publish: $(Build.ArtifactStagingDirectory)/*.nupkg (this is the default option)
  • This organization/collection: from the dropdown select your Target feed (in my case PureSourceCode)
Push the package in the Artifacts
Push the package in the Artifacts
- task: DotNetCoreCLI@2
  displayName: Publish the package
  inputs:
    command: 'push'
    packagesToPush: '$(Build.ArtifactStagingDirectory)/*.nupkg'
    nuGetFeedType: 'internal'
    publishVstsFeed: 'yourfeed'

Push the package to NuGet.org

Finally, I’m ready to push the package to the NuGet.org. So, add a new NuGet task from the Assistant. I have to choose this option because the .NET Core task doesn’t support the new version of the NuGet apis.

NuGet task

Then, fill it with the following options:

  • Command: push
  • Path to NuGet package(s) to publish:
$(Build.ArtifactStagingDirectory)/**/*.nupkg;!$(Build.ArtifactStagingDirectory)/**/*.symbols.nupkg

Then, select External NuGet server (including other accounts/collections) and from the dropdown list select the connection we created at the beginning of this post (in my case NuGet Website).

NuGet configuration in Azure DevOps
NuGet configuration in Azure DevOps
- task: NuGetCommand@2
  displayName: Push the package to NuGet.org
  inputs:
    command: 'push'
    packagesToPush: '$(Build.ArtifactStagingDirectory)/**/*.nupkg;!$(Build.ArtifactStagingDirectory)/**/*.symbols.nupkg'
    nuGetFeedType: 'external'
    publishFeedCredentials: 'NuGet Website'

The full YAML for the pipeline

# Starter pipeline
# Start with a minimal pipeline that you can customize to build and deploy your code.
# Add steps that build, run tests, deploy, and more:
# https://aka.ms/yaml

trigger:
- main

pool:
  vmImage: ubuntu-latest

steps:
- task: DotNetCoreCLI@2
  displayName: Restore packages
  inputs:
    command: 'restore'
    feedsToUse: 'select'
    vstsFeed: 'your-feed'
- task: DotNetCoreCLI@2
  displayName: Build project
  inputs:
    command: 'build'
    projects: '**/*.csproj'
    arguments: '--configuration $(buildConfiguration)'
- task: DotNetCoreCLI@2
  displayName: Run tests
  inputs:
    command: 'test'
    projects: '**/*[Te]ests/*.csproj'
    arguments: '--configuration $(buildConfiguration) --no-build'
- task: DotNetCoreCLI@2
  displayName: Prepare the package
  inputs:
    command: 'pack'
    packagesToPack: '**/*.csproj'
    versioningScheme: 'byEnvVar'
    versionEnvVar: 'PackageVersion'
    arguments: '-t:pack'
- task: DotNetCoreCLI@2
  displayName: Publish the package
  inputs:
    command: 'push'
    packagesToPush: '$(Build.ArtifactStagingDirectory)/*.nupkg'
    nuGetFeedType: 'internal'
    publishVstsFeed: 'yourfeed'
- task: NuGetCommand@2
  displayName: Push the package to NuGet.org
  inputs:
    command: 'push'
    packagesToPush: '$(Build.ArtifactStagingDirectory)/**/*.nupkg;!$(Build.ArtifactStagingDirectory)/**/*.symbols.nupkg'
    nuGetFeedType: 'external'
    publishFeedCredentials: 'NuGet Website'

Wrap up

So, this is how to create the ultimate pipeline for NuGet packages in Azure DevOps. If you have any question, please use the forum or leave a message at the bottom of this post.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.