Distribute your blessed ARM templates with Universal Packages in Azure DevOps

There is a fine-grained balance between full autonomy of a team and arranging things on a more central level.  One of the things I talk about, when I talk about shifting to Rugged DevOps, is the use of blessed libraries, scripts and templates. As an example, if all your teams write their own logging library, you end up with 10 potential vulnerable libraries. If you all use the same logging library, there is only one to maintain and scan. The same goes for scripts and templates. There are many situations where I copy and paste a script or ARM template between Git repositories to obtain the same functionality.

Why do we copy scripts and templates in the first place? There are multiple reasons. But one of them is that in a Azure DevOps Build Pipeline you can point to 1 Git repository. Your secure and reviewed script or template might be in another Git Repo. Another reason might be that you don’t have permission because you are not the “owner” of that code. There are ways to overcome that too, but that is outside the scope of this article.

We have solved the problem of distributing and reuse of other people’s code nicely in many languages. We have NuGet, Maven and NPM. All build for that purpose. Build a library that can be easily distributed and used. For single scripts or in this  case blessed ARM templates there was not a real good way to do this. Until now! The Azure DevOps team released Universal Packages!

Universal Packages

With Universal Packages teams can store artifacts that don’t neatly fit into the “default” package types. A Universal Package is just a collection of files that you’ve uploaded to our service and labelled with a name and version. This makes it an immutable package that can be distributed easily!

Universal Packages can be huge (Tested up to 4TB). Special deduplication and compression technology ensure it is still efficient. You can store anything you like in a Universal Package. Some examples.

  • Configuration scripts and templates (e.g. ARM templates)
  • Database snapshots for integration testing
  • Machine learning training data and models
  • Developer tools and SDKs
  • 3D models and textures

Distributing you Blessed ARM templates

In this blog post I continue using the example of a Blessed ARM template. This template is created, tested and maintained by multiple people. Making sure it is up to date, secure etc.

In the Microsoft Docs article, there is a good step by step how to set this up.

First you need a package feed in Azure Artifacts.


To start, create a Git Repository with your templates.


Then create a Build Pipeline that publishes your Universal Package to your Package feed


Now your package is in your Package Feed


When you click the package you will see the CLI command you can use to get the package locally.

vsts package universal download 
--instance "https://account.visualstudio.com/" 
--feed "DemoFeed" 
--name "rvo.armtemplates" 
--version "3.0.0" 
--path .

Then you can use the Universal Package Download Task in the Release Pipeline to get the package. It is automatically extracted, so you can use the files directly.



Universal packages is a great way to start versioning your shared code. Open up your repos, set branch policies so that everyone can contribute, set up a CI build that publishes packages and let everyone benefit from the shared code. If you want to make it one step further, you can use Release Views and Programmatically promote your package quality with Release Views in VSTS

Cover Photo by chuttersnap on Unsplash


  1. Top Stories from the Microsoft DevOps Community – 2018.10.19 – Art2Dec SoftLab - October 25, 2018

    […] Distribute your blessed ARM templates with Universal Packages in Azure DevOps Moving to “Rugged DevOps” *mdash; and improving the security of your development process — makes you carefully examine the libraries and scripts you rely on and use DevOps practices for managing them. You can even push the results into Azure Artifacts. […]

%d bloggers like this: