- Infrastructure as Code with ARM Templates and Bicep: Part 1 – ARM Template Fundamentals
- Infrastructure as Code with ARM Templates and Bicep: Part 2 – Building Production-Ready Infrastructure
- Infrastructure as Code with ARM Templates and Bicep: Part 3 – Advanced ARM Template Patterns
- Infrastructure as Code with ARM Templates and Bicep: Part 4 – Introduction to Bicep
- Infrastructure as Code with ARM Templates and Bicep: Part 5 – Advanced Bicep Patterns
- Infrastructure as Code with ARM Templates and Bicep: Part 6 – CI/CD Integration and Advanced Deployment
- Infrastructure as Code with ARM Templates and Bicep: Part 7 – Enterprise Governance and Compliance

This part focuses on integrating Bicep templates with CI/CD pipelines, implementing advanced deployment strategies, and establishing robust testing and validation practices for enterprise-scale Infrastructure as Code.
What You’ll Learn
- Advanced CI/CD pipeline patterns
- Blue-green and canary deployment strategies
- Automated testing and validation
- Secret management and security practices
- Multi-environment deployment strategies
GitHub Actions Workflow
name: Infrastructure as Code - Bicep
on:
push:
branches: [main, develop]
paths: ['infrastructure/**']
jobs:
lint-and-validate:
name: Lint and Validate Templates
runs-on: ubuntu-latest
steps:
- name: Checkout
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: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- name: Lint Bicep Files
run: |
cd infrastructure/bicep
for file in $(find . -name "*.bicep"); do
az bicep build --file "$file" --stdout > /dev/null
done
- name: Validate Templates
run: |
for env in dev staging prod; do
az deployment sub validate \
--location eastus \
--template-file infrastructure/bicep/main.bicep \
--parameters @infrastructure/parameters/$env.bicepparam
done
deploy-dev:
name: Deploy to Development
needs: lint-and-validate
environment: development
steps:
- name: Deploy Infrastructure
run: |
az deployment sub create \
--location eastus \
--template-file infrastructure/bicep/main.bicep \
--parameters @infrastructure/parameters/dev.bicepparam
Blue-Green Deployment Pattern
// Blue-Green deployment pattern for App Services
@description('Application name')
param appName string
@description('Deployment slot to deploy to')
@allowed(['blue', 'green', 'staging'])
param deploymentSlot string = 'staging'
// App Service Plan
resource appServicePlan 'Microsoft.Web/serverfarms@2023-01-01' = {
name: 'asp-${appName}'
location: resourceGroup().location
sku: {
name: 'S1'
capacity: 1
}
}
// Main App Service
resource appService 'Microsoft.Web/sites@2023-01-01' = {
name: 'app-${appName}'
location: resourceGroup().location
properties: {
serverFarmId: appServicePlan.id
httpsOnly: true
siteConfig: {
healthCheckPath: '/health'
appSettings: [
{
name: 'DEPLOYMENT_SLOT'
value: 'production'
}
]
}
}
}
// Deployment Slot
resource deploymentSlotResource 'Microsoft.Web/sites/slots@2023-01-01' = {
parent: appService
name: deploymentSlot
location: resourceGroup().location
properties: {
serverFarmId: appServicePlan.id
siteConfig: {
healthCheckPath: '/health'
appSettings: [
{
name: 'DEPLOYMENT_SLOT'
value: deploymentSlot
}
]
}
}
}
// Outputs
output appServiceUrl string = 'https://${appService.properties.defaultHostName}'
output deploymentSlotUrl string = 'https://${deploymentSlotResource.properties.defaultHostName}'
Automated Testing Framework
// Integration test template
@description('Target environment to test')
param targetEnvironment string
// Test execution using Azure Container Instances
resource integrationTestContainer 'Microsoft.ContainerInstance/containerGroups@2023-05-01' = {
name: 'integration-tests-${targetEnvironment}'
location: resourceGroup().location
properties: {
osType: 'Linux'
restartPolicy: 'Never'
containers: [
{
name: 'test-runner'
properties: {
image: 'mcr.microsoft.com/azure-cli:latest'
command: [
'/bin/bash'
'-c'
'''
echo "Starting integration tests..."
# Health Check Test
APP_URL="https://app-webapp-${targetEnvironment}.azurewebsites.net"
HEALTH_URL="$APP_URL/health"
if curl -f -s $HEALTH_URL; then
echo "✅ Health check passed"
else
echo "❌ Health check failed"
exit 1
fi
echo "All tests passed!"
'''
]
}
}
]
}
}
Secret Management
// Key Vault for secure secret management
@description('Application name')
param appName string
@description('Environment name')
param environment string
// User-assigned managed identity
resource appIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
name: 'id-${appName}-${environment}'
location: resourceGroup().location
}
// Key Vault
resource keyVault 'Microsoft.KeyVault/vaults@2023-07-01' = {
name: 'kv-${appName}-${environment}-${uniqueString(resourceGroup().id)}'
location: resourceGroup().location
properties: {
tenantId: tenant().tenantId
sku: {
family: 'A'
name: environment == 'prod' ? 'premium' : 'standard'
}
enableRbacAuthorization: true
enablePurgeProtection: environment == 'prod'
publicNetworkAccess: environment == 'prod' ? 'Disabled' : 'Enabled'
}
}
// RBAC assignment for application
resource appIdentitySecretUserRole 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(keyVault.id, appIdentity.id)
scope: keyVault
properties: {
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6')
principalId: appIdentity.properties.principalId
principalType: 'ServicePrincipal'
}
}
// Outputs
output keyVaultId string = keyVault.id
output appIdentityId string = appIdentity.id
Best Practices
- Security: Use managed identities, implement RBAC, enable Key Vault
- Deployment: Use infrastructure as code, implement automated testing
- Monitoring: Implement logging, set up alerts, use Application Insights
- Operations: Implement backups, use auto-scaling, proper tagging
What’s Next?
In Part 7, we’ll explore enterprise governance patterns, compliance automation, and advanced cost optimization strategies.
This is Part 6 of our 7-part series on Infrastructure as Code with ARM Templates and Bicep.