AZ-204Chapter 84 of 102Objective 1.3

Azure DevOps Pipelines for Developers

This chapter covers Azure Pipelines, the CI/CD service in Azure DevOps that enables developers to automate builds, tests, and deployments. For the AZ-204 exam, this is a critical topic under Objective 1.3 (Integrate caching and content delivery within solutions) but also spans CI/CD automation. Approximately 10-15% of exam questions touch on Azure DevOps Pipelines, focusing on YAML pipelines, triggers, agents, variables, and integration with Azure services. You will need to know how to define a pipeline, configure continuous integration and continuous delivery, use multi-stage pipelines, and secure secrets. This chapter provides the deep technical foundation you need to answer those questions confidently.

25 min read
Intermediate
Updated May 31, 2026

The Automated Build Kitchen

Imagine a restaurant kitchen that must produce hundreds of identical meals daily. A single chef cannot do everything manually — they need an assembly line. Azure Pipelines is like a programmable kitchen automation system. The pipeline YAML file is the recipe card that specifies every step: prep ingredients (restore dependencies), cook (build code), season (run tests), plate (package artifacts), and deliver to the dining room (deploy to Azure). Each step runs in a clean workstation (agent) that is provisioned fresh for every meal (build). The system can run multiple orders in parallel (parallel jobs) and can automatically re-try a step if a burner fails (retry policy). It can also trigger a new meal whenever the recipe changes (CI trigger) or when the head chef approves a tasting (approval gate). The key mechanism is the pipeline's state machine: it tracks which steps completed, which are running, and which failed, and it can branch based on conditions (if/else logic). Just as a kitchen manager monitors the line, Azure Pipelines logs every action, so you can see exactly where a build failed and why. This automation ensures consistency, speed, and reliability — no burnt meals.

How It Actually Works

What is Azure Pipelines?

Azure Pipelines is a cloud-based CI/CD service that automatically builds, tests, and deploys your code. It supports any language, platform, and cloud. The exam focuses on YAML-based pipelines (not classic editor) because YAML pipelines are defined as code, versioned, and repeatable.

How It Works Internally

A pipeline is a series of steps executed by an agent. The agent can be Microsoft-hosted (Ubuntu, Windows, macOS) or self-hosted (your own VM). When a trigger event occurs (e.g., code push to a branch), Azure Pipelines allocates an agent, pulls the pipeline definition from the repository, and executes each job sequentially or in parallel. Each job runs in an isolated environment, and artifacts can be passed between stages.

Key Components

Pipeline: The definition of the CI/CD process, written in YAML.

Stage: A logical boundary in the pipeline (e.g., Build, Test, Deploy).

Job: A set of steps that run on the same agent.

Step: The smallest unit of work (e.g., a script, a task).

Task: A pre-built action (e.g., DotNetCoreCLI@2, AzureWebApp@1).

Agent: The compute resource that runs the job.

Trigger: Defines when the pipeline runs (CI, PR, scheduled).

Variable: A name-value pair passed to the pipeline.

Artifact: Output of a build that can be consumed by a release.

Defaults and Timers

Timeout: Each job has a default timeout of 60 minutes. You can override with timeoutInMinutes.

Retry: Tasks can have retryCountOnTaskFailure (up to 3).

Parallel jobs: Free tier includes 1 parallel job (Microsoft-hosted). Paid accounts get more.

Agent queue: Microsoft-hosted agents have a queue time limit of 30 minutes.

Cache: Pipeline caching can store dependencies (e.g., npm packages) with a configurable key.

Configuration Commands

Pipeline definition example (YAML):

trigger:
- main

pool:
  vmImage: 'ubuntu-latest'

variables:
  buildConfiguration: 'Release'

steps:
- task: DotNetCoreCLI@2
  inputs:
    command: 'build'
    arguments: '--configuration $(buildConfiguration)'
- task: DotNetCoreCLI@2
  inputs:
    command: 'test'
    arguments: '--configuration $(buildConfiguration)'
- task: DotNetCoreCLI@2
  inputs:
    command: 'publish'
    publishWebProjects: true
    arguments: '--configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)'

- task: PublishBuildArtifacts@1
  inputs:
    PathtoPublish: '$(Build.ArtifactStagingDirectory)'
    ArtifactName: 'drop'

Interaction with Related Technologies

Azure Repos: Source control; pipeline triggers on push/PR.

Azure Artifacts: Store packages; pipeline can publish and consume.

Azure Key Vault: Store secrets; pipeline can fetch via variable group linked to Key Vault.

Azure App Service: Deploy web apps using AzureWebApp@1 task.

Azure Functions: Deploy using AzureFunctionApp@1.

Azure Container Registry: Build and push container images.

Advanced Concepts

Multi-stage pipelines: Define build, test, and deploy stages in one YAML file, with dependencies and conditions.

Environment: A collection of resources (e.g., VMs, Kubernetes) with approval checks and gates.

Approvals: Manual approval before a stage runs.

Checks: Automatic gates like branch policy, required template, or Azure Monitor alerts.

Templates: Reusable YAML snippets to avoid duplication.

Variables: Use $(var) syntax. Can be set in YAML, UI, or variable groups.

Secure files: Upload and use files (e.g., .pfx) securely.

Exam-Specific Details

YAML schema: Know the structure: trigger, pool, variables, steps, stages.

Predefined variables: Build.BuildId, Build.BuildNumber, Build.SourceBranch, Build.ArtifactStagingDirectory, Agent.JobStatus.

Conditions: always(), succeeded(), failed(), succeededOrFailed().

DependsOn: Control stage/job execution order.

Matrix strategy: Run a job with multiple configurations in parallel.

Deployment jobs: Special job type for deploying to environments with lifecycle hooks (pre-deploy, deploy, post-deploy).

Common Pitfalls

Missing trigger: If no trigger is defined, pipeline runs only manually.

Agent pool exhaustion: Microsoft-hosted agents have limited concurrency; builds may queue.

Variables not expanded: Ensure proper syntax $(variable) and that the variable is defined at the correct scope.

Artifact path issues: Use $(Build.ArtifactStagingDirectory) as the staging directory.

Performance Considerations

Pipeline caching: Cache npm, NuGet, or Maven packages to speed up builds.

Parallelism: Use strategy: with matrix: or parallel: to run jobs concurrently.

Self-hosted agents: For large builds, use your own VMs to avoid queue times and control environment.

Clean builds: Use clean: true on checkout to avoid stale artifacts.

Security

Secrets: Use Azure Key Vault or pipeline secret variables (encrypted). Never hardcode.

Permissions: Use branch policies to require builds to succeed before merging.

Agent isolation: Each job runs in a fresh container or VM; no state leaks.

Monitoring

Logs: Each step logs output; view in pipeline run UI.

Alerts: Configure notifications for pipeline failures.

Analytics: Pipeline analytics show duration, success rate, and trends.

Walk-Through

1

Define Trigger Condition

Specify which events start the pipeline. Common triggers include `trigger:` for CI (code push) and `pr:` for pull request validation. The default trigger is `trigger: none`, meaning manual only. You can use wildcards like `trigger: - main` to run on pushes to main branch. For scheduled triggers, use `schedules:` with cron syntax. The exam tests that you know `trigger:` and `pr:` are separate; a PR trigger runs when a PR is created or updated, not on branch pushes.

2

Select Agent Pool

Define `pool:` to choose where the pipeline runs. Use `vmImage: 'ubuntu-latest'` for Microsoft-hosted agents. For self-hosted agents, specify the pool name (e.g., `name: 'MyPool'`). The agent must have the required tools. Microsoft-hosted agents come with many tools pre-installed (see `software` report). If a tool is missing, you can install it via a script or use a custom container. The exam may ask about using `container:` to run inside a Docker container.

3

Define Variables

Variables can be defined at the pipeline, stage, or job level. Use `variables:` section with name-value pairs. Predefined variables like `Build.BuildNumber` are available automatically. To use a variable, reference it as `$(variableName)`. Variables can also be set via the UI as pipeline variables or variable groups. Secret variables are encrypted and cannot be used directly in logs; they are accessed via `$(secretName)`. The exam tests that you know how to override variables using `variables:` in YAML and that runtime variables can be set with `##vso[task.setvariable]`.

4

Add Steps and Tasks

Steps are the actions performed by the agent. They can be scripts (`script:` or `bash:`) or tasks (e.g., `DotNetCoreCLI@2`). Tasks are community or Microsoft-provided. Each task has inputs. You can also run inline PowerShell or bash. The order of steps is sequential. You can use conditions like `condition: succeeded()` to run a step only if previous steps succeeded. The exam tests that you know how to use `displayName` for readability and that `continueOnError: true` keeps the pipeline running even if a step fails.

5

Build and Publish Artifacts

After building code, you typically publish artifacts for later stages. Use `PublishBuildArtifacts@1` task to upload files from `$(Build.ArtifactStagingDirectory)` to Azure Pipelines. Artifacts are stored and can be downloaded in subsequent stages. For container images, use `Docker@2` task to build and push to a registry. The exam may ask about artifact names and how to consume them in a release pipeline. Note that artifacts are not automatically passed between stages; you must use `download: current` in the consuming stage.

6

Configure Deployment Stage

For CD, add a deployment job (`deployment:` keyword) that targets an environment. Deployment jobs have lifecycle hooks: `preDeploy`, `deploy`, `routeTraffic`, `manageApproval`. You can specify `environment:` to define approval gates and checks. The deployment job can run on a different agent pool. Use `strategy:` with `runOnce`, `rolling`, or `canary` to control deployment strategy. The exam tests that you know how to use `environment:` with approvals and how to reference variables from the environment.

What This Looks Like on the Job

Scenario 1: CI/CD for a Microservices Application

A fintech company has 15 microservices hosted on Azure Kubernetes Service (AKS). They use Azure Pipelines to build Docker images and deploy to AKS. Each service has its own pipeline defined in YAML in the same repository (monorepo). The pipeline triggers only when files in that service's directory change using path filters: trigger: paths: include: - 'service-a/**'. The build stage compiles code, runs unit tests, builds a Docker image, and pushes it to Azure Container Registry. The deploy stage uses a Kubernetes manifest task (KubernetesManifest@1) to apply deployments to the dev namespace. For production, they use a multi-stage pipeline with manual approval gates. They also use pipeline caching for npm packages, reducing build time by 40%. Common issue: forgetting to update the path filter when adding a new service, causing no trigger. They monitor pipeline success rates with Azure DevOps Analytics.

Scenario 2: Infrastructure as Code with Terraform

A retail company uses Azure Pipelines to deploy infrastructure via Terraform. The pipeline runs on a self-hosted agent with Terraform installed. The pipeline has two stages: Plan and Apply. The Plan stage runs terraform plan and publishes the plan as an artifact. The Apply stage is manually triggered and uses the plan artifact to apply changes. They use variable groups linked to Azure Key Vault for secrets like ARM client ID and client secret. They also use environment approvals: the Apply stage targets the 'Production' environment which requires approval from the infrastructure lead. Common pitfall: the Terraform state file is stored in Azure Storage; if the storage account is deleted, the pipeline fails. They use a pre-job script to verify the storage account exists.

Scenario 3: Mobile App CI/CD

A gaming company builds a mobile app for iOS and Android using React Native. They have a single pipeline with a matrix strategy to build for both platforms in parallel. The pipeline uses Microsoft-hosted macOS and Windows agents. For iOS, they need to install certificates; they use a secure file task to download the .p12 certificate and a script to import it. They also run automated UI tests using App Center. The pipeline publishes the .ipa and .apk as artifacts. For deployment, they use App Center distribute task to push to test groups. Common issue: the macOS agent may not have the required Xcode version; they explicitly set XCODE_DEVELOPER_DIR variable. They also use pipeline caching for CocoaPods and npm to speed up builds.

How AZ-204 Actually Tests This

What AZ-204 Tests

Objective 1.3 (Integrate caching and content delivery) is the primary domain, but Azure Pipelines appears in multiple objectives. The exam expects you to:

Create and configure YAML pipelines (trigger, pool, variables, steps, stages).

Use predefined variables and custom variables.

Implement multi-stage pipelines with dependencies and conditions.

Use deployment jobs and environments with approvals.

Integrate with Azure Key Vault for secrets.

Use pipeline caching to improve build performance.

Understand agent types (Microsoft-hosted vs self-hosted).

Common Wrong Answers

1.

Choosing classic editor over YAML: The exam emphasizes YAML pipelines. Classic editor is legacy. If a question asks you to define a pipeline as code, YAML is the answer.

2.

Using `trigger: none` as default: Many candidates think a pipeline automatically runs on push. Actually, if no trigger is specified, it defaults to none (manual). You must explicitly set trigger: for CI.

3.

Assuming artifacts are automatically passed between stages: Artifacts must be explicitly published and downloaded. A common trap: a deploy stage fails because it cannot find the artifact.

4.

Forgetting that secret variables are not available in logs: The exam may present a scenario where a variable is not expanded in a script; the correct fix is to use $(var) syntax, but secrets are masked. Candidates may think they need to use environment variables.

5.

Misunderstanding `condition:` syntax: The exam tests succeeded(), failed(), always(). A common mistake is using condition: success() which is not valid; the correct function is succeeded().

Specific Numbers and Terms

Default job timeout: 60 minutes.

Maximum parallel jobs for free: 1 Microsoft-hosted.

Agent queue time limit: 30 minutes.

Retry count: Up to 3 for task failures.

Variable syntax: $(variableName) for runtime; $[variables.variableName] for compile-time.

Stages: Use stages: keyword with - stage:, - job:.

Environment: Use environment: in deployment job to enable approvals.

Predefined variable for build number: Build.BuildNumber.

Artifact staging directory: $(Build.ArtifactStagingDirectory).

Edge Cases

Path filters: trigger: paths: include: - 'src/**' — if you use exclude, it overrides include. Know that include and exclude work like a whitelist/blacklist.

Scheduled triggers: Use schedules: with cron; timezone is UTC.

Multi-repo checkout: Use resources: repositories: to trigger from another repo.

Template parameters: Use parameters: to pass values to templates.

How to Eliminate Wrong Answers

If a question mentions 'pipeline as code', eliminate options that describe classic editor.

If secrets are involved, look for answers that reference Azure Key Vault or variable groups linked to Key Vault.

If the question is about build speed, look for pipeline caching or parallel jobs.

For deployment strategies, runOnce is simplest; canary and rolling are advanced.

Always check if the trigger is properly defined; if a pipeline doesn't run on push, the trigger is missing.

Key Takeaways

Azure Pipelines YAML is the required format for AZ-204; classic editor is deprecated.

Default trigger is `trigger: none` — always set `trigger:` for CI.

Use `$(Build.ArtifactStagingDirectory)` to stage files for artifact publishing.

Artifacts must be explicitly downloaded in consuming stages.

Secret variables are masked in logs and should be fetched from Azure Key Vault.

Job timeout default is 60 minutes; override with `timeoutInMinutes`.

Use `condition: succeeded()` to run a step only if all previous steps succeeded.

Deployment jobs use `environment:` for approvals and checks.

Pipeline caching uses a key to store and restore dependencies.

Multi-stage pipelines use `stages:` with `dependsOn:` for ordering.

Easy to Mix Up

These come up on the exam all the time. Here's how to tell them apart.

Azure Pipelines (YAML)

Defined as code in YAML file

Versioned with source code

Supports multi-stage in one file

Easier to review and audit

Preferred for exam and modern DevOps

Azure Pipelines (Classic Editor)

Defined via UI with drag-and-drop

Not versioned (only in UI)

Separate build and release pipelines

Harder to automate and review

Legacy; not recommended for new projects

Watch Out for These

Mistake

Azure Pipelines only supports .NET applications.

Correct

Azure Pipelines supports any language: Node.js, Python, Java, Go, C++, etc. The agent can run any script or tool. The exam will test multi-language support.

Mistake

If you don't specify a trigger, the pipeline runs automatically on every push.

Correct

The default trigger is `trigger: none`, meaning the pipeline only runs manually. You must explicitly set `trigger:` for CI. This is a common exam trap.

Mistake

Artifacts are automatically available in all stages of a multi-stage pipeline.

Correct

Artifacts must be explicitly published in one stage and downloaded in another using `download: current` or `DownloadBuildArtifacts@0` task. They are not automatically passed.

Mistake

Secret variables can be used directly in scripts and will be visible in logs.

Correct

Secret variables are encrypted and masked in logs. They are accessed via `$(secretVar)` but the value is never displayed. You can pass them to tasks as inputs.

Mistake

Microsoft-hosted agents always have the latest tools and unlimited time.

Correct

Microsoft-hosted agents have a default timeout of 60 minutes per job and a queue time limit of 30 minutes. They come with many tools pre-installed, but you can also use custom containers.

Do You Actually Know This?

Reveal each answer, then mark whether you got it right. Score 60%+ to unlock the next chapter.

Frequently Asked Questions

How do I trigger a pipeline on a pull request?

Use the `pr:` trigger in your YAML file. For example, `pr: - main` triggers the pipeline when a PR is created or updated targeting the main branch. Note that `trigger:` is for CI (pushes) and `pr:` is for PR validation. They are independent; you can have both.

What is the difference between a variable group and a variable in YAML?

A variable group is a set of variables defined in the Azure DevOps UI that can be shared across pipelines. In YAML, you reference it with `variables: - group: myGroup`. Variables defined in YAML are scoped to the pipeline. Variable groups can be linked to Azure Key Vault for secrets. Use variable groups for secrets and common values across pipelines.

How can I run a job only if a previous stage succeeded?

Use the `condition` property on the job or stage. For example, `condition: succeeded()` runs if all previous stages/jobs succeeded. You can also use `dependsOn` to specify dependencies. The default condition is `succeeded()`.

Can I use Azure Pipelines to deploy to on-premises servers?

Yes, by using self-hosted agents installed on your on-premises machines. These agents can access internal networks. You define a pool for those agents and reference it in your pipeline with `pool: name: 'MyOnPremPool'`. The agent must have the necessary tools and network access.

How do I pass variables from one job to another?

Use the `##vso[task.setvariable]` logging command to set a variable that can be used in subsequent jobs. For example, in a script step: `echo '##vso[task.setvariable variable=myVar]value'`. Then reference it as `$(myVar)` in later jobs. Note that the variable must be marked as `isOutput=true` if you want to use it across jobs in a stage.

What is the purpose of the `pool` keyword?

The `pool` keyword specifies which agent pool to use for running the job. For Microsoft-hosted agents, you use `vmImage`. For self-hosted, use `name`. You can also specify demands (e.g., `demands: - agent.os -equals Windows_NT`). The pool determines the environment where your code builds.

How do I secure secrets in Azure Pipelines?

Store secrets in Azure Key Vault and link the vault to a variable group. In your pipeline, reference the variable group. The secrets are automatically mapped as secret variables. Never hardcode secrets in YAML. You can also use pipeline secret variables, but Key Vault is more secure and manageable.

Terms Worth Knowing

Ready to put this to the test?

You've just covered Azure DevOps Pipelines for Developers — now see how well it sticks with free AZ-204 practice questions. Full explanations included, no account needed.

Done with this chapter?