Victor commits the pipeline, watches it run, removes checkout: self, watches it fail, then fixes it.
The gap between reading YAML and owning it
You can read azure-pipelines.yml a dozen times and still not know what happens when a merge fires it, an agent picks it up, and one stage waits on another. This lab closes that gap on the cheapest possible instance of the file: no Azure subscription, no billable resource, nothing but a free Azure DevOps organisation and a browser. You commit the same shape the class taught — a Build stage with an ordinary job, a Deploy stage with a deployment job — watch both go green, then remove the one line the class warned you about and watch the deploy fail for exactly the reason it predicted.
Read it once. Break it once. Then you own it.
You need a Microsoft account (a free outlook.com one works) and a browser — no local installs, no az CLI, no Cloud Shell. Sign up for a free organisation at dev.azure.com if you do not already have one.
A brand-new organisation does not always start with its free Microsoft-hosted parallel job active. If your run sits queued forever with "No hosted parallelism has been purchased or granted," go to Organization settings → Billing and link the org to an Azure subscription (even a free one) — that is what triggers the automatic free grant of one Microsoft-hosted job at 1,800 minutes a month. It can take a few minutes to a few days to apply; nothing in this lab costs money either way.
A free organisation and project
Everything here happens in the browser, at dev.azure.com.
# in the browser, not a terminal
1. Sign in at https://dev.azure.com with your Microsoft account
2. "Create new organization" > pick a name and a region > Continue
3. "Create a new project" named campux-warehouse
- Visibility: Private
- Version control: Git
- Work item process: Basic
campux-warehouse's empty Repos page, offering to initialise the repo. Click Initialize with a README so you have a main branch to commit onto.Commit the pipeline, entirely in the browser
Use the Repos web editor — Repos → Files → New → File — to add two files at the repository root. The first is a placeholder "build," so npm ci and npm run build have something real to do without needing an actual application:
# package.json — at the repo root
{
"name": "campux-warehouse",
"version": "1.0.0",
"scripts": {
"build": "echo 'warehouse build complete' > dist-marker.txt"
}
}
The second is the pipeline itself — same shape as the class: a CI trigger, a PR trigger, a Build stage whose ordinary job gets its checkout implicitly, and a Deploy stage whose deployment job does not — so it checks out source explicitly on purpose, then reads a file from that source to prove the checkout mattered:
# azure-pipelines.yml — committed at the repository root trigger: branches: include: [ main ] pr: branches: include: [ main ] stages: - stage: Build jobs: - job: build pool: vmImage: ubuntu-latest steps: # checkout: self is implicit here — source is already present - script: | npm ci --no-audit --no-fund || true npm run build displayName: Install and build - stage: Deploy dependsOn: Build jobs: - deployment: deployWarehouse pool: vmImage: ubuntu-latest environment: warehouse-production strategy: runOnce: deploy: steps: - checkout: self # deployment jobs do NOT auto-checkout — this is the line we break - script: | echo "Deploying the warehouse build..." cat README.md displayName: Deploy build to the warehouse app
Repos → Files lists both package.json and azure-pipelines.yml at the root, on main.This lab is about the pipeline mechanics — stages, jobs, the implicit-versus-explicit checkout — not about authenticating to Azure. The deploy step reads a file from the checked-out repo instead of calling az; that is enough to prove whether the source is there. Deploying for real, through a properly scoped service connection, is the next lab.
Create the pipeline and watch it run
Point Azure Pipelines at the file you just committed, then watch both stages go green.
# in the browser
1. Pipelines > Create Pipeline
2. "Where is your code?" > Azure Repos Git
3. Select the campux-warehouse repository
4. "Configure your pipeline" > Existing Azure Pipelines YAML file
5. Branch: main Path: /azure-pipelines.yml
6. Review, then "Run"
The first run against a fresh environment name usually pauses once, asking you to approve the deployment job's use of warehouse-production — approve it. That approval creates the environment; every later run against the same name skips it.
Deploy build to the warehouse app step's log: it printed the contents of README.md, proof the explicit checkout: self put the source on the deployment agent.Break it: remove the one line
Now do on purpose what people do by accident. Open azure-pipelines.yml in the Repos web editor, delete the - checkout: self line from the Deploy stage's steps, and commit straight to main. The CI trigger fires the pipeline again automatically.
Deploy build to the warehouse app step fails: cat: README.md: No such file or directory. The deployment job's workspace is empty because a deployment job, unlike an ordinary job, does not clone the repository automatically — the exact behaviour the class flagged as the one people get caught by.Fix it and watch it pass again
Put the line back exactly where it was, first step of the deploy hook, and commit again.
strategy:
runOnce:
deploy:
steps:
- checkout: self # restored
- script: |
echo "Deploying the warehouse build..."
cat README.md
displayName: Deploy build to the warehouse app
README.md. The identical job — same task, same script — went from failing to passing because of one checkout step. That is the entire lesson, watched rather than read.Tear it down
Nothing here billed you — an idle Azure DevOps organisation, project, and pipeline cost nothing while they sit unused. Tear down anyway; a stray pipeline nobody remembers is exactly the debris a real project accumulates.
# in the browser
1. Pipelines > select the pipeline > ⋯ > Delete
2. Pipelines > Environments > warehouse-production > ⋯ > Delete environment
3. Optional — remove the whole project:
Organization settings > Projects > campux-warehouse > ⋯ > Delete
4. Optional — remove the whole organisation if you made it just for this lab:
Organization settings > Overview > Delete
What you can now honestly claim
You created an Azure DevOps organisation and project from nothing, committed a two-stage azure-pipelines.yml, watched a build job and a deployment job run on separate agents, and proved with your own broken and fixed run — not a paragraph you took on faith — that a deployment job does not check out source automatically. You know what a CI trigger and a PR trigger each answer, why stages hold jobs and jobs hold steps, and the one line that catches almost everyone moving from GitHub Actions. The credential this pipeline is missing on purpose — a real, secret-free connection to Azure, scoped to one resource group — is the next lab.