Pipeline CI/CD para Bicep no Azure DevOps — lint, validação, what-if e deploy
1) Visão geral
Vamos configurar um pipeline que faz build e lint do Bicep, executa what-if e, com aprovação, realiza o deploy no Azure. Usaremos Azure Resource Manager (classic) ou Workload Identity/OIDC via Service Connection, agentes hospedados ubuntu-latest e a CLI az com a extensão deployment.
2) Estrutura do repositório
/.azure-devops
pipelines/
bicep-ci.yml # pipeline principal
/bicep
main.bicep # template raiz
modules/ # módulos reutilizáveis
parameters/
dev.parameters.json
prod.parameters.json
scripts/
validate.sh # (opcional) validações extras
3) Service Connection
No Azure DevOps, crie um Service connection do tipo Azure Resource Manager (preferencialmente com Workload Identity Federation) com acesso à Subscription e Resource Group desejados. Dê permissão ao pipeline (Grant access permission to all pipelines).
4) Pipeline YAML (CI/CD)
Salve como .azure-devops/pipelines/bicep-ci.yml. Este exemplo executa lint/build, publica artefatos, roda what-if e faz deploy em ambiente com aprovações.
# .azure-devops/pipelines/bicep-ci.yml
trigger:
branches: { include: [ main ] }
paths: { include: [ 'bicep/*', '.azure-devops/pipelines/bicep-ci.yml' ] }
pr:
branches: { include: [ main ] }
variables:
- name: azureSubscription
value: 'SC-Azure-Prod' # Service connection name
- name: location
value: 'brazilsouth'
- name: rgName
value: 'rg-bluecloud-prod'
- name: bicepFile
value: 'bicep/main.bicep'
- name: paramsFile
value: 'bicep/parameters/dev.parameters.json'
stages:
- stage: CI
displayName: 'CI - Build & Lint'
jobs:
- job: Build
pool: { vmImage: 'ubuntu-latest' }
steps:
- task: AzureCLI@2
displayName: 'Bicep version'
inputs:
azureSubscription: $(azureSubscription)
scriptType: bash
scriptLocation: inlineScript
inlineScript: |
az bicep version || az bicep install
- script: |
az bicep build --file $(bicepFile) --outfile out/azure.json
displayName: 'bicep build'
- script: |
az bicep build --file $(bicepFile) --stdout | jq . > out/azure.pretty.json
displayName: 'format json (opcional)'
- task: PublishBuildArtifacts@1
inputs:
PathtoPublish: 'out'
ArtifactName: 'bicep-build'
publishLocation: 'Container'
- stage: PREVIEW
displayName: 'Preview - What-if'
dependsOn: CI
jobs:
- deployment: WhatIf
environment: 'preview'
strategy:
runOnce:
deploy:
steps:
- task: AzureCLI@2
displayName: 'what-if'
inputs:
azureSubscription: $(azureSubscription)
scriptType: bash
scriptLocation: inlineScript
inlineScript: |
az group create -n $(rgName) -l $(location)
az deployment group what-if \
--resource-group $(rgName) \
--template-file $(bicepFile) \
--parameters @$(paramsFile) \
--no-pretty-print false
- stage: CD
displayName: 'CD - Deploy'
dependsOn: PREVIEW
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
jobs:
- deployment: Deploy
environment: 'prod' # configure approvals neste ambiente
strategy:
runOnce:
deploy:
steps:
- task: AzureCLI@2
displayName: 'Deploy group'
inputs:
azureSubscription: $(azureSubscription)
scriptType: bash
scriptLocation: inlineScript
inlineScript: |
az group create -n $(rgName) -l $(location)
az deployment group create \
--resource-group $(rgName) \
--template-file $(bicepFile) \
--parameters @$(paramsFile) \
--confirm-with-what-if false
5) Variáveis e parâmetros
Mantenha parâmetros por ambiente em bicep/parameters/*.json. Exemplo:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"environmentName": { "value": "dev" },
"tags": { "value": { "owner": "bluecloud", "costCenter": "it" } }
}
}
6) What-if: valide mudanças antes do deploy
O comando az deployment group what-if mostra criações, atualizações e remoções previstas, reduzindo riscos. Em PRs, você pode postar o diff como comentário usando um job condicional.
7) Ambientes e aprovações
Use Environments do Azure DevOps para mapear preview e prod. Configure Approvals and Checks (por exemplo, aprovadores, branch protection, limites de horário, verificações manuais) antes de executar a stage CD.
8) Boas práticas
- Habilite lint via
bicepconfig.jsoncom regras de nomenclatura e parâmetros obrigatórios. - Separe variáveis sensíveis em Variable groups ou Azure Key Vault (vinculado ao pipeline).
- Versione artefatos e gere
CHANGELOGvia Conventional Commits. - Para assinaturas múltiplas, parametrize
subscriptionIde use múltiplos service connections. - Em projetos complexos, prefira deployments no scope de subscription/management group.
--template-file por --template-spec se você publicar Template Specs e quiser versionamento centralizado.