Working rules for Azure DevOps that survive the second project and the tenth developer β YAML discipline, environment gates, and the setup failures every new org hits.
3 chapters Β· 8 rules
4 reusable commands β fill the placeholders, copy, done. Values you fill are never stored.
Kick a pipeline without leaving the terminal β branch pinned, no UI clicking.
az pipelines run --name {{pipeline_name}} --branch {{branch}} --org {{org_url}} --project {{project}}
The "is it just me or is CI broken" check.
az pipelines runs list --org {{org_url}} --project {{project}} --top 5 --query "[].{id:id, pipeline:definition.name, result:result, branch:sourceBranch}" -o table
The only force-push that belongs in muscle memory: it refuses to overwrite work you have not seen.
git push --force-with-lease origin {{branch}}
Careful: Never force-push a shared branch (main/develop) β this card is for your own feature branches after a rebase.
Follows Rule 7
One command instead of eleven portal clicks β per environment.
az pipelines variable-group create --name {{group_name}} --org {{org_url}} --project {{project}} --authorize false --variables placeholder=replace-via-keyvault-link
Careful: Leave --authorize false: groups authorized for every pipeline defeat the access model.
Follows Rule 3
1 repeatable process β read straight through, or run step by step with a private record of what you did.
From empty Azure DevOps org to a pipeline that builds an image, pushes to ACR, and deploys to a gated prod β including the two setup failures every new org hits.
New orgs have zero free hosted parallelism and the grant form (aka.ms/azpipelines-parallelism-request) takes days to process. File it before writing any YAML, or your first run will queue forever.
Runs stuck on "waiting for an agent" with no error = no parallelism. See the attached failure note.
β First pipeline run never starts: no hosted parallelism
##[error]No hosted parallelism has been purchased or granted. To request a free parallelism grant, please fill out the following form...
Likely cause: Free-tier hosted parallelism is grant-only for new orgs (an anti-abuse measure) and nobody requests it in advance
Fix: Submit the grant form (aka.ms/azpipelines-parallelism-request) and wait 2β3 business days, or buy a parallel job / register a self-hosted agent to unblock immediately.
Project settings β Service connections β Azure Resource Manager β Workload identity federation (automatic). Scope it to the resource group, not the subscription. Name it for the environment (rg-prod-deploy), and do NOT tick "grant access to all pipelines".
Push failures with 403 later usually mean the connection identity lacks AcrPush β see the attached failure note.
β Image push fails 403 despite a green service connection
unauthorized: authentication required / 403 on push, while az acr login and pulls work
Likely cause: The connection's identity has no AcrPush role on the registry β "verified" only proves login, not authorization
Fix: Grant AcrPush on the registry to the service connection identity (az role assignment create --role AcrPush ...). Re-run β no pipeline changes needed.
Stages: Build (docker build + push to ACR, tag = $(Build.SourceVersion)), DeployStaging (deployment job targeting the staging Environment), DeployProd (same job, prod Environment). The image tag built once is the artifact every stage deploys β no rebuilds downstream.
Pipelines β Environments β new "staging" and "prod". On prod: Approvals and checks β Approvals β add the named approvers (min 1, ideally 2) and a timeout. This single screen is Rule 6 made real.
az pipelines run --name {{pipeline_name}} --branch {{branch}} --org {{org_url}} --project {{project}}
Approve in the run view. When prod is green, confirm the image digest running in prod matches the digest staging verified β same artifact, not a rebuild.
2 notes from the field β observations, discoveries, warnings, and lessons.
${{ }} resolves at template compile time, $( ) at runtime, and $[ ] lazily at runtime. A ${{ }} referencing a variable set by an earlier task will silently be empty β it was evaluated before the run started. When a variable is mysteriously blank, check which syntax consumed it before checking where it was set.
Twice now the lease check refused a push because a teammate had fixed something on the "abandoned" branch. Plain --force would have erased their commits silently. The refusal is not friction; it is the entire point of the flag.
2 known failuresβ the approaches that didn't work, preserved so you don't repeat them.
##[error]No hosted parallelism has been purchased or granted. To request a free parallelism grant, please fill out the following form...
Attempted: Ran the first pipeline in a brand-new organization
Context: Any new Azure DevOps organization created after the 2021 policy change
Likely cause: Free-tier hosted parallelism is grant-only for new orgs (an anti-abuse measure) and nobody requests it in advance
Diagnose: The error message itself; also Organization settings β Parallel jobs shows 0
Fix: Submit the grant form (aka.ms/azpipelines-parallelism-request) and wait 2β3 business days, or buy a parallel job / register a self-hosted agent to unblock immediately.
unauthorized: authentication required / 403 on push, while az acr login and pulls work
Attempted: Pipeline authenticated fine, then docker push to ACR returned 403
Context: Service connection created with the automatic defaults, scoped at the subscription with Reader-ish rights
Likely cause: The connection's identity has no AcrPush role on the registry β "verified" only proves login, not authorization
Diagnose: az role assignment list on the ACR for the connection's service principal / managed identity
Fix: Grant AcrPush on the registry to the service connection identity (az role assignment create --role AcrPush ...). Re-run β no pipeline changes needed.
Every org discovers the same lessons in the same order: pipelines drift when they live in the UI, secrets sprawl when they live in variables, and the first pipeline run fails on the parallelism grant nobody knew to request. This book is the shortcut past all of it, commands included.
Engineers who own build and release, and team leads setting up a fresh Azure DevOps org.
Initial publication.
Readers of this book also keep