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.
Microsoft now withholds the free Microsoft-hosted parallel job from a brand-new organisation by default, to stop it being used for hidden crypto-mining. Expect to hit this: when you try to run the pipeline in Step 3, the run queues forever and the log reads "No hosted parallelism has been purchased or granted." Handle it before you get there. Go to aka.ms/azpipelines-parallelism-request — the same link Azure DevOps prints inside that error — and submit the request against your new organisation now, while Steps 1 and 2 still give you something to do. Microsoft states a two-to-three business day review, and some requests take longer. The alternative, in Organization settings → Billing, is linking the organisation to a real Azure subscription, which also triggers the grant automatically — but it must be a billable subscription such as Pay-As-You-Go; Azure DevOps does not accept the Azure Free Trial for billing. Either path costs nothing: the grant itself is one Microsoft-hosted job, 1,800 minutes a month, free.
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 run build has 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 run build displayName: 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 with a banner reading "This pipeline needs permission to access a resource" — select View, then Permit. That click creates the environment; every later run against the same name skips it. If instead the run never starts and stays queued, that is the free-tier grant from the callout above, not this environment step — go request it if you have not already.
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.