Blog Azure Infrastructure Modernization Cloud Native

Azure Verified Modules with Bicep, DevOps Pipelines & GitHub Actions

Most organisations start their cloud journey by manually deploying and managing resources through the Azure Portal — known as “ClickOps”.

A better way is to use Infrastructure as Code (IaC) with Azure Bicep (we love Azure and IaC).

From there, you can standardise your deployments using Azure Verified Modules (AVM).  

This article shows you how to use AVM with Bicep and automate deployment using Azure DevOps Pipelines and GitHub Actions.

Simon Lee

Author

Simon Lee Azure Consultant

Reading time 6 minutes Published: 08 September 2025

What are Azure Verified Modules (AVM)? 

Azure Verified Modules (AVM) are standardised, reusable modules for deploying Azure resources. It ensures compliance, best practices and consistency across cloud infrastructure. 

Azure Verified Modules Publish, Static Validation and Deployment Validation

Instead of defining your resources manually from scratch, you can use AVM Bicep modules to leverage pre-verified, Microsoft-supported templates.

Types of modules in AVM 

Azure Verified Modules (AVM): Pattern Modules and Resource Modules

AVM modules are composable building blocks that encapsulate groups of resources dedicated to one task.  

Used to deploy Azure resources consistently, there are two modules: Pattern Modules and Resource Modules. 

These are further defined in the table below:

Module Class Definition Who is it for?
Resource Module Deploy a primary resource, applying WAF high-priority best practices by default.

For people who want to build bespoke architectures that follow WAF best practices 

For creating pattern modules

Pattern Module Deploys multiple resources, often by using Resource Modules. The goal is to speed up common deployments or architectures.  For people who want to deploy common architectures using WAF best practices quickly.
Utility Module (draft)

Provides a reusable function or routine that can be called from Resource or Pattern Modules (e.g., retrieving the endpoint of an API or portal for a given environment).

It MUST not deploy Azure resources other than deployment scripts.

For people who need shared functions or helpers without re-implementing them in every module.

 

 

Why use Azure Verified Modules (AVM)?  

AVM accelerates the delivery of migrated and cloud-native applications and their supporting infrastructure, reliably, consistently and at scale.

In short, Azure Verified Modules provide:  

  • Standardisation: Microsoft-validated templates ensure compliance with best practices. 
  • Modularity: Encapsulate infrastructure elements into reusable modules. 
  • Security and Compliance: AVM includes built-in policies and guardrails. 
  • Scalability: Reuse modules in multiple environments and teams. 
  • Faster time to ACR: AVM drives faster time to ACR and enhances quality. 

When working with multiple teams, having source control in place is a must for any organisation. It keeps code organised, consistent and well-managed. 

Iac Whitepaper

Want to learn more about how to use Azure Verified Modules?

Read our latest white paper about IaC in Azure and master Azure Bicep with Azure Verified Modules (AVM) and more!

Download the IaC whitepaper for free!

Why CI/CD Matters for Infrastructure 

Adopting a CI/CD automated approach helps your infrastructure align with the pillars of the Well-Architected Framework (WAF) and the Cloud Adoption Framework (CAF). These frameworks set the standard for creating secure, reliable and maintainable environments. 

  • Using a main.bicep file with parameters helps ensure these principles are adhered to while allowing certain values to be adjusted via the parameter file. For example, you could modify the Virtual Machine SKU, adjust backup policies, or enable/disable specific services during the development stage. 
  • You can also use a bicepparam file to simplify testing across dev, test, and production environments, using CI/CD pipelines handling automation based on Environment/Input variables. 
  • CI/CD takes it further by automating checks and enforcing consistency. For example, you can pull requests using PSRule.Rules. Azure, ensuring the bicepparam file is checked and validated before deployment. This keeps best practices at the heart of your infrastructure deployments. 

 

Structuring an AVM-Based Bicep deployment 

Below is an example folder structure to help keep your CI/CD clean and organised. 

Folder structure 

A well-organised AVM-based Bicep project should follow this structure:

/infra
 ├── bicepparam
 │ ├── dev.bicepparam
 │ ├── acc.bicepparam
 │ ├── prod.bicepparam
 ├── main.bicep
 ├── azure-pipelines.yml
 ├── .github/workflows/deploy.yml 

 

Using an Azure Verified Module in main.bicep 

Here’s an example of how to use an Azure Verified Module directly in your main.bicep file to deploy a resource group with standardised parameters.

targetScope = 'subscription'

@description('Customer Name (max 15 characters to prevent long resource names)')
@minLength(3)
@maxLength(15)
param customerName string

@description('Deployment Location')
param location string

@description('Location Short Code (2-4 characters, e.g., "weu" for West Europe)')
@minLength(2)
@maxLength(4)
param locationShortCode string

@description('Environment Type')
@allowed([
  'dev'
  'acc'
  'prod'
])
param environmentType string

// Resource Group Naming Convention
var resourceGroupName = 'rg-${customerName}-${environmentType}-${locationShortCode}'

// Storage Account Name
@description('Storage Account Name (must be unique, 3-24 characters, lowercase)')
@minLength(3)
@maxLength(24)
param storageAccountName string

// Azure Verified Modules - Start Here
module createResourceGroup 'br/public:avm/res/resources/resource-group:0.4.1' = {
  name: 'create-resource-group'
  params: {
    name: resourceGroupName
    location: location
  }
}

module storageAccount 'br/public:avm/res/storage/storage-account:0.17.0' = {
  name: 'create-storage-account'
  scope: resourceGroup(resourceGroupName)
  params: {
    name: storageAccountName
    location: location
    kind: 'StorageV2'
    skuName: 'Standard_LRS'
  }
}

 

Environment-Specific Parameters

(bicepparam/dev.bicepparam)

using './main.bicep'

param customerName = 'contoso'
param location = 'westeurope'
param locationShortCode = 'weu'
param environmentType = 'dev'
param storageAccountName = 'stcontosodevweu' // must be lowercase and static

 

Deploying AVM Modules Using Azure DevOps Pipelines

If you’re using Azure DevOps, you can automate the deployment of Azure Verified Modules with a pipeline defined in azure-pipelines.yml.

Here’s an example: 

Pipeline YAML (azure-pipelines.yml)

name: Infrastructure Deployment
trigger:
  - main

pool:
  vmImage: ubuntu-latest

parameters:
  - name: subscriptionId
    displayName: Subscription Id
    type: string
    default: ''
  - name: environmentType
    displayName: Deployment Environment
    type: string
    default: dev
    values:
      - dev
      - acc
      - prd

steps:
  - task: AzureResourceManagerTemplateDeployment@3
    inputs:
      azureResourceManagerConnection: '<azureResourceConnectionId>'
      deploymentScope: Subscription
      subscriptionId: ${{ parameters.subscriptionId }}
      location: westeurope
      templateLocation: 'Linked artifact'
      csmFile: './infra/main.bicep'
      csmParametersFile: 'infra/bicepparam/${{ parameters.environmentType }}.bicepparam'
      deploymentMode: Incremental

 

GitHub Actions

If your organisation is more comfortable using GitHub Actions, We have you covered. Here is an example workflow. 

Deploying AVM Modules Using GitHub Actions Workflow YAML (.github/workflows/deploy.yml)

name: Infrastructure Deployment

on:
  workflow_dispatch:
    inputs:
      subscriptionId:
        description: Azure Subscription ID
        required: true
      environment:
        description: Deployment Environment
        required: true
        type: choice
        options:
          - dev
          - acc
          - prd

permissions:
  id-token: write

jobs:
  deploy:
    runs-on: ubuntu-latest
    env:
      AZURE_SUBSCRIPTION_ID: ${{ inputs.subscriptionId }}
      AZURE_ENVIRONMENT: ${{ inputs.environment }}
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Azure Login
        uses: azure/login@v1
        with:
          client-id: ${{ secrets.AZURE_CLIENT_ID }}
          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          subscription-id: ${{ env.AZURE_SUBSCRIPTION_ID }}

      - name: Deploy Bicep Template
        uses: azure/arm-deploy@v1
        with:
          subscriptionId: ${{ env.AZURE_SUBSCRIPTION_ID }}
          scope: 'subscription'
          region: 'westeurope'
          template: './infra/main.bicep'
          parameters: './infra/bicepparam/${{ env.AZURE_ENVIRONMENT }}.bicepparam'
          deploymentMode: 'Incremental'

 

Best Practices for AVM Deployment

While using the Azure Verified Modules is the way to go, let’s look at some best practices regarding authentication and validation: 

Best practice 1: Authentication best practices

Best practice 2: Validation before deployment

  • Run az bicep build to validate module syntax before deployment.
  • Use az deployment sub what-if to preview changes before applying. 
Note

Using the –what-is flag will not work within a pipeline, as it requires you to complete a key entry to validate the what if with [Y] [Microsoft Learn].

Best practice 3: Reusability and scalability

  • Store modules in an Azure Bicep Registry for centralised management. 
  • Use AVM to leverage pre-tested, best-practice modules instead of custom ones.

 

Closing thoughts 

We’ve covered how AVM and CI/CD can automate and scale deployment and make your infrastructure in Azure more modular, reusable, and compliant. 

By using AVM Bicep modules in CI/CD workflows, you can create a scalable, compliant, and maintainable cloud infrastructure, while also improving efficiency and security. 

Intercept Camera Robot (1)

Free Infrastructure Scan

Infrastructure issues often go unnoticed... until it’s too late. Act now to prevent costly disruptions, scaling problems, or system failures. 

Request your free infrastructure scan now!