A build pipeline is an automated sequence of steps that takes your source code and turns it into a deployable software package. Without a pipeline, developers would have to manually compile code, run tests, and package files every time they make a change—which is slow, error-prone, and impossible to scale across a team. For the AZ-400 exam, you must understand how to design these pipelines so they are reliable, fast, and secure.
Jump to a section
A simple way to picture Designing a Build Pipeline
A recipe book is a collection of instructions for turning raw ingredients into a finished dish, but it does nothing on its own until a cook follows it.
Imagine you want to bake a three-tier chocolate cake for a friend's birthday. If you just hand them a recipe book—even one with the perfect chocolate cake recipe—they still need to go step by step: preheat the oven, measure the flour, cream the butter, melt the chocolate, mix the batter, pour it into tins, bake each layer, let them cool, make the frosting, assemble the tiers, and then decorate. Each step has to happen in exactly the right order. If you try to put the frosting on before the cake cools, the frosting melts and slides off. If you skip measuring the baking powder, the cake doesn't rise.
Now map that to a build pipeline. The recipe book is your build pipeline configuration in Azure DevOps. The raw ingredients are your source code files, libraries, and dependencies. The cook is the automated build agent (a virtual machine or container) that executes each instruction. The oven is the build environment, the cake is your built application (a compiled executable or package), and the finished cake with frosting and decorations is a deployable artifact ready to ship. Just as a recipe ensures a consistent cake every time, a build pipeline ensures your code compiles, passes tests, and packages reliably, even when a different 'cook' (different build agent) executes it on a different day.
A build pipeline, often called a Continuous Integration (CI) pipeline, is the automated process that transforms source code into a build artifact—a file or set of files ready to be deployed to a server, a cloud service, or a test environment. Before CI became standard, developers would write code for weeks or months, then attempt to 'integrate' all their changes into one final build. That integration phase was famously painful: conflicting changes, missing dependencies, and broken features. CI pipelines solve that by building and testing every single change automatically, often multiple times a day.
Here is how a build pipeline works in Azure DevOps. You start with a source control repository—a centralised place where your team stores code, typically using Git. Whenever a developer pushes new code to a branch (like 'main' or 'feature/login'), Azure Pipelines detects that event and triggers a build pipeline automatically. The pipeline runs on a build agent, which is a machine (Windows, Linux, or macOS) that executes the steps you define. Those steps live inside a YAML file (a human-readable configuration file) or in a visual designer.
The pipeline consists of stages, jobs, and steps. A stage is a major phase like 'Build', 'Test', and 'Deploy'. Each stage contains one or more jobs, which are units of work that run on a specific agent. Each job contains steps, which are individual commands or tasks like 'restore NuGet packages', 'compile the solution', 'run unit tests', 'publish build artifacts', or 'run a security scan'.
Why does this matter for the AZ-400 exam? The exam tests your ability to design a pipeline that is efficient, secure, and compliant with your team's workflows. You need to decide things like: what triggers the pipeline (continuous integration, pull request validation, scheduled builds); which agent pool to use (Microsoft-hosted vs self-hosted); how to handle variables and secrets (like API keys); how to run multiple jobs in parallel to speed up the build; and how to publish artifacts so downstream release pipelines can consume them.
Key concepts you must understand:
Triggers: These define what starts a pipeline. A CI trigger starts the pipeline when code is pushed to a branch. A PR trigger starts it when a pull request is created or updated. A scheduled trigger runs it at a specific time (e.g., nightly).
Variables: These are key-value pairs that configure your pipeline without hardcoding values. You can store things like the build configuration (Debug or Release), version numbers, or connection strings. Azure DevOps allows you to set variables in the YAML file, in the pipeline UI, or in variable groups linked to Azure Key Vault for secrets.
Artifacts: These are the output files of a build, such as compiled binaries, Docker images, or deployment packages. You publish artifacts so that release pipelines can download them later.
Dependencies: You can define that one job or stage must finish before another starts. For example, you might run all unit tests first, then only if those pass, run integration tests.
Conditions: These let you run steps conditionally. For example, only deploy to a test environment if the build came from the 'main' branch, or only run a security scan if the build is a release.
Agent pools: A collection of build agents. Microsoft-hosted agents come pre-configured with common tools (like .NET SDK, Node.js, Python). Self-hosted agents are machines you manage, giving you full control over the environment.
The exam expects you to know how to design pipelines using YAML syntax. The YAML file is called azure-pipelines.yml and sits at the root of your repository. It defines the pipeline as code, meaning the pipeline is versioned alongside your source code, so you can review changes in pull requests, roll back to old versions, and see exactly how a pipeline was configured when a specific build ran.
A simple pipeline might look like this in concept:
Trigger on any push to 'main' branch.
Use a Windows agent from the 'windows-latest' pool.
Check out the code from the repository.
Restore dependencies (like NuGet packages for a .NET app).
Compile the code with the 'Release' configuration.
Run unit tests.
Publish the compiled binary as a build artifact.
That is the bare minimum. In the real world, you add more steps: static code analysis, code coverage thresholds, integration tests, and publishing to a package feed like Azure Artifacts.
What does a build pipeline replace? It replaces manual build processes. In the old days, a developer would compile the project on their local machine, zip up the output, email it to someone or manually upload it to a server, then cross their fingers. That approach was fragile: if the dev's machine had a special library installed that the server didn't, the build would fail. With a pipeline, every build runs in a clean, consistent environment, so you catch those 'works on my machine' problems early.
To design a build pipeline, you also need to think about security. Secrets like database passwords should never be hardcoded in the YAML file. Instead, you store them in Azure Key Vault and link them to your pipeline using variable groups. The pipeline can then access those secrets at runtime without exposing them in logs or to developers who should not see them.
The exam also tests your knowledge of build retention policies. By default, Azure DevOps keeps build results for a set number of days (e.g., 30). You can configure retention to delete old builds automatically, saving storage space and ensuring compliance.
Finally, you need to understand how to handle multiple configurations. For example, you might want to build both Debug (with extra debugging info) and Release (optimised for performance) versions of your app. You can use a matrix strategy in YAML to run builds for multiple configurations in parallel.
In summary, designing a build pipeline is about automating the handoff from 'code written by a developer' to 'tested, packaged software ready to deploy'. The AZ-400 focuses on your ability to configure that automation using Azure Pipelines, balancing speed, reliability, security, and scalability.
Define the Trigger
Decide what event starts the pipeline. Common choices: CI trigger (push to a branch), PR trigger (pull request created), or a scheduled trigger. For example, a CI trigger on 'main' ensures every merge triggers a build.
Select the Agent Pool
Choose between Microsoft-hosted agents (e.g., ubuntu-latest) or self-hosted agents. Microsoft-hosted agents are convenient for standard toolchains; self-hosted agents are necessary for custom environments or private networks.
Check Out the Repository
Add a step to fetch the source code from the Git repository. This is usually the first step and is done automatically when you use the 'checkout: self' command in YAML.
Restore Dependencies
Install external libraries and packages the project needs, such as NuGet packages for .NET or npm packages for Node.js. This step ensures the build environment has everything required to compile.
Compile the Code
Run the build command (e.g., 'dotnet build', 'npm run build', 'mvn compile') that turns source code into executable binaries. This step uses the 'Release' configuration unless overridden by a variable.
Run Tests
Execute unit tests and optionally integration tests. This step validates that the code behaves correctly. The pipeline can publish test results and code coverage reports for visibility.
Publish Build Artifacts
Copy the final build output (e.g., DLL files, Docker images, or deployment packages) to a staging directory, then use the 'PublishBuildArtifacts' task to make them available to release pipelines or for manual download.
Imagine you work as a DevOps engineer for a mid-sized e-commerce company called 'ShopWave'. Your team of eight developers builds a web application that runs on Azure App Service. The application is written in C# using ASP.NET Core, with a React front end. The team uses Git hosted in Azure Repos.
Your first task is to design a build pipeline that runs every time a developer pushes code to any feature branch, and also runs whenever a pull request is created against the 'main' branch. You need to ensure the build compiles the code, runs unit tests, and publishes a deployable package. You also want to run a security scan using a tool like Microsoft Defender for DevOps.
Step by step, here is what you do:
You create an azure-pipelines.yml file at the root of the repository.
You define a CI trigger for 'main' and a PR trigger for pull requests targeting 'main'.
You set the agent pool to 'ubuntu-latest' because the app is Linux-compatible, which is cheaper than Windows agents.
You define a variable for the build configuration ('Release') and a variable for the version number that auto-increments using the build ID.
In the pipeline, you start with a 'dotnet restore' step to restore NuGet dependencies.
Then you run 'dotnet build' with the Release configuration.
After that, you run unit tests using 'dotnet test' with a flag that generates a code coverage report.
If all tests pass, you run 'dotnet publish' to create a self-contained deployment package.
Then you publish the output folder as a build artifact named 'drop'.
Finally, you add a security scan step that runs a static analysis tool on the source code. You store the API key for that tool in Azure Key Vault and link it to the pipeline using a variable group.
Now, a developer named Priya creates a new branch called 'feature/checkout-update' and pushes code. Instantly, Azure Pipelines picks up the change and runs the pipeline. The build compiles, the tests pass, and the security scan finds no critical vulnerabilities. She feels confident opening a pull request.
Later, another developer named Marcus pushes to his branch but accidentally introduces a syntax error. The pipeline fails at the build step. Azure DevOps sends an email to Marcus notifying him of the failure. He fixes the error, pushes again, and the pipeline succeeds. The team never sees a broken 'main' branch because the PR validation pipeline also catches issues before merge.
As the company grows, you need to optimise. You notice the unit tests take 12 minutes. You split them into two parallel jobs: one runs front-end tests using Jest, the other runs back-end tests using xUnit. You configure the pipeline to run both jobs simultaneously, cutting the total pipeline time to 8 minutes.
You also set up a retention policy: keep the last 10 successful builds for 'main' and only the last 2 builds for feature branches. This saves storage costs.
In a more complex scenario, you might set up a multi-stage pipeline where the build stage produces artifacts, and the next stage (release) deploys to a test environment. For AZ-400, the focus for this chapter is on the build stage itself, but you need to understand how it connects to release pipelines via artifacts.
The AZ-400 exam (exam code AZ-400) includes 'Design a build pipeline' as part of objective 3.1. This objective accounts for roughly 10-15% of the exam weight. The questions are scenario-based: you are given a description of a team's development process, their constraints (e.g., security policies, team size, tooling preferences), and you must select the best design for their build pipeline.
Here are the specific concepts the exam tests repeatedly:
Trigger types: You must know when to use CI triggers, PR triggers, scheduled triggers, and path filters. A common trap: they give a scenario where a team wants to run the pipeline only when code in the 'src/app' folder changes. The correct answer uses paths in the trigger section (e.g., paths: include: ['src/app/*']). Many candidates forget path filters and choose a generic branch trigger.
Agent selection: Microsoft-hosted vs self-hosted agents. The exam expects you to choose self-hosted when you need specific software installed that the standard agents do not have, or when you need to run builds in a private network without outbound internet access. Microsoft-hosted agents are the default for most scenarios because they are maintained by Microsoft and include common tools.
Variables and secret management: You must know how to store secrets using Azure Key Vault and link them via variable groups. The trap here: candidates mistakenly store secrets directly in the YAML file or in pipeline variables as plain text. The correct pattern is to reference a variable group connected to Key Vault, and then use that variable in the pipeline (e.g., $(mySecret)).
Artifact publishing: The exam tests that you must publish build artifacts using the 'PublishBuildArtifacts' task. A common distractor is 'CopyFiles' (which copies files to a staging directory but does not publish them as an artifact). You need both: copy to staging, then publish.
Parallelism and matrix strategies: You should know how to use a matrix strategy to build multiple configurations (e.g., x86 and x64) in parallel. The exam might show a scenario where a team needs to build for Windows, Linux, and macOS simultaneously. The correct answer uses a 'strategy' section with 'matrix'.
Conditions: The exam tests conditions like 'only run if the branch is main' using 'condition: eq(variables['Build.SourceBranch'], 'refs/heads/main')'. Traps involve using 'and' or 'or' incorrectly, or forgetting the full ref path.
Dependencies: You must understand how to order jobs and stages. The default is that jobs in a stage run sequentially. If you want them to run in parallel, you must explicitly set 'dependsOn: []' or 'dependsOn: none'. A common trap: assuming all jobs run in parallel by default.
Build retention: The exam expects you to know how to set retention policies at the pipeline level or for specific runs. The default retention period is 30 days for runs, but you can set it to something like 'keep the last 5 runs for 365 days'.
Security scanning: You may be asked to integrate a security scan tool (like WhiteSource Bolt, SonarQube, or Microsoft Defender for Cloud) into the pipeline. The key is that the scan runs as part of the build, and the results are published as part of the pipeline report.
YAML vs Classic editor: The exam focuses on YAML-based pipelines. You are expected to read and understand YAML syntax. Classic editor (visual) is mentioned but not tested in depth.
Templates: You should know how to use YAML templates to reuse common steps across multiple pipelines. A question might ask you to share a set of steps (like 'run linting and tests') across three different project pipelines. The correct answer is to create a template file (e.g., steps-template.yml) and reference it in each pipeline using 'template:'.
Common exam question formats:
'You need to design a build pipeline that runs unit tests only when code changes in the 'src' folder. What should you configure?' Answer: Use the 'paths' trigger with an 'include' filter.
'Your build pipeline must deploy to multiple environments, but only from the main branch. What condition do you use?' Answer: A condition like 'eq(variables['Build.SourceBranch'], 'refs/heads/main')'.
'You need to securely store a database connection string for use in the build pipeline. What is the recommended approach?' Answer: Store the connection string in Azure Key Vault, create a variable group linked to Key Vault, and reference the variable in the pipeline.
'Your team uses self-hosted build agents. One of the agents runs out of disk space during builds. What should you do?' Answer: Use the 'Agent.WorkFolder' variable to point to a drive with more space, or clean the workspace using the 'clean' option (e.g., clean: true).
Trap patterns to watch for:
Overcomplicating: Some answer choices add unnecessary steps like 'deploy to production' when the question only asks about the build pipeline.
Incorrect trigger paths: Using 'refs/heads/*' when a specific branch is required, or forgetting that the path filter applies relative to the root of the repository.
Confusing 'variables' with 'parameters': Variables are computed at runtime, parameters are evaluated at template expansion time. The exam occasionally uses the wrong one in a distractor.
Mixing up 'stages', 'jobs', and 'steps': For example, a question might ask where to put a condition to run a task only on failure. The correct place is in the 'step' definition, not at the job or stage level (unless you want the entire job to be skipped).
A build pipeline is an automated CI process that compiles, tests, and packages code every time it changes, replacing manual builds.
Use CI triggers to run pipelines automatically on code pushes, and PR triggers to validate pull requests before merge.
Store secrets like API keys in Azure Key Vault, not in YAML files or pipeline variables, and reference them via variable groups.
Publish build artifacts using the PublishBuildArtifacts task so that release pipelines can consume the output.
Jobs in a stage run sequentially by default; use 'dependsOn: []' or a matrix strategy to run jobs in parallel.
Self-hosted agents give you full control over the build environment but require maintenance; Microsoft-hosted agents are simpler and pre-configured for common toolchains.
Retention policies automatically delete old build runs to save storage and maintain compliance.
YAML-based pipelines are preferred over the classic editor because they are version-controlled and easy to review in pull requests.
These come up on the exam all the time. Here's how to tell them apart.
CI Trigger
Triggers on any push to a specified branch (e.g., main).
Used for continuous integration of code changes.
Runs on the latest commit after push.
PR Trigger
Triggers when a pull request is created or updated.
Used to validate code before merging into the target branch.
Runs on the merge commit of the PR (combined with target branch).
Microsoft-hosted Agent
Managed by Microsoft; no maintenance required.
Comes with common tools pre-installed (e.g., .NET, Node, Python).
Limited to 30 minutes per job (free tier) and 6 hours per job (paid).
Self-hosted Agent
Managed by your team; you install and update software.
Allows custom software and network configurations.
No time limit per job; suitable for long builds.
YAML Pipeline
Pipeline configuration stored as code in the repository.
Version-controlled; changes go through pull requests.
Preferred for modern DevOps as it is auditable and reusable.
Classic Editor Pipeline
Pipeline configuration stored in Azure DevOps UI database.
Not version-controlled; changes are made via web interface.
Legacy approach; still supported but not recommended for new projects.
Build Pipeline
Focused on CI: compile, test, and produce artifacts.
Typically does not deploy to environments.
Artifacts are published and stored in Azure DevOps.
Release Pipeline
Focused on CD: deploy artifacts to environments.
Includes approvals, gates, and manual intervention steps.
Consumes artifacts from the build pipeline.
Mistake
A build pipeline can only be triggered manually by a developer clicking the 'Run' button.
Correct
Build pipelines are typically triggered automatically when code is pushed to a branch (CI trigger) or when a pull request is created (PR trigger). Manual triggers are the exception, not the rule.
Many beginners are accustomed to a manual compilation step (like pressing 'Build' in Visual Studio) and assume automation works the same way.
Mistake
The build pipeline and the release pipeline are the same thing.
Correct
A build pipeline produces an artifact (like a compiled binary). A release pipeline takes that artifact and deploys it to environments like testing, staging, and production. They are separate concepts often hosted in separate pipelines in Azure DevOps.
The terms 'build' and 'release' are sometimes used interchangeably in casual conversation, but Azure DevOps treats them as distinct stages of the DevOps lifecycle.
Mistake
If the build pipeline passes on my machine, it will always pass in Azure DevOps.
Correct
Build pipelines run in a clean environment that may have different versions of SDKs, operating systems, or tools. 'Works on my machine' is famously unreliable. Pipelines catch those discrepancies by using a consistent, isolated build agent.
Beginners underestimate differences between environments. They assume a local build is a perfect representation of the production pipeline.
Mistake
You can store passwords and API keys directly in the YAML file as long as you mark them as 'secret' variables.
Correct
Even secret variables in YAML can be exposed if the YAML file is stored in a repository accessible to unauthorised users. The industry best practice is to store secrets in Azure Key Vault and reference them via variable groups that are linked to the vault.
Azure DevOps allows you to mark variables as 'secret' in the UI, but that still stores them in the pipeline's metadata. Key Vault provides an extra layer of security with access policies and auditing.
Mistake
All jobs in a stage run in parallel by default, which is always faster.
Correct
By default, jobs in a stage run sequentially (one after the other). To run them in parallel, you must explicitly set 'dependsOn: []' or 'dependsOn: none'. Parallelism speeds up the build but costs more in concurrent agent usage.
The word 'parallel' sounds like the default in a modern CI system, but Azure DevOps prioritises simplicity and avoids resource contention by default.
Mistake
Once a build pipeline is set up, you never need to modify it.
Correct
Build pipelines need ongoing maintenance: updating dependencies, rotating secrets, changing agent pools, adjusting retention policies, and optimising steps as the codebase evolves. It is a living configuration.
Newcomers treat infrastructure like a one-time installation. In reality, DevOps is a continuous practice of incremental improvement.
Reveal each answer, then mark whether you got it right. Score 60%+ to unlock the next chapter.
A build pipeline (CI) compiles, tests, and packages your code into an artifact. A release pipeline (CD) takes that artifact and deploys it to environments like development, staging, and production. They are separate pipelines that work together.
Store passwords and other secrets in Azure Key Vault, then link the vault to Azure Pipelines using a variable group. Reference the secret as a pipeline variable (e.g., $(myPassword)) without hardcoding it in the YAML file.
A YAML pipeline is a configuration file (azure-pipelines.yml) stored in your repository that defines the build steps as code. It is preferred because it is version-controlled, reviewable in pull requests, and easy to replicate across projects.
Yes. Self-hosted agents are machines you manage, giving you full control over the operating system, installed software, and network access. Register them with Azure DevOps and they appear in your agent pool selection.
Azure DevOps sends an email notification to the person who triggered the build, showing the failure and logs. The team can investigate the logs, fix the issue, and retry the build. Failed builds do not block other work unless you configure it.
You can speed up builds by running jobs in parallel, using a matrix strategy for multiple configurations, caching dependencies (like NuGet packages), and only running steps that are necessary (e.g., skip tests if only documentation changed).
An artifact is the output of a build pipeline—a compiled binary, a Docker image, a deployment package, or any set of files that can be consumed by a release pipeline. Artifacts are published using the PublishBuildArtifacts task.
You've finished Designing a Build Pipeline. Continue through the AZ-400 study guide to build a complete picture of the exam.
Done with this chapter?