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.

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.

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.

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:
Name | Reason | Value |
---|---|---|
buildConfiguration | What kind of build we want? I’m specified this because the pipeline could have problem to find the right directory during the process | Release |
Major | Major version of the package (it must be a number) | 1 |
Minor | Minor version of the package | 0 |
PackageVersion | This create the package version based on the other values | $(Major).$(Minor).$(Patch)$(PackageVersionType) |
PackageVersionType | I can use this variable to add more info in the package version such as -prerelease , -alfa , -beta and so on. | |
Patch | Here Azure DevOps checks the version of the next package incrementing the Minor version | $[counter(format(‘{0}.{1}’, variables[‘Major’], variables[‘Minor’]), 0)] |
What you see in the Variables section something like the following screenshot.

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)

- 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

- 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.

- 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)

- 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.

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).

- 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.