In an Azure Pipelines YAML pipeline, what does declaring a job as `deployment:` with an `environment:` give you that a plain `job:` does not?
answer
- a job with a declared target
- the platform records where it went
- steps sit under a strategy hook
- gates live on the object, not the YAML
- runOnce, rolling, canary
basics
~20 sA deployment job targets a named environment, so Azure Pipelines records deployment history against it, enforces that environment's approvals and checks before the stage runs, and lets you choose a runOnce, rolling or canary strategy.
solid answer
~50 sA plain `job:` is just steps on an agent. A `deployment:` job binds those steps to an Azure DevOps **environment**, which is a first-class object in the project, and three things come with that binding. First, **traceability**: the environment page lists every deployment to it, with the commits and work items each one carried. Second, **gating**: approvals and checks configured on that environment are evaluated before the stage containing the job is allowed to start. Third, **strategy**: the steps no longer sit under `steps:`, they sit under a lifecycle hook of a `runOnce`, `rolling` or `canary` strategy, so the platform drives how the rollout proceeds. The environment can also hold Kubernetes namespace or virtual-machine resources that the job targets. Referencing an environment name that does not exist creates it automatically, with no resources and no checks on it.
code
yaml · 13 linesstages:
- stage: Deploy
jobs:
- deployment: DeployWeb
environment: production
pool:
vmImage: ubuntu-latest
strategy:
runOnce:
deploy:
steps:
- checkout: self
- script: ./scripts/deploy.shgo deeper
Know that a deployment job names an environment and that its steps go under a strategy hook such as runOnce.deploy.steps, not under a plain steps: list.
Be ready to list what the environment binding buys — deployment history with commits and work items, checks that gate the stage, resource targeting — and to explain the checkout and artifact-download defaults.
Show you know the gate lives on the environment object rather than in the YAML, and name the auto-creation trap: a mistyped environment name yields an ungated deployment that still reports success.
Own the question of which environments exist at all and who may create them. Argue for pre-created, permission-scoped environments so the deployment history is a trustworthy audit record rather than a pile of one-off names.
## The two job types Azure Pipelines YAML has two kinds of job. A regular `job:` is a unit of work that runs steps on an agent from a pool. A `deployment:` job is the same execution unit with a declared *target*: the `environment:` property. That one property is the hinge of Azure DevOps' change-control model. ## Steps move under a strategy The most visible difference is structural. A deployment job has no top-level `steps:`. Instead it has a `strategy:`, and the steps live inside one of the strategy's lifecycle hooks: ```yaml jobs: - deployment: DeployWeb environment: production pool: vmImage: ubuntu-latest strategy: runOnce: deploy: steps: - script: ./scripts/deploy.sh ``` `runOnce` is the simplest strategy: run the hooks once. `rolling` repeats them over batches of virtual-machine resources, and `canary` repeats them over percentage increments. Writing `steps:` directly under `deployment:` is a schema error, and it is the most common first mistake. ## The environment is a real object An environment is not a string label like a Git branch name. It is a project-level object with its own page under **Pipelines > Environments**. It holds: - **Deployment history** — every run that deployed to it, in order, with the commits and work items each deployment included. This is the audit trail an auditor or an incident responder asks for: *what is running in production right now, and which change put it there?* - **Resources** — optionally a Kubernetes namespace or a set of registered virtual machines, so the job can target concrete infrastructure and the page can show the live workloads or machines. - **Approvals and checks** — the gate list described below. - **Security** — which pipelines and which users may use it, including an "open access" toggle versus explicit pipeline permissions. If you reference an environment name that does not exist yet, Azure Pipelines creates it on the fly with no resources. That is convenient and also a trap: an auto-created environment has **no** checks on it, so a typo in the environment name silently produces an *ungated* deployment that goes straight through. Locking down who may create environments, and pre-creating the ones that matter, is the standard mitigation. ## Checks gate the stage When a stage contains a deployment job whose environment carries checks, the run pauses at the *start of that stage* until every check passes. No agent is consumed while it waits. The gate is attached to the environment, not written into the pipeline YAML, so a pipeline author cannot remove it by editing the file — which is exactly why compliance-minded teams like this model. ## Defaults that differ from a regular job Two defaults surprise people. A deployment job **does not check out the source repository** — add `- checkout: self` if a step needs repo files. And it **does automatically download** the pipeline artifacts published earlier in the same run, which you suppress with `- download: none`. The reasoning is that a deployment consumes an already-built artifact rather than rebuilding from source, which is the build-once-deploy-many discipline expressed as a default. ## Targeting resources When the environment holds resources, the job can name one: ```yaml environment: name: production resourceType: VirtualMachine tags: web ``` With VM resources, the machines themselves run the agent, so no `pool:` is given; the job fans out across every matching machine. With a Kubernetes resource, the resource carries the cluster service connection and namespace, so manifest tasks target it without a separate connection. ## When you do not need one Build, test and lint jobs should stay plain `job:` entries. A deployment job for work that does not change a running environment adds noise to the deployment history and buys nothing. Reach for `deployment:` exactly when the job is the thing that changes what is running somewhere.
- What happens if the environment name in your YAML has a typo?Azure Pipelines creates a brand-new environment with that name, no resources and no checks, and the deployment proceeds ungated. It looks like a successful production deploy while bypassing every approval. Restrict who may create environments and pre-create the real ones so a typo fails loudly rather than sailing through.
- Can two deployment jobs in the same stage target the same environment?Yes. The checks on that environment are evaluated once for the stage, not once per job, so approvers see a single approval request rather than two. That is worth knowing when you split a deployment into several jobs and wonder why you were only prompted once.
- Why does a deployment job download artifacts automatically but not check out the repository?Because a deployment is meant to consume the artifact built earlier in the run rather than rebuild from source — build once, deploy many. The default encodes that discipline. Add `- checkout: self` if a step genuinely needs repository files such as deployment scripts, or `- download: none` to skip the automatic artifact download.
saying these in an interview costs you the question
- Thinking an environment is just a label string
- Putting steps: directly under deployment: in the YAML
- Believing approvals are written into the pipeline YAML
- Assuming a deployment job checks out the repo like a normal job
- Using deployment jobs for build and test work