Introduction , we can publish NuGet packages to a private (or public) NuGet feed. These feeds can be scoped in Azure DevOps at either an organization level or at a project level. Using Azure Artifacts Creating a private NuGet feed in Azure DevOps is really simple. This article below shows have you can set one up. If you’re following along and you haven’t set up an internal feed yet, stop reading this article and check out the article . Once you’re done with that, you can return here. here This post will show you how to use a YAML build file to publish the NuGet packages we create to our own Private feeds in Azure Artifacts. Now you might have an opinion on YAML in general, and yes, we can achieve the same result via the Classic user interface. Still, I like being able to include our build files within our code repository and providing me with the ability to check the history of our build file using the git history of that YAML file. To publish our NuGet package to our internal feed, we need to do the following: Create our NuGet package. Decide our versioning strategy for our package. Publish our package to our Internal Feed. For this post, I will be using a helper library that I’ve been using for my own health application. If you want to look at it while reading this (it includes the YAML file), check it out . here Creating our NuGet Package Before jumping into the meat of our build file, We need to set some things up: trigger: - main pool: vmImage: 'ubuntu-latest' variables: ProjectName: 'MyHealth.Common' ProjectPath: '**/MyHealth.Common.csproj' buildConfiguration: 'Release' steps: - task: UseDotNet@2 displayName: 'Install .NET Core SDK' inputs: packageType: 'sdk' version: '3.x' - task: DotNetCoreCLI@2 displayName: 'dotnet restore' inputs: command: 'restore' projects: '$(ProjectPath)' - task: DotNetCoreCLI@2 displayName: 'Build $(ProjectName)' inputs: command: 'build' arguments: '--configuration $(buildConfiguration)' projects: '$(ProjectPath)' Let’s break this down: We trigger the build to kick off every time we make a commit to our branch. main We set some common variables that we will need throughout our build pipeline. We’re using a Linux image as our build agent. We then install the .NET Core SDK on our build agent, restore our project using a task that runs the restore command, and build the project using another task that runs the build command. DotNetCoreCLI To create a NuGet package in our build file, we need to add a task like so: DotNetCoreCLI - task: DotNetCoreCLI@2 displayName: 'Pack $(ProjectName)' inputs: command: 'pack' arguments: '--configuration $(buildConfiguration)' packagesToPack: '$(ProjectPath)' nobuild: true versioningScheme: 'off' In this task, we run the pack command and tell the task to pack our project path that I’ve defined earlier in the YAML file. I’ve set the argument to true since I’ve already built my project. nobuild My package is a .NET Standard package. For , Microsoft recommends that you use the tasks. If you’re building , you can use a task. .NET Core and .NET Standard packages DotNetCoreCLI packages for .NET Framework NuGet Versioning Strategy There are a couple of ways we can do this. In my package file, I’ve specified my Version number like so: .csproj <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>netstandard2.1</TargetFramework> <Description>Common Helper Library for MyHealth Applications</Description> <Authors>Will Velida</Authors> <Product>MyHealth</Product> <Version>1.4.0</Version> <GeneratePackageOnBuild>false</GeneratePackageOnBuild> </PropertyGroup> <ItemGroup> <PackageReference Include="Azure.Messaging.ServiceBus" Version="7.1.2" /> <PackageReference Include="Azure.Storage.Blobs" Version="12.8.1" /> <PackageReference Include="Microsoft.Azure.Cosmos.Table" Version="1.0.8" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> </ItemGroup> </Project> If we wanted to achieve this via a build task defined in YAML, we could do so like this: variables: Major: '1' Minor: '0' Patch: '0' steps: - task: NuGetCommand@2 inputs: command: pack versioningScheme: byPrereleaseNumber majorVersion: '$(Major)' minorVersion: '$(Minor)' patchVersion: '$(Patch)' With the task, we can use the semantic versioning scheme for our builds. However, once a version has been produced, we can’t update or replace that version. They are immutable. To produce new versions of our package each time we update them, we can do the following: NuGet Major.Minor.Patch Use the variable for the version number that we wish to increment. This will automatically increment the build number for that variable each time we push to our branch while keeping the other variables constant. $(rev:.r) Use the variable. This is ideal for creating prelease labels for the build while keeping our major, minor, and patch versions constant. $(date:yyyyMMdd) Publishing our package to the feed Now that we have a package, we can publish it in our feed. To publish to our Azure Artifacts feed, we’ll need to set the . Project Collection Build Service identity to be a Contributor on the feed Once we have enabled that, we can add the following YAML to our build pipeline: - task: NuGetAuthenticate@0 - task: NuGetCommand@2 displayName: 'Publish $(ProjectName)' inputs: command: push feedsToUse: 'select' packagesToPush: '$(Build.ArtifactStagingDirectory)/**/*.nupkg;!$(Build.ArtifactStagingDirectory)/**/*.symbols.nupkg' nuGetFeedType: 'internal' publishVstsFeed: '<projectname>/<feedname>' versioningScheme: 'off' allowPackageConflicts: true Here, we are using the command to authenticate our Build server to push packages to our internal NuGet feed. We then run a task with the push command to push our package (stored in our Artifact Staging Directory) to our internal NuGet feed. NuGetAuthenticate NuGetCommand Here, we have used as our VSTS feed to publish to. Remember, we can scope our feeds at either the project level or an organization level in Azure DevOps. Since my feed is scoped at the project level, I need to put the project name here. <projectname>/<feedname> I’ve also included the argument and stated that our target field is an internal feed. Since we are using the command in the NuGet command task, this argument is required. nuGetFeedType push Full YAML file Here’s our complete YAML file: trigger: - main pool: vmImage: 'ubuntu-latest' variables: ProjectName: 'MyHealth.Common' ProjectPath: '**/MyHealth.Common.csproj' buildConfiguration: 'Release' steps: - task: UseDotNet@2 displayName: 'Install .NET Core SDK' inputs: packageType: 'sdk' version: '3.x' - task: DotNetCoreCLI@2 displayName: 'dotnet restore' inputs: command: 'restore' projects: '$(ProjectPath)' - task: DotNetCoreCLI@2 displayName: 'Build $(ProjectName)' inputs: command: 'build' arguments: '--configuration $(buildConfiguration)' projects: '$(ProjectPath)' - task: DotNetCoreCLI@2 displayName: 'Pack $(ProjectName)' inputs: command: 'pack' arguments: '--configuration $(buildConfiguration)' packagesToPack: '$(ProjectPath)' nobuild: true versioningScheme: 'off' - task: NuGetAuthenticate@0 - task: NuGetCommand@2 displayName: 'Publish $(ProjectName)' inputs: command: push feedsToUse: 'select' packagesToPush: '$(Build.ArtifactStagingDirectory)/**/*.nupkg;!$(Build.ArtifactStagingDirectory)/**/*.symbols.nupkg' nuGetFeedType: 'internal' publishVstsFeed: 'projectname/feedname' versioningScheme: 'off' allowPackageConflicts: true Conclusion Hopefully, you can see how simple it is to publish our NuGet packages to a private NuGet feed in Azure Artifacts. This isn’t just limited to private NuGet feeds. We can also publish packages from DevOps to . NuGet.org If you want to learn more about Azure Artifacts, I recommend that you check out the that covers topics such as configuring feeds, publish NuGet (and other) types of packages, and more. documentation If you have any questions about this article, please let me know in the comments, or you can reach out to me on . Twitter Previously published on . dev.to