Restoring NuGet Packages from Artifactory into Azure DevOps

JFrog Artifactory is a market leader and a decent choice for package management. I’ve just completed a PoC which will hopefully allow us to retire an existing, self-hosted package server.

One hurdle we had to get over was finding a simple way to get Azure DevOps to pull packages from Artifactory as part of our build pipelines. JFrog provide an extension to help with this, but the documentation wasn’t super-easy to follow so here’s a run-through of how we’ve got it working:

Install the Extension

If not, use Browse Marketplace to find and install this extension.

Add a Service Connection to your project

You need to enter the URL to your Artifactory instance as well as authentication details, which will look something like this:

The handy thing here is that this is the only place within your project where you need the authentication details, so as a project admin you can set this up and then anyone else can add or edit builds which pull packages using this connection.

Configure your build Pipeline to restore from Artifactory

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add
key="Artifactory"
value="https://foo.jfrog.io/artifactory/api/nuget/foo-nuget" />
</packageSources>
</configuration>

Unfortunately though, the build step in your pipeline will probably fail at this point. We need to add a step before the build to restore packages from Artifactory, using the service connection. It’s easiest to do this using the interactive yaml editor in the portal first time around - once you have a pattern that works you can just copy the yaml snippet between builds. Start by finding the Artifactory NuGet task:

You’ll see two dropdowns in the dialog, which will automatically populate with available services and repos from Artifactory, which makes it very straightforward to set up:

Fun times with the Global Packages Folder

The yaml generated from adding the task above will look something like this:

- task: ArtifactoryNuGet@2
inputs:
command: 'restore'
artifactoryService: 'foo.jfrog.io'
targetResolveRepo: 'foo-nuget'
solutionPath: '**/*.sln'

This task fetches all your packages from Artifactory but it has to store them somewhere, and by default it puts them into a folder called packages in the root folder of your repository. If you get lucky (see above) then this is the right place for the build step to find them and pick them up, otherwise the build will just try (and fail) to restore packages for itself.

Framework projects use a packages folder in the solution root folder, but NuGet also caches downloaded packages in a global packages folder. Core dispenses with the solution-local packages folder entirely and just uses the global one. So, the best thing to have Artifactory do is to put the downloaded packages into the global packages folder, and the safest way to do that is to override this folder location by setting the NUGET_PACKAGESenvironment variable. Before your build steps, add this variable to your yaml file:

variables:
NUGET_PACKAGES: $(Pipeline.Workspace)/.nuget/packages

You’ve now overridden the global packages folder location and the last thing that you need to do is to tell the Artifactory task to download packages to this folder, so that your builds will will able to find them - see the extra line added to the task below:

- task: ArtifactoryNuGet@2
inputs:
command: 'restore'
artifactoryService: 'foo.jfrog.io'
targetResolveRepo: 'foo-nuget'
solutionPath: '**/*.sln'
packagesDirectory: '$(NUGET_PACKAGES)'

Your build should work now, but let me know if you have any further difficulties!

Caching for improved build performance

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store