Publish NuGet packages with Azure Pipelines (YAML/Classic)

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019 | TFS 2018

In Azure Pipelines, you can use the classic editor or the YAML tasks to publish your NuGet packages within your pipeline, to your Azure Artifacts feed, or to public registries such as nuget.org.

Create a NuGet package

There are various ways to create your NuGet packages such as using Visual Studio to pack your NuGet packages. If you're already using MSBuild or some other task to create your packages, skip this section and jump to the publish NuGet packages section.

To create a NuGet package, add the following snippet to your pipeline YAML file. See NuGet task for more details.

- task: NuGetCommand@2
  inputs:
    command: pack
    packagesToPack: '**/*.csproj'
    packDestination: '$(Build.ArtifactStagingDirectory)'
  • packagesToPack: pattern to search for csproj directories to pack
  • packDestination: directory where packages will be created

YAML is not supported in TFS.

Package versioning

NuGet packages are identified by their names and version numbers. A recommended approach to versioning your packages is to use Semantic Versioning. Semantic versions have three numeric components: Major, Minor, and Patch.

The patch is usually incremented after fixing a bug (E.g. 1.0.0 -> 1.0.1). When you release a new backward-compatible feature, you increment the minor version and reset the patch version to 0 (E.g. 1.4.17 -> 1.5.0). When you make a backward-incompatible change, you increment the major version and reset the minor and patch versions to 0 (E.g. 2.6.5 -> 3.0.0).

With Semantic Versioning, you can also use prerelease labels to tag your packages. To use prelease labels, enter a hyphen followed by whatever letter(s) or number(s) you choose: E.g.1.0.0-beta.

Semantic Versioning is supported in Azure Pipelines and can be configured in your NuGet task:

  • Use the same versioning scheme for your builds and packages:

    • $(Major).$(Minor).$(rev:.r), where Major and Minor are two variables defined in your pipeline. This format will automatically increment the build number and the package version with a new patch number. It will keep the major and minor versions constant, until you change them manually.
    • $(Major).$(Minor).$(Patch).$(date:yyyyMMdd), where Major, Minor, and Patch are variables defined in your pipeline. This format will create a new prerelease label for the build and package while keeping the major, minor, and patch versions constant.
  • Use a custom versioning scheme. You can customize the major, minor, and patch versions for your packages and let the NuGet task generate a unique prerelease label based on the date and time. Format: Major.Minor.Patch-ci-datetime. See NuGetCommand@2 for more details.

  • Use a script in your build pipeline to generate the version.

This example shows how to use the date and time as the prerelease label. This will generate a SemVer compliant version formatted as: Major.Minor.Patch-ci-datetime.

variables:
  Major: '1'
  Minor: '0'
  Patch: '0'

steps:
- task: NuGetCommand@2
  inputs:
    command: pack
    versioningScheme: byPrereleaseNumber
    majorVersion: '$(Major)'
    minorVersion: '$(Minor)'
    patchVersion: '$(Patch)'

YAML is not supported in TFS.

Note

DotNetCore and DotNetStandard packages should be packaged with the DotNetCoreCLI@2 task to avoid System.InvalidCastExceptions. See the .NET Core CLI task for more details.

task: DotNetCoreCLI@2
inputs:
    command: pack
    versioningScheme: byPrereleaseNumber
    majorVersion: '$(Major)'
    minorVersion: '$(Minor)'
    patchVersion: '$(Patch)'

Publish NuGet packages

To publish packages to an Azure Artifacts feed from your pipeline, you must set the Project Collection Build Service identity to be a Contributor on your feed. See Configure feed settings for more details.

steps:
- task: NuGetAuthenticate@0
  displayName: 'NuGet Authenticate'
- task: NuGetCommand@2
  displayName: 'NuGet push'
  inputs:
    command: push
    publishVstsFeed: '<projectName>/<feed>'
    allowPackageConflicts: true

To publish a package to an external NuGet feed, you must first create a service connection to connect to that feed. You can do this by going to Project settings > Service connections > New service connection. Select NuGet, and then select Next. Fill out the form and then select Save when you're done. See Manage service connections for more details.

To publish a package to an external NuGet feed, add the following snippet to your YAML pipeline.

- task: NuGetAuthenticate@0
  inputs:
    nuGetServiceConnections: <NAME_OF_YOUR_SERVICE_CONNECTION>
- task: NuGetCommand@2
  inputs:
    command: push
    nuGetFeedType: external
    versioningScheme: byEnvVar
    versionEnvVar: <VERSION_ENVIRONMENT_VARIABLE>

Example using the Command line task (NuGet.exe):

  - task: NuGetAuthenticate@1
    inputs:
      nuGetServiceConnections: <NAME_OF_YOUR_SERVICE_CONNECTION>

  - script: |
      nuget push <PACKAGE_PATH> -src https://pkgs.dev.azure.com/<ORGANIZATION_NAME>/<PROJECT_NAME>/_packaging/<FEED_NAME>/nuget/v3/index.json -ApiKey <ANY_STRING>
    displayName: "Push"          

Example using the Command line task (dotnet):

  - task: NuGetAuthenticate@1
    inputs:
      nuGetServiceConnections: <NAME_OF_YOUR_SERVICE_CONNECTION>

  - script: |
      dotnet build <CSPROJ_PATH> --configuration <CONFIGURATION>
      dotnet pack <CSPROJ_PATH> -p:PackageVersion=<YOUR_PACKAGE_VERSION> --output <OUTPUT_DIRECTORY> --configuration <CONFIGURATION>
      dotnet nuget push <PACKAGE_PATH> --source https://pkgs.dev.azure.com/<ORGANIZATION_NAME>/<PROJECT_NAME>/_packaging/<FEED_NAME>/nuget/v3/index.json --api-key <ANY_STRING>
    displayName: "Build, pack and push"          

Note

The ApiKey is only used as a placeholder.

YAML is not supported in TFS.

Publish to NuGet.Org

  1. Generate an API key

  2. Navigate to your Azure DevOps project and then select gear icon Project settings.

  3. Select Service Connections, and then select New service connection.

  4. Select NuGet, and then select Next.

  5. Select ApiKey as your authentication method. Use the following url for your Feed URL: https://api.nuget.org/v3/index.json.

  6. Enter the ApiKey you generated earlier, and then enter a Service connection name.

  7. Select Grant access permission to all pipelines, and then select Save when you're done.

Add the following YAML snippet to your pipeline definition:

steps:
- task: NuGetCommand@2
  displayName: 'NuGet push'
  inputs:
    command: push
    nuGetFeedType: external
    publishFeedCredentials: nuget.org