Azure DevOps - Always Be Shipping!

Azure DevOps – how to package a single DLL?

This post was most recently updated on November 11th, 2019.

Reading Time: 3 minutes.

Okay – a quick piece of documentation that was a bit lackluster, so it’s again a good idea to log somewhere. How to package a simple DLL that’s a result of your Azure DevOps Pipeline?

In my particular case, I have configured a post-build step to obfuscate the DLL, that’s first built by MSBuild. That works nicely. However, the default way to create a NuGet package, where you select a project (usually you pass the same variable to NuGet pack command that you used earlier for your VSBuild command), doesn’t work here: instead, you need to specify a nuspec file.

What’s a nuspec file?

A nuspec file is an XML manifest file, that contains the metadata for a NuGet package. In our case, it’s used by the Azure DevOps build pipeline to pack our solution into an actual NuGet package, that can then be pushed to a package stream or distributed some other way.

While Visual Studio doesn’t have a template for it out-of-the-box, you can just create an empty file, copy-paste the template below into it and replace the node values with your own:

<?xml version="1.0"?>
<package>
  <metadata>
    <id>[yournugetname]</id>
    <version>[semver-compatible version (such as major.minor.patch - or 1.0.32)]</version>
    <authors>[You]</authors>
    <owners>[You]</owners>
    <requireLicenseAcceptance>[true/false]</requireLicenseAcceptance>
    <description>[Description is actually required.]</description>
    <releaseNotes>[Link or something]</releaseNotes>
    <copyright>[Your copyright statement]</copyright>
    <tags>[Any tags you might have]</tags>
  </metadata>
  <files>
    <file src="bin\Release\net45\Obfuscated\*.dll" target="lib\net45" />
  </files>
</package>

Pay close attention to the <files>-section – that’s where you specify which file or files you’ll include in the NuGet package you’re creating. In my case, I’m grabbing my obfuscated DLL (built with Release configuration) and drop it into lib\net45 (because it is, please stop laughing, built with .NET Framework 4.5).

If you’re using something else than .NET Framework 4.5, please adjust the values accordingly.

This file needs to be committed to Azure DevOps with your project. While it’s not (to my knowledge, anyway) a requirement to have the file named like the project, I’d consider it a good practice to name your nuspec file like this: “[yourprojectname].nuspec

How to package a DLL into a NuGet package using Azure DevOps?

Okay, so how’s this work in practice? Well, first you’ll need the nuspec file you just created earlier. Once you’ve committed that to Azure DevOps, configure a new build pipeline. You need a step for building, another one for packing, and finally a third one for pushing your package.

Below, you can see a simple example of such YAML build definition:

# ASP.NET
# Build and test ASP.NET projects.
# Add steps that publish symbols, save build artifacts, deploy, and more:
# https://docs.microsoft.com/azure/devops/pipelines/apps/aspnet/build-aspnet-4

trigger:
- master

pool:
  vmImage: 'VS2017-Win2016'

variables:
  solution: '**/[yourprojectname].csproj'
  buildPlatform: 'AnyCPU'

steps:
- task: [email protected]

- task: [email protected]
  inputs:
    restoreSolution: '$(solution)'
    packagesdirectory: '..\packages'

- task: [email protected]
  inputs:
    solution: '$(solution)'
    msbuildArgs: '/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:PackageLocation="$(build.artifactStagingDirectory)"'
    platform: '$(buildPlatform)'
    configuration: '$(buildConfiguration)'
 

- task: [email protected]
  inputs:
    command: pack
    packagesToPack: '**/[yourprojectname].csproj.nuspec'
    versioningScheme: byEnvVar
    versionEnvVar: PackageVersion
    packDestination: '$(Build.ArtifactStagingDirectory)\nugetpkg'

- task: [email protected]
  displayName: 'NuGet push'
  inputs:
    command: push
    publishVstsFeed: '[YourInternalAzureDevOpsNuGetFeed]'
    allowPackageConflicts: true

That’s it! Nice and simple, but figuring out the right way to go about it took a while.

References

Antti K. Koskela

Antti Koskela is a proud digital native nomadic millennial full stack developer (is that enough funny buzzwords? That's definitely enough funny buzzwords!), who works as a Solutions Architect for Valo Intranet, the product that will make you fall in love with your intranet. Working with the global partner network, he's responsible for the success of Valo deployments happening all around the world.

He's been a developer from 2004 (starting with PHP and Java), and he's been bending and twisting SharePoint into different shapes since MOSS. Nowadays he's not only working on SharePoint, but also on .NET projects, Azure, Office 365 and a lot of other stuff.

This is his personal professional (e.g. professional, but definitely personal) blog.
mm

Leave a Reply

avatar
5000
  Subscribe  
Notify of