AZ-400 · Domain 3: Design and implement build and release pipelines · 54% of the exam
Task 3.3: Design and implement pipelines
GitHub Actions or Azure Pipelines, runner and agent infrastructure, GitHub repositories in Azure Pipelines, triggers, YAML, job order and parallelism, templates, variables and variable groups, and checks and approvals on environments.
Study it
GitHub Actions or Azure Pipelines, and runner and agent infrastructure
Lesson coming
YAML pipelines: triggers, stages, jobs, parallelism and templates
Lesson coming
Variables, variable groups, environments, checks and approvals
Lesson coming
Sample questions
Try each one before opening the answer. Every option is explained, with the Microsoft documentation page that proves it.
Question 1 · choose 2
A YAML pipeline deploys to a production environment. The platform team must enforce two rules that pipeline authors can't remove by editing the YAML file: only runs built from refs/heads/main may deploy, and when several runs reach the production stage at the same time, only the newest one deploys while the older ones are skipped. Which two configurations should you add? (Choose TWO.)
AA Branch control check on the environment that allows refs/heads/main
BA stage condition of eq(variables['Build.SourceBranch'], 'refs/heads/main') in the pipeline
CA Business hours check on the environment
DAn Exclusive lock check on the environment, with no lockBehavior set
Ebatch set to true in the pipeline's CI trigger
Show the answer and why
AA Branch control check on the environment that allows refs/heads/main
Correct
Branch control is a static check owned by the resource administrator; it fails the stage when a linked resource comes from a branch that isn't allowed.
BA stage condition of eq(variables['Build.SourceBranch'], 'refs/heads/main') in the pipeline
Incorrect
A condition lives in the YAML file, so any pipeline author can change or delete it; it isn't enforced by the resource owner.
CA Business hours check on the environment
Incorrect
It doesn't limit how many runs deploy or which one wins.
DAn Exclusive lock check on the environment, with no lockBehavior set
Correct
The exclusive lock lets one run use the environment at a time, and without a lockBehavior value the default runLatest lets only the latest run acquire it.
Ebatch set to true in the pipeline's CI trigger
Incorrect
It changes how CI runs start, not which existing run reaches production.
Checks are defined on the resource in the web interface, not in the YAML file, so users who edit the pipeline can't modify them. Branch control validates the branches of all linked resources against an allowed list. The exclusive lock check allows a single run to use the resource, and its default lock behavior, runLatest, lets only the latest run proceed.
Forty teams write their own YAML pipelines. Security requires that any pipeline that uses the production Azure Resource Manager service connection runs a credential scan before deploying and can't inject arbitrary script steps into the deployment. Teams must keep owning their pipeline files. What should you implement?
AAn extends template that adds the scan and validates the steps it receives, plus a Required template check on the service connection
BA shared steps template containing the scan, which every team includes in its deployment job and the security team reviews in pull requests
CA Branch control check on the service connection that allows only main
DA task group with the scan, referenced from each team's pipeline
Show the answer and why
AAn extends template that adds the scan and validates the steps it receives, plus a Required template check on the service connection
Correct
The extends template controls what a pipeline may contain, and the Required template check fails any pipeline using the connection that doesn't extend from that template.
BA shared steps template containing the scan, which every team includes in its deployment job and the security team reviews in pull requests
Incorrect
An includes template is only inserted where authors put it; a team can drop it, so nothing guarantees the scan runs.
CA Branch control check on the service connection that allows only main
Incorrect
Branch control checks which branch a run came from, not what steps the pipeline contains.
DA task group with the scan, referenced from each team's pipeline
Incorrect
Task groups belong to classic pipelines, and referencing one is still optional for the pipeline author.
An extends template defines the structure a pipeline must follow and can reject steps it doesn't allow. Adding a Required template check to the service connection makes a pipeline fail if it uses the connection without extending from the referenced template, so the rule holds even though teams edit their own YAML.
A pipeline has an optional performance test stage. The person who starts a run must choose from a fixed list of target regions or None, typing free text must be impossible, and when None is chosen the stage must not appear in the run at all rather than show as skipped. What should you use?
AA variable that is settable at queue time, tested by a runtime expression in the stage condition
BThe macro $(region) in the stage name, left empty when no test is wanted
CA variable group that holds the region, edited before each run
DA string runtime parameter with a values list, and a ${{ if }} expression around the stage
Show the answer and why
AA variable that is settable at queue time, tested by a runtime expression in the stage condition
Incorrect
A queue-time variable accepts any text, and a stage whose condition is false still appears in the run as skipped.
BThe macro $(region) in the stage name, left empty when no test is wanted
Incorrect
Macro syntax isn't expanded in keys or compile-time keywords, so it can't decide whether a stage exists.
CA variable group that holds the region, edited before each run
Incorrect
A variable group isn't a choice made when the run starts, and it offers no list of allowed values.
DA string runtime parameter with a values list, and a ${{ if }} expression around the stage
Correct
Parameters can be restricted to a set of values and are expanded during template parsing, so the if-expression removes the stage before the run starts.
Runtime parameters have data types and can be limited to a list of values, which the run dialog shows as choices. They're available only during template parsing, so a template expression such as ${{ if }} can include or leave out the stage entirely. A condition, by contrast, is evaluated at run time and leaves a skipped stage in the run.
In stage Build, job Package has a step named tagStep that computes an image tag at run time. A deployment job in stage Release, which depends on Build, must read that tag into a job variable. What should you do?
ASet the variable with isOutput=true, and in the Release job map it from stageDependencies.Build.Package.outputs['tagStep.imageTag']
BSet the variable with isOutput=true, and in the Release job map it in a variables block from dependencies.Package.outputs['tagStep.imageTag']
CSet the variable with task.setvariable without isOutput, and read $(imageTag) in the Release job
DRead ${{ variables.imageTag }} in the Release job
Show the answer and why
ASet the variable with isOutput=true, and in the Release job map it from stageDependencies.Build.Package.outputs['tagStep.imageTag']
Correct
A variable marked as output can be read by later stages through the stageDependencies context, addressed by stage, job, step and name.
BSet the variable with isOutput=true, and in the Release job map it in a variables block from dependencies.Package.outputs['tagStep.imageTag']
Incorrect
The dependencies form addresses jobs in the same stage; a job in another stage needs stageDependencies.
CSet the variable with task.setvariable without isOutput, and read $(imageTag) in the Release job
Incorrect
Without isOutput the variable exists only for later steps of the same job.
DRead ${{ variables.imageTag }} in the Release job
Incorrect
Template expressions are processed at compile time, before the step that sets the tag has run.
To share a value set by a script with later stages, the step sets it as a multi-job output variable (isOutput=true). A job in a later stage maps it with $[ stageDependencies.<stage>.<job>.outputs['<step>.<name>'] ]. Variables set without isOutput are visible only to later steps in the same job.
Azure Pipelines builds repositories in your GitHub organization. Pull requests must show build and test results through GitHub Checks, and the builds must keep working when the engineer who set them up leaves the company. Which connection type should the pipelines use?
AAn OAuth service connection authorized by that engineer
BThe Azure Pipelines GitHub App
CA GitHub personal access token with repo and admin:repo_hook scopes
DAn Incoming WebHook service connection for the repository
Show the answer and why
AAn OAuth service connection authorized by that engineer
Incorrect
OAuth status updates are made with the engineer's personal identity, and features such as Checks aren't available with OAuth.
BThe Azure Pipelines GitHub App
Correct
The app runs builds and status updates with the Azure Pipelines identity, not a person, and works with GitHub Checks.
CA GitHub personal access token with repo and admin:repo_hook scopes
Incorrect
A PAT also acts as one person's identity, so the builds depend on that person's access.
DAn Incoming WebHook service connection for the repository
Incorrect
An incoming webhook connection lets an external system trigger a pipeline; it doesn't report results as GitHub Checks.
The Azure Pipelines GitHub App is the recommended authentication for CI pipelines on GitHub. Builds and status updates use the Azure Pipelines identity rather than a personal account, and the app works with GitHub Checks. OAuth and PAT connections act as a person, and Checks require the app.
Builds must reach package feeds and test databases that are reachable only through private endpoints in an Azure virtual network. The platform team wants agents that scale out under load and down at night, the same images as Microsoft-hosted agents, and no virtual machines or images of its own to patch. What should you use?
AManaged DevOps Pools injected into the virtual network, using Azure Pipelines images
BMicrosoft-hosted agents, with the Azure geography's IP ranges allowed on the firewall
CA Virtual Machine Scale Set agent pool built from an Azure Marketplace image
DSelf-hosted agents installed on a fixed set of VMs in the virtual network
Show the answer and why
AManaged DevOps Pools injected into the virtual network, using Azure Pipelines images
Correct
The service runs and scales the agent VMs for you, can join your virtual network, and offers the same images as Microsoft-hosted agents.
BMicrosoft-hosted agents, with the Azure geography's IP ranges allowed on the firewall
Incorrect
Microsoft-hosted agents can't join your virtual network, and allowing their wide IP ranges doesn't reach private endpoints.
CA Virtual Machine Scale Set agent pool built from an Azure Marketplace image
Incorrect
Scale set agents run in your subscription on images you maintain, which is the patching work the team wants to avoid.
DSelf-hosted agents installed on a fixed set of VMs in the virtual network
Incorrect
Fixed VMs reach the endpoints, but they don't scale with load and the team must patch them.
Managed DevOps Pools is a fully managed evolution of scale set agent pools: Microsoft runs the agent machines, the pool scales with standby agent schedules, it can run in a private network or your virtual network, and it can use Azure Pipelines images, which match the Microsoft-hosted images.
An open-source project on GitHub uses Azure Pipelines for pull request validation. Outside contributors open pull requests from forks. A maintainer must review the change before any build runs, and pipeline secrets must never reach builds of fork pull requests. What should you configure?
ABuild fork pull requests on a dedicated self-hosted pool with secrets made available
BNo secrets for fork builds, and a collaborator's comment to start each build
CTurn off pull request triggers and validate only on CI after merge
DGive fork builds the same permissions as regular builds so they can report status
Show the answer and why
ABuild fork pull requests on a dedicated self-hosted pool with secrets made available
Incorrect
Exposing secrets to fork builds is the leak the project wants to avoid, and untrusted code on a self-hosted agent can compromise it.
BNo secrets for fork builds, and a collaborator's comment to start each build
Correct
Fork builds get no secrets by default, and comment triggers let a collaborator run the pipeline after reviewing the code.
CTurn off pull request triggers and validate only on CI after merge
Incorrect
Changes would merge without any validation build, which defeats pull request validation.
DGive fork builds the same permissions as regular builds so they can report status
Incorrect
This widens what a fork build can do; status reporting doesn't need it.
By default, secrets aren't made available to pull request builds from forks. Comment triggers let repository collaborators start a pipeline from a pull request comment, which is the recommended way to review contributed code before it runs. Microsoft-hosted agents are recommended for fork builds because they're discarded after each job.
A test job must run against Node.js 20, 22 and 24 and on Linux and Windows, six combinations in all, from one job definition. The organization has few parallel jobs, so no more than two combinations may run at once. What should you configure on the job?
Astrategy with parallel set to 6
BSix jobs with dependsOn chaining each one to the previous job
Cstrategy with a six-entry matrix and maxParallel set to 2
DSix stages, each with dependsOn set to an empty list
Show the answer and why
Astrategy with parallel set to 6
Incorrect
The parallel strategy slices one job into identical copies; it doesn't give each copy its own configuration.
BSix jobs with dependsOn chaining each one to the previous job
Incorrect
Chaining runs one job at a time, slower than needed, and duplicates the job definition six times.
Cstrategy with a six-entry matrix and maxParallel set to 2
Correct
A matrix generates one copy of the job per entry, and maxParallel caps how many copies run at the same time.
DSix stages, each with dependsOn set to an empty list
Incorrect
Stages with no dependencies run in parallel with no cap, and the job is still copied six times.
A matrix strategy generates copies of a job, each with different variable values. The optional maxParallel keyword limits how many matrix legs run at once; when it's unset or 0 there's no limit. The parallel strategy is mutually exclusive with matrix and is meant for slicing work such as tests across identical agents.
A private project on the free Microsoft-hosted tier has a build job that now takes 75 minutes, and it's canceled every time. Concurrency is fine with one job, and the team wants to keep Microsoft-hosted agents. What should you do?
APurchase one Microsoft-hosted parallel job
BSet timeoutInMinutes to 120 on the Microsoft-hosted job
CPurchase one self-hosted parallel job
DEnable batching on the CI trigger so that fewer runs are queued
Show the answer and why
APurchase one Microsoft-hosted parallel job
Correct
The first purchased hosted job removes the free tier's time limits and allows jobs of up to 360 minutes.
BSet timeoutInMinutes to 120 on the Microsoft-hosted job
Incorrect
A job timeout can't exceed the tier's limit; free-tier jobs stop at 60 minutes.
CPurchase one self-hosted parallel job
Incorrect
Self-hosted parallel jobs apply to your own agents, not to Microsoft-hosted ones.
DEnable batching on the CI trigger so that fewer runs are queued
Incorrect
Batching reduces the number of runs; each run still stops at 60 minutes.
The Microsoft-hosted free tier for private projects gives one job that can run up to 60 minutes each time, up to 1,800 minutes a month. Paid hosted parallel jobs allow up to 360 minutes per job; the first purchase removes the time limits on the first job.
A pipeline defines the variable logLevel as info at the root, warn in stage Test, and debug in job Integration inside stage Test. Which value do the steps of job Integration see?
Ainfo, because the root value applies to the whole pipeline
Bdebug, because the job value is the most local
Cwarn, because the stage value is read when the stage starts
DA pipeline error, because the name is defined three times
Show the answer and why
Ainfo, because the root value applies to the whole pipeline
Incorrect
The root value is overridden by values defined at narrower scopes.
Bdebug, because the job value is the most local
Correct
When a name is defined in several places, the most locally scoped definition takes precedence.
Cwarn, because the stage value is read when the stage starts
Incorrect
The stage value applies to jobs in the stage that don't set their own.
DA pipeline error, because the name is defined three times
Incorrect
Defining the same name at several scopes is allowed.
Variables can be set at the root, stage and job levels. When the same name is defined in several places, the most locally scoped variable takes precedence: a job variable overrides a stage variable, which overrides a root variable.
A YAML pipeline in Azure DevOps Services has no pool section at all. Which agent image do its jobs run on?
Awindows-latest, which is Windows Server 2025
Bubuntu-22.04
CThe Default self-hosted pool
Dubuntu-latest, which is Ubuntu 24.04
Show the answer and why
Awindows-latest, which is Windows Server 2025
Incorrect
Windows images are used only when a pipeline names one.
Bubuntu-22.04
Incorrect
Ubuntu 22.04 is deprecated and is used only when named.
CThe Default self-hosted pool
Incorrect
Without a pool section, a YAML pipeline uses the Microsoft-hosted default image, not a self-hosted pool.
Dubuntu-latest, which is Ubuntu 24.04
Correct
ubuntu-latest is the default image for YAML pipelines, and the label points to Ubuntu 24.04.
The ubuntu-latest image is the default image for YAML pipelines if no image is specified, and today it maps to Ubuntu 24.04. The Ubuntu 22.04 image is deprecated and scheduled for removal.
A deployment job runs a migration script that is stored in the repository, but the step fails because the script file doesn't exist on the agent. The build artifact is downloaded correctly. What should you add to the deployment job?
AA download step for the current pipeline's artifact
BA demand for an agent that has the script installed
CA pipeline variable pointing to the script's path
DA checkout self step
Show the answer and why
AA download step for the current pipeline's artifact
Incorrect
The artifact already downloads in the deploy hook; the missing file is in the repository, not the artifact.
BA demand for an agent that has the script installed
Incorrect
The script belongs to the repository; matching an agent doesn't fetch it.
CA pipeline variable pointing to the script's path
Incorrect
A path variable doesn't put the file on the agent.
DA checkout self step
Correct
A deployment job doesn't automatically clone the source repository; checkout self fetches it.
Deployment jobs don't clone the source repository automatically, while the Download artifact task is injected in the deploy hook. To use files from the repository, add a checkout: self step.