Microsoft AZ-400: CI/CD Pipelines with Azure Pipelines — Study Guide
Part of the Microsoft DevOps Engineer Expert AZ-400 — Study Guide. Practice with verified answers in the Microsoft exam hub, or take timed practice tests on ExamRoll.io.
Overview
Azure Pipelines delivers end-to-end CI/CD as code, with multi-stage YAML pipelines that unify build, test, and release while preserving enterprise controls. Mastery of YAML authoring, triggers, agents, variables, templates, deployment jobs, artifacts, caching, and service connections is essential to build scalable, secure, and repeatable delivery systems.
Authoring with YAML and Templates
A YAML pipeline is composed of stages, jobs, and steps. Stages model lifecycle boundaries such as Build, Test, Release; jobs execute on agents and can run in parallel; steps are tasks or scripts executed within a job. Dependencies are explicit via dependsOn, allowing fine-grained orchestration and conditional execution. Multi-stage YAML consolidates CI and CD, supports fan-in/fan-out patterns, and ties approvals to environments rather than a standalone release construct.
Templates enable composition and reuse at different granularities:
- Step templates: encapsulate a sequence of tasks (e.g., tool setup, restore, build, test) for reuse across repositories.
- Job templates: bundle steps with a specific agent specification and strategy (e.g., a test matrix job).
- Stage templates: package entire stages, including approvals, conditions, and environment targeting, for consistent promotion flows.
- Extends templates: enforce pipeline inheritance. A top-level extends references a central template that prescribes required stages/jobs/steps and governance. This is powerful for organization-wide policies, ensuring every team inherits security scans, compliance checks, and naming conventions.
Template evaluation occurs at compile-time prior to runtime execution. Use ${{ }} for template expressions to branch the pipeline structure at compile time (for example, include certain jobs only for main). Macro syntax $(var) and runtime expressions $[ ] resolve at runtime, which affects when secrets and variable groups are available. Store shared templates in a central repo and import via resources repositories; pin to a branch or tag for deterministic builds.
Triggers, Agents, Variables, and Expressions
Triggers govern automation entry points:
- CI triggers start pipeline runs when code is pushed to tracked branches. Include and exclude path filters reduce churn. Batch allows coalescing multiple pushes.
- PR triggers validate pull requests. Configure target branches and path filters, and enable auto-cancel of superseded runs.
- Scheduled triggers run on cron expressions to support nightly builds or periodic validations with time zone control.
- Pipeline triggers fire when an upstream pipeline publishes a new run or artifact. Declare pipeline resources and attach trigger: true with branch filters to chain pipelines across repositories or projects.
Agents and agent pools determine where jobs run:
- Microsoft-hosted agents provision ephemeral VMs on ubuntu-latest, windows-latest, or macOS images with preinstalled toolsets. They are ideal for elasticity and minimal maintenance. Plan for concurrency by purchasing parallel jobs and consider cache warm-up limits.
- Self-hosted agents run on your infrastructure for custom toolchains, private network access, and predictable performance. Harden the host, restrict egress as needed, and rotate the agent PAT used to register the agent. Use scale sets or containerized agents for elasticity.
- Agent pools logically group agents and are used to delegate permissions. Grant project-level “Use” rights to pools, and isolate sensitive workloads by dedicated pools. Jobs specify pool and optionally demands to select agents with required capabilities.
Variables and parameters drive configurability:
- Pipeline variables are key/value pairs available to tasks as environment variables and through $(name) macro. Secret variables are masked in logs and never exposed in compile-time template expressions. Mark them as secret in the Library or pipeline.
- Variable groups centralize shared values and secrets in the Library. Link to Azure Key Vault to source secrets at runtime, ensuring values are not stored in the pipeline. Control pipeline permissions to restrict which pipelines can consume a group.
- Runtime parameters define strong-typed input at queue time (string, number, boolean, object) and are evaluated at compile time via ${{ parameters.* }} to shape the pipeline (e.g., enable/disable stages). Prefer parameters when you need to alter pipeline structure; prefer variables when you need runtime values within steps.
- Expressions: use ${{ }} for compile-time template logic, $(var) for macro substitution, and $[condition()] for runtime conditionals in properties. Set variables from tasks via logging commands, and propagate outputs across jobs using isOutput variables.
Deployments, Environments, Strategies, and Gates
Deployment jobs provide first-class CD semantics. A deployment job targets an environment and runs under a strategy that controls rollouts and lifecycle hooks:
- Environments represent deployment targets (e.g., dev, test, prod) and can contain resources like Kubernetes clusters, virtual machines, or generic “none” resources for platform-agnostic deployments. Environments unify telemetry, approvals, and checks.
- Approvals and checks are attached to environments and service connections. Approvals require designated approvers before deployment proceeds. Checks act as gates that evaluate conditions such as business hours, required work items, Azure Monitor signals, invoking REST APIs or Azure Functions, and branch protection. These prevent promotion if performance baselines or compliance conditions are not satisfied.
- Strategies shape how updates are rolled out:
- runOnce applies changes in a single wave, with preDeploy and postDeploy hooks.
- rolling deploys in batches across instances, with maxParallel and failure thresholds for safe progression.
- canary shifts traffic gradually through increments, with routeTraffic and postRouteTraffic phases to validate before full rollout.
- blue-green (also called red/black) is implemented by deploying to a parallel environment or slot and switching traffic at the load balancer or App Service slot swap. Although blue-green is not a named YAML strategy, it is realized via environments, routing, and swap tasks, and provides fast rollback by reverting traffic.
Encode deployment logic as a deployment job per environment stage. Leverage environment checks for robust gates, not ad-hoc script polling. When secrets are needed, retrieve them from Azure Key Vault via a service connection rather than embedding them in variables.
Artifacts, Caching, and Service Connections
Artifacts and caching improve reuse and performance:
- Pipeline artifacts are the native way to publish and consume build outputs. Use PublishPipelineArtifact to publish named artifacts and DownloadPipelineArtifact to fetch from the current or a specific run. They are optimized for reliability and cross-stage sharing in YAML. When consuming from another pipeline, declare a pipeline resource and use its artifacts resource name for precise retrieval.
- Universal packages provide versioned, immutable binary distribution via Azure Artifacts for non-language-specific assets (e.g., CLI tools, data files). Publish and download with the Universal Packages tasks, organize via feed views (e.g., prerelease vs release), and manage retention in feeds.
- Pipeline caching accelerates dependency restores. The Cache task uses a key and path. Keys should hash lockfiles (package-lock.json, Pipfile.lock, packages.lock.json, go.sum) plus OS and tool versions for precise invalidation. Restore keys provide fallback matches for partial cache hits. Avoid embedding secrets in cache paths, respect cache size limits, and disable caching for ephemeral tools when lockfiles are unstable. Observe cacheHitVar to branch task behavior.
Service connections define the identity Azure Pipelines uses to reach external systems:
- Types include Azure Resource Manager (for Azure subscriptions and resource groups), GitHub (repository read/write, status reporting), and Docker/Container Registry (Docker Hub, ACR). Others exist for AWS, GCP, generic service endpoints, and package registries.
- OIDC federation (workload identity federation) removes long-lived secrets by establishing a trust between Azure DevOps and cloud identity providers. For ARM, configure an Entra ID application with a federated credential bound to the Azure DevOps issuer and repository/pipeline claims. At runtime, Azure DevOps exchanges a short-lived token for a cloud access token, eliminating service principal secrets and reducing credential leakage risk.
- Scoping and governance are critical. Scope ARM connections to the least privilege (ideally resource group level with custom RBAC). Disable “Grant access permission to all pipelines” and instead explicitly authorize pipelines. Attach approvals and checks to service connections to require human review or policy validation before use.
Classic vs YAML and Migration
Classic pipelines use the visual designer with separate Build and Release concepts. They offer task-based authoring, variable management, release environments, and gates. YAML pipelines provide pipeline-as-code, multi-stage unification, templates, and robust versioning with the repository. Feature parity is largely achieved: environment approvals and checks replace release gates; deployment jobs model environments; pipeline artifacts supersede build artifacts; and templates and extends implement central governance at scale. Remaining differences are typically around UI-based manual interventions and some niche release designer features, which are covered in YAML via Manual Validation tasks and environment checks.
A pragmatic migration path is:
- Inventory classic build and release definitions, tasks, variables, environments, approvals, and gates.
- Convert build to YAML using the assistant or export to YAML, then refactor into templates for reuse and maintainability.
- Model each release environment as a YAML stage with a deployment job targeting an environment. Translate release gates to environment approvals and checks (e.g., Azure Monitor query checks, work item query checks).
- Externalize shared variables into variable groups and link Key Vault for secrets. Replace service principal secrets with OIDC-backed service connections.
- Replace release artifact triggers with pipeline resource triggers. Publish pipeline artifacts in CI and consume them in CD stages.
- Validate parity by running both pipelines temporarily, then cut over and retire classic definitions with appropriate rollback plans.
Practical Problem Scenario
Starbucks is standardizing delivery for a microservices platform and must migrate from classic releases to YAML while enforcing performance gates, reducing credential risk, and speeding builds.
- Author multi-stage YAML with extends templates
- Approach: Create a central organization-level extends template that injects common stages for static analysis, SCA, and security checks, plus standard notifications. Each service pipeline extends this template and defines service-specific build and deploy stages.
- Rationale: Extends enforces governance uniformly and keeps service pipelines lean while guaranteeing required compliance steps.
- Implement CI, PR, schedule, and pipeline triggers
- Approach: Configure CI and PR triggers with path filters for each service; add a nightly schedule for long-running integration tests; chain a packaging pipeline to trigger a deployment pipeline via pipeline resources.
- Rationale: Ensures rapid feedback on code changes, periodic health checks, and deterministic promotion of known artifacts.
- Use mixed agent strategy with agent pools
- Approach: Build jobs on Microsoft-hosted ubuntu-latest for elasticity; deploy jobs on self-hosted agents inside the Starbucks VNet with access to internal clusters. Isolate agents by pools per environment and restrict pool usage.
- Rationale: Hosted agents minimize maintenance for CI; self-hosted agents provide secure network reach for CD. Pool scoping enforces least privilege.
- Manage variables with variable groups and runtime parameters
- Approach: Place shared non-secret values in variable groups, retrieve secrets from Azure Key Vault via linked variable groups, and expose a boolean parameter enablePerfGate to toggle performance gates in non-prod branches.
- Rationale: Centralized configuration avoids duplication; Key Vault protects secrets; parameters drive compile-time structure choices.
- Define deployment jobs with environments, approvals, and checks
- Approach: Model dev, staging, and prod as environments. Add approvals for staging and prod. Add checks: business hours for prod, and an Azure Monitor query check that blocks promotion if staging latency exceeds baseline.
- Rationale: Environment-level approvals and checks implement controlled promotion and enforce SLOs before production deployment.
- Apply canary then blue-green strategies
- Approach: Use a canary strategy in staging to validate increments. In production, deploy to a parallel slot/environment and swap traffic (blue-green/red-black) with instant rollback capability.
- Rationale: Canary reduces risk during validation; blue-green minimizes deployment time and provides fastest rollback.
- Optimize with pipeline artifacts and caching
- Approach: Publish build outputs as pipeline artifacts; consume them in deployment stages. Cache dependency restores using lockfile-hashed keys with restoreKeys for fallback.
- Rationale: Artifacts ensure immutable, traceable promotion; caching cuts build times significantly without sacrificing correctness.
- Secure service connections with OIDC and scoped permissions
- Approach: Create ARM service connections using workload identity federation scoped to resource groups. Require service connection approvals and checks, and disable “Grant access to all pipelines”.
- Rationale: Removes long-lived secrets and enforces least privilege with auditable approvals.
This end-to-end design aligns YAML-as-code governance with enterprise-grade approvals and checks, accelerates delivery through caching and artifacts, and strengthens security via OIDC and scoped service connections.
← Source Control and Repository Management · All domains · Infrastructure as Code and Configuration Management →
Practice these questions → · Timed practice on ExamRoll.io →
Pass the whole exam — not just this question
You found this answer. Get every verified question and explanation in one place, and save hours of prep. Free to start.
Pass your exam →