I Learned Something - Azure Bicep Local Extensions

Bicep Local Extensions

Azure Bicep has always been focused on the Azure Cloud. However, with an experimental feature, that is going to change.

When creating resources using Infrastructure as Code, regardless of the language, the backing call is using standard API endpoints. IaC is a wrapper around API endpoints, providing readability, structure and enhancements. Terraform already provides a way to create custom Plugins for any API endpoint, and now Bicep has introduced a feature to create Extensions.

I have watched a few demos, including Freek Berson's session at Build 2026 (In the photo of his presentation you can see the back of my hat in the audience), and I had to try it out for myself. Some examples I have seen are, using Bicep to turn on a light using Home Assist, managing Databricks, and managing GitHub Repos. My experiment is creating Work Items in Azure DevOps. This feature has a lot of potential for expanding Bicep outside of the Azure sphere.

Note: As of this blog post, Bicep Local Extensions are Experimental

Extension Overview

GitHub Repository Link

This extension uses the Azure DevOps .NET Client Library to create new Work Items. It can only create a Story, Bug or Product Backlog Item.

This is an example of trying out a new feature. This is not production ready code.

Required Tools

.NET 10.0

  • My example uses .NET 10 but in general .NET 9.0+ is aneeded

Extension Source

src/Program.cs

  • Standard App entrance file
  • The extensions on builder.Services are different than the quickstart example from using .NET 10.

src/AzDOWorkItem.Extension.csproj

  • Packages for Client Libraries
  • Local Extension Package - Azure.Bicep.Local.Extension

src/Handlers/AzDOWorkItemHandler.cs

  • Handler for creating Work Items
  • Code for checking that properties exist
  • Instantiates AzureDevOpsClient for connecting and creating work items

src/Models/Models.cs

  • Model of the parameters to be used in the Bicep template

src/services/AzureDevOpsClient.cs

  • Class with methods to interact directly with the Azure DevOps Client Library
    • Create connection
    • Create Work Items

Publishing Extension

Make sure to update the paths in the publish-extension command to match where dotnet publish creates the files. The path here is slightly different than the documentation.

1dotnet publish --configuration release -r osx-arm64 .
2dotnet publish --configuration release -r linux-x64 .
3dotnet publish --configuration release -r win-x64 .
4
5bicep publish-extension --bin-osx-arm64 ./bin/release/net10.0/osx-arm64/publish/bicep-ext-azdoworkitem --bin-linux-x64 ./bin/release/net10.0/linux-x64/publish/bicep-ext-azdoworkitem --bin-win-x64 ./bin/release/net10.0/win-x64/publish/bicep-ext-azdoworkitem.exe --target ./bin/bicep-ext-azdoworkitem --force

📆 Look for a future post (or update) on publishing to Azure Container Registry

Using Extension in Bicep

Files

infrastructure/bicepconfig.json

  • The experimentalFeaturesEnabled property is required

infrastructure/main.bicep

  • targetScope must be local
  • The extension matches the extension name set in bicep.config
  • VSCode intellisense will recognize and auto populate required properties like it does for standard Bicep templates

infrastructure/parameters/main.bicepparam

  • Required even if no params specified

Azure and AzDO Login

Like deploying standard Bicep templates, it relies on the permissions you have in the terminal where the deploy command is executed.

There are a couple ways to authenticate to AzDO in the terminal for

Use Azure DevOps CLI Extension

1# Login to Azure
2az login
3
4# Set AzDO Default
5az devops configure --defaults organization=https://dev.azure.com/YourOrg project=YourProject
6
7az devops login --organization https://dev.azure.com/YourOrg
8# Enter PAT (Work Item - Read & Write)

Get Access token using Azure CLI

1# Login to Azure
2az login
3
4az account get-access-token --resource https://app.vssps.visualstudio.com

Deployment

A specific bicep command used to deploy the template. An important note is that it uses the .bicepparam file. So even if you have no parameters to pass in, it still needs a .bicepparam file with the using statement pointing to the main template file.

1bicep local-deploy main.bicepparam

Resources

Bicep Local Extension with .NET Quickstart

Cloud Lunch and Learn Example

Community Created Extensions