Menu Close

From Bicep to ARM Template specs with Azure DevOps

In my previous post, I showed how to get started with Azure ARM Template specs. I’m excited to say that this week, the announcement came that Template specs are now General Available. This means Microsoft supports them and they are ready for production. So in this post, I want to focus on how to make this in production ready solution. We will go from Bicep to ARM Template specs with Azure DevOps.

But why

As mentioned in my previous post, I think Template specs can be very helpful when working with landing zones. It gives you the opportunity to easily share resources that comply with your security standards. As environments with landing zones are often large, you will need a structured way to manage and deploy the templates.

What will we create

I will show you one way to work with Template specs. Of course, there are multiple options and as there is still a lot of development going on, other ways might be available later. I made this post as an inspiration on how you can manage your template specs.

We start with Bicep templates as I think they make working with enterprise deployments a lot easier, thanks to modules.
We will build these files into ARM templates that can be reviewed or automatically tested.
For deployment, I have created a custom PowerShell script.

Note: Template specs can be deployed through ARM templates. But as described here, the Az CLI or PowerShell is recommended. This is why I chose this route.


Note: While Bicep is now a Microsoft supported solution, it is still in preview and breaking changes could still happen. If you are not comfortable with using preview services, you can change the build part of the pipeline to allow usage with ARM templates.

The files in the repository

To use as an example for this guide, I have created a few Bicep templates.
They are pretty basic, but I’ve added two variablessomething to each file that I want to use as a template spec:

  • templateSpecName to define the name of the Template Spec
  • version to define the version of the Template Spec

These will be used when deploying the new template specs to decide if an update is needed. They are also tags for the resources in the Template.

Variables in the bicep file

Note: at this point, this script only works for numbered versioning with a maximum of one point (so 1 or 1.1). It does not work with semantic versioning, I will try to add that in the future.

If you want to follow along, you can create a fork of my repository. You can find it here on GitHub.

Build: Turning Bicep into ARM

For a detailed guide on how to build the templates and create the starter pipeline, you can check out the build stage in a previous post on Bicep in Azure DevOps. We will only change the step where the templates are actually build. In the previous post, we only created one ARM template. In this version, we want to change all the bicep files into ARM templates. To do that, we use a few lines of PowerShell / AZ cli:

$Biceps = Get-ChildItem $Path -Recurse -Include *.bicep
$Biceps | Foreach-Object {
    az bicep build --file $_.FullName --outfile "$(Build.ArtifactStagingDirectory)/$($_.BaseName).json" 


This way we create a template out of all the bicep files in the repo. The start of your pipeline should now look like this:

(don’t forget to change the variables to names that fit your environment.)


After the templates are build, this would be a nice place to perform testing and maybe manual checks on the ARM templates. To find out more about ways of testing your arm templates, find my previous post on Testing ARM templates or more specifically testing with What-If in a pipeline. For simplicity I will not create testing for this post.

Deploying the template specs

To deploy the Template specs, I make use of a PowerShell script, which you can find here on GitHub. This script does the following:

  • It collects all the JSON files in the repository. This should only be the files that were created in the build stage.
  • It looks for the templates that contain TemplateSpecName and TemplateSpecVersion in the Variables. Only these files are considered for deployment.
  • It checks in Azure if a Template Spec with that name already exists. If it does, it will check if the version in the repository is newer.
  • It will deploy the template spec only if the version in the repository is newer than the one in Azure.

Note: Because the script works with JSON files, you can also use this script for ARM templates directly.

In the pipeline, this will look like this


The full pipeline file is available here on GitHub.

The pipeline will deploy all Template specs to Azure.

From Bicep to ARM Template specs with Azure DevOps: new resources in the portal

When you change the version in a bicep file in the repository, this version will automatically be deployed

From Bicep to ARM Template specs with Azure DevOps: Versioning in the portal


So this is a way to automate deploying from Bicep to ARM Template specs with Azure DevOps. I love this new technology and think creating a CICD pipeline can really help bring it to an enterprise level.

The full repository with all files used can be found here on GitHub.

If you have any questions or remarks, let me know in the comments!

1 Comment

Leave a Reply

Your email address will not be published. Required fields are marked *