Microsoft Azure
Intermediate 14 min read Microsoft Azure

Azure Pipelines & Infrastructure as Code

Azure DevOps Pipelines runs multi-stage build and release pipelines for any language on Microsoft-hosted or self-hosted agents. Terraform and Bicep describe Azure infrastructure in code so environments are reproducible. Learn how a CI/CD pipeline and IaC toolchain fit together on Azure.

Azure DevOpsPipelinesyaml pipelinebuildreleaseagentTerraformBicepInfrastructure as CodeIaCARM
Introduction

What is this?

Azure Pipelines is the CI/CD engine of Azure DevOps: a YAML or classic pipeline defines stages, jobs and steps that run on Microsoft-hosted agents or your own self-hosted agents, from build through test to deployment. On the infrastructure side, Terraform and Bicep treat Azure resources as code — Bicep is Azure's domain-specific language compiled to ARM templates, while Terraform is the cross-cloud standard. Both enable reviewable, repeatable environments.

Motivation

Why do you need it?

  • Pipelines turn 'it works on my machine' into a tested, reviewed, auditable release path.
  • IaC makes environments reproducible — the same code creates dev, staging and production.
  • Bicep and Terraform diff your intended state against reality, so drift is visible and fixable.
  • Interviewers almost always ask how you ship code and infrastructure safely and repeatably.
  • Both are force multipliers: a single pipeline change updates every release.
Think about it

Mental model

Imagine

A recipe card and a test kitchen

Think of

IaC and Azure Pipelines

The recipe card (Bicep or Terraform) lists every ingredient and step to produce the exact dish (environment) every time. The test kitchen (CI/CD pipeline) runs the recipe end to end, tasters (tests) sample every course, and only approved recipes go to the dining room (production). Because the recipe is versioned, you can replay a past dinner or branch a new menu without risk.

Mechanics

How it works

  • A YAML pipeline defines trigger, stages (Build, Test, Deploy), jobs and steps; agents execute them.
  • Build stages compile, run tests and publish artifacts (or container images to ACR).
  • Release stages download artifacts and apply them with approvals and gates between environments.
  • Bicep files declare Azure resources and parameters; az deployment group create compiles and applies them.
  • Terraform uses a state file to plan and apply changes, so the cloud always matches your code.

Pipeline stages driving infrastructure and application deployment.

Push to main
Build stage
Terraform plan
Approval gate
Apply IaC
Deploy app
Reference

Key commands

az pipelines run --branch main

Queue a pipeline run from the main branch.

az pipelines runs list --status completed

List completed pipeline runs.

terraform init

Initialize Terraform providers and the backend.

terraform plan -out=tfplan

Compute the diff between code and current infrastructure.

terraform apply tfplan

Apply the planned changes.

az deployment group create --resource-group rg-devops --template-file main.bicep --parameters env=staging

Apply a Bicep template to a resource group.

Hands-on

Examples

Run a build and apply infrastructure with Terraform

Run a build and apply infrastructure with Terraform
$ az pipelines run --branch main
Build #20260809.1
Started by: devops-bot
$ terraform init
Initializing the backend...
Terraform has been successfully initialized!
$ terraform plan -out=tfplan
Terraform will perform the following actions:
+ azurerm_resource_group.rg
name = "rg-devops"
Plan: 1 to add, 0 to change, 0 to destroy.
$ terraform apply tfplan
azurerm_resource_group.rg: Creating...
azurerm_resource_group.rg: Creation complete
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

az pipelines run queues a build from main. terraform init prepares the provider and backend, plan computes the diff between code and reality, and apply executes it — creating the resource group. The same three commands replay in every environment, which is the entire point of IaC.

Real world

In production

  • Run a multi-stage pipeline that builds, tests, plans IaC, and applies with an approval gate before production.
  • Store IaC in the same repo as the app so infrastructure changes review like code changes.
  • Use Bicep for Azure-only stacks and Terraform when you manage multi-cloud or existing tooling.
  • Keep state and plan outputs in a locked backend so two pipelines cannot apply conflicting changes.
  • Use environments in Pipelines to gate deploys, hold approvals, and surface deployment history.
Guidelines

Best practices

  • Run terraform plan in CI and apply only after human or automated gate approval.
  • Use workspaces or per-environment directories so dev, staging and prod state never mix.
  • Make pipelines hermetic: pin versions of tools, images and extensions.
  • Fail the build on lint and format checks (terraform fmt, bicep build) before applying anything.
  • Store all secrets in Key Vault / variable groups referenced by the pipeline, never inline.
Watch out

Common mistakes

  • Letting pipelines apply straight to production with no approval or drift check.
  • Sharing one Terraform state across environments, so dev and prod fight over the same resources.
  • Using latest tags for tools and images, breaking builds on unexpected upstream changes.
  • Checking the state file or .tfstate into git — a leak of everything you own.
  • Editing cloud resources by hand and letting IaC drift until the next apply fails catastrophically.
Root cause analysis

Common issues

Error
Terraform apply fails on a resource that already exists
Root cause

The resource was created outside Terraform, or state is stale and drift is unmanaged.

Fix

Run terraform state pull to inspect, import the resource with terraform import, or re-plan after reconciling the difference.

Error
Pipeline job hangs waiting for a self-hosted agent
Root cause

No matching self-hosted agent is online and labeled for the job's demands.

Fix

Start the agent or change the job to a Microsoft-hosted agent pool, and align the demands with what the agent advertises.

Error
az deployment group create rejects the Bicep template
Root cause

A syntax or type error, or a parameter referenced but never passed.

Fix

Run bicep build locally to surface the compile error, then pass all required parameters with --parameters.

When things break

Debugging tips

  • Re-run the failing pipeline stage with the same inputs — flaky stages are usually missing dependency pins.
  • For Terraform, compare the plan against the actual state to see whether drift or a typo caused the diff.
  • Read the first failing step, not the last green one — pipeline failures cascade.
  • Check the agent log for 'denied' messages that reveal permission gaps before the apply stage.
  • Use az pipelines runs show to pull the run and stage status after a failed deployment.
Interviews

Interview checkpoint

Practice

Hands-on lab

Simulate a Plan-Apply-Validate IaC Cycle
20 min · intermediate
In progress
Objectives
  • Write a declarative description of an environment
  • Compute a plan by diffing against the current state
  • Apply the plan to update the environment
  • Detect drift and fix it back to the declared state

Simulate a Plan-Apply-Validate IaC Cycle

20 min · intermediate

0/6 steps
0%
sandbox · Linux sandbox
$
Try these commands
Test yourself

Quick quiz

0/3
1

Which command shows the diff between Terraform code and current infrastructure?

2

Bicep compiles to ARM templates that Azure applies.

3

Two engineers run terraform apply at the same time. What prevents a corrupt state file?

Quick reference

Cheat sheet

Pipelines
StagesBuild, test, deploy phases
JobsUnit of work on an agent
StepsCommands or tasks in a job
ArtifactsDeployable outputs
ApprovalsGates between environments
Infrastructure as Code
BicepAzure DSL, compiles to ARM
TerraformCloud-agnostic, state + plan
terraform initProviders + backend setup
terraform planShow the diff
terraform applyMake reality match code
Go deeper

Official documentation