If you are working on several closed-source projects and have many internal libraries that you wish to share as NuGet packages, you’d be looking for a way to privately host those packages. We had been using Azure DevOps Artifact Feed for this purpose. However, with the release of GitHub Packages we’ve started moving our packages there as all our devs were already on GitHub and we didn’t have to reprovision AzDO Package Management feature for those who weren’t really creating or maintaining build pipelines.
Following is what we did to keep our build pipelines in Azure DevOps and post the NuGet packages that they built in to GitHub Packages.
- An Azure DevOps account
- Access to Azure KeyValut
- A GitHub account with GitHub Packages feature enabled
Prepare your project for GitHub Packages
When publishing the NuGet package you’ll be pushing from the pipeline, you’ll need the
RepositoryUrl element in the project’s
.csproj file to be set properly. Do this either by using the Project Properties screen in Visual Studio, or directly add it in the
Create a GitHub PAT for managing GitHub Packages
In GitHub, click on your profile icon on the top right corner and click
Settings in the drop down menu. Then go to
Developer Settings and then
Personal access tokens. Click on the
Generate new token button and select the following scopes.
Generate token at the bottom of the page and note down the Access Token generated for you.
Create an Azure Key Valut to hold the PAT
On the Azure Portal, create a new Key Vault and add the Access Token as a secret with the name
Create a Build Pipeline in Azure DevOps
Login to your Azure DevOps Organization and create a new Pipeline. Select the Classic Editor to build your pipeline using the wizard UI.
Select to GiHub as the source repository type. You would need to create a new Service Connection at this point, if you had not already setup a GitHub connection before. You can do this using OAuth or by setting up a new GitHub PAT granting the following permissions.
Technically, you can set up one PAT with these permissions as well as the ones from the previous one. However, since you’ll be using these two tokens in different ways, I’d recommend setting up two separate tokens.
ASP.NET Core template.
Pull existing NuGet Packags from GitHub at Build-time
Next, you need the build pipeline to be able to pull in NuGet packages that may already be in GitHub Packages. You can do this by creating a
NuGet.config file that holds the GitHub PAT we created earlier. However, as we wouldn’t want to check this file back in to source control, we’d generate this file at build-time by pulling in the PAT from Azure KeyVault.
Click on the
+ button to add a task to the pipeline. From the available list of tasks, select
Bash Script and move to the top of the pipeline. In the Task Configuration, select
Inline and enter the following script to the
echo ‘ ‘ > NuGet.config
Be sure to replace your_github_org with the name of your GitHub Organization.
When this script runs at build-time, Azure DevOps will replace
$(GitHubPackagesPAT) with a value we’ll expose through Azure KeyVault. You will see how this is done later on.
Next, click on the
Restore task in the pipeline (which should be the 2nd task), and select
Feeds from my NuGet.config option under
Feeds to use. In
Path to NuGet.config just type in
NuGet.config as the above script will create the file at the root.
Push the built NuGet package to GitHub Packages
Remove the last two tasks (
Publish Artifact) tasks from the pipeline. Then add a
NuGet task at the end. Configure the task as below, setting the
push. Be sure to change
Path to NuGet package(s) to publish to,
External NuGet server (including other accounts/collections) under
Target feed location. Then create a new service connection for the
Note that your
Feed URL will take the form of
The username will also be your_github_org.
The pipeline tasks are now setup. Hit
Save (rather than
Save & Queue) to save up to now.
Setup Pipeline Variables
Pipeline on the left navigation pane, click on
+ Variable group button.
Give the Variable group a name and turn on the option to
Link secrets from Azure key vault as variables.
Switch to the
Variables tab and click on
Variable Groups. Now click the
Link variable group button. Pick your
Azure Subscription and Authorize it. Then pick the key vault and authorize it.
+ Add button under
Variables and pick
GitHubPackagesPAT from the popup window. Click
Now go back to your pipeline and switch to the
Variables tab. Then click on
Variable groups and then
Link variable group button. From the
Link variable group flyout, select the variable group you created earlier and click
You have just setup the mapping for the
$(GitHubPackagesPAT) variable you used in the Bash script.
Queue the Pipeline
Can go ahead and do a bit more configuration on Triggers and Options tab in the pipeline. However, as far as the core build pipeline is concerned, you are ready to execute. You can go ahead and queue it now.