CAMPUX Cloud Bootcamp Phase Three Supplement · Class Forty
Phase Three — DevOps Core · Supplement
Reading 34 min · Drills 6 · 1 Desk Lab
AZ-400 alignment
Class Forty

Azure DevOps Pipelines

You learned CI/CD on GitHub Actions; the company that hires you may run it on Azure DevOps — same discipline, older estate, different nouns — and the engineer who can walk in speaking both is worth two who can only speak one.

§1

The other CI/CD system — and why it's everywhere

Phase Three taught you continuous delivery on GitHub Actions, and taught it there for good reasons: it is where the industry's momentum is, it is what your portfolio runs on, and Microsoft — who owns both — has made GitHub the visible front of its developer strategy. But walk into a mid-size company that adopted Azure before 2020 and the odds are excellent that the deployment machinery lives in Azure DevOps: a full suite — Boards for work tracking, Repos for Git, Pipelines for CI/CD, Artifacts for packages, Test Plans — that was the standard way enterprises shipped to Azure for a decade, and still runs an enormous share of the world's production deploys.1 This class exists for the first week of that job.

Hold two facts about it at once, because both shape your working life. First: Azure DevOps is not legacy — it is actively supported, deeply integrated with Azure, and for organisations that live in it, Boards-to-Pipelines traceability (this work item, to this commit, to this deploy) is a genuine strength GitHub only approximates. Second: the strategic weather is visible — Microsoft's new investment flows conspicuously toward GitHub, and the two platforms have been converging for years. The practical posture this produces is the one this class teaches: respect the estate, learn its nouns, and keep everything you build in it portable — which, it will turn out, mostly means one thing: YAML in the repository.

§2

Classic build & release — the estate you will inherit

Before YAML, Azure DevOps pipelines were built in the portal: a classic build pipeline assembled as a visual list of tasks, and a separate classic release pipeline drawn as a chain of stages — Dev, Test, Prod — with approval gates between them, each configured by clicking. You will meet these, in numbers, because they worked: a decade of enterprises shipped reliably on them, the release view's stage-by-stage picture is genuinely legible to non-engineers, and machinery that works does not get rewritten just because fashion moved. When you inherit seventy of them, that is not a scandal; that is a decade of a company shipping.

But you know the argument against them already, because it is Class Twenty's argument wearing pipeline clothes: a pipeline built by clicking is infrastructure built by clicking. It lives outside Git — no pull request reviews a change to it, no history explains why the deploy step changed on March 3rd, no branch carries a pipeline experiment safely. It drifts: the person who built it edits it live, in production, because there is nowhere else to edit it. It cannot be duplicated for the next project except by screenshot archaeology. And when it breaks at deploy time, the diff you need — what changed in the pipeline? — does not exist. Classic pipelines are the click-configured VM of the CI/CD world: everywhere, functional, and precisely the thing the last twenty classes taught you to migrate opportunistically rather than venerate or panic about.

A pipeline you can't diff is folklore.

§3

YAML pipelines — your Class 22 skills, re-nouned

The modern Azure DevOps pipeline is a file — azure-pipelines.yml, in the repository, reviewed and branched like everything Phase Three taught — and here is the sentence that should relax you: you already know this system; you know it under different nouns. The concepts you drilled in Classes Twenty-Two through Twenty-Four map across nearly one-to-one:

Table 1 — The translation, Actions to Pipelines
GitHub ActionsAzure PipelinesThe difference that matters
Workflow (.github/workflows/*.yml)Pipeline (azure-pipelines.yml)Same idea; Pipelines adds an explicit stages layer above jobs for multi-environment flows.
JobJobIdentical concept: a unit of work on one machine, parallel by default.
Step / actionStep / taskMarketplace actions become built-in and marketplace tasks; the Class 22 caution about third-party code transfers verbatim.
RunnerAgent (pool)Microsoft-hosted or self-hosted, same trade-offs as Class 24 — including the same security rules for self-hosted.
Secrets / environmentsVariable groups · Library · EnvironmentsVariable groups can link to Key Vault; environments carry the approval gates.
Environment protection rulesEnvironment checks & approvalsThe Class 23 human gate before production, wearing its ADO name.
Reusable workflowsTemplatesSame DRY instinct; templates compose steps, jobs, or whole stages across repos.
OIDC federation to AzureService connection with workload identity federation§4. The single most important row on this table.

Read a real one once and the familiarity lands: trigger is on:, pool picks the agent, stages hold jobs hold steps, and a step is either a script or a task. Everything structural you learned — plan on PR and apply on merge, least-privilege tokens, gates before production, no secrets in the file — transfers as discipline, independent of dialect. That is the real content of this class: the discipline was never GitHub's; it was yours.2

§4

Service connections — the credential question, asked again

Every CI/CD system eventually faces the same question Class Twenty-Three called the most important in Phase Three: how does the pipeline prove to Azure that it is allowed to deploy? In Azure DevOps the answer object is the service connection — a named, permissioned credential that pipelines reference instead of holding secrets themselves — and it comes in the same two flavours that OIDC taught you to distinguish. The old way: a service principal with a client secret stored inside the service connection — a long-lived password sitting in a vendor's database, expiring at the worst moment (the classic "deploys mysteriously failing" ticket is an expired service connection secret), and powerful enough that its theft is Class Thirty-One's nightmare scenario. The current way: workload identity federation — the service connection holds no secret at all; Azure DevOps proves its identity to Entra with a federated token exchange per run, exactly the OIDC pattern you built in Class Twenty-Three, wearing ADO's name for it.3

Service connection
Azure DevOps's named bridge to an external system — for Azure, an identity with scoped RBAC that pipelines reference by name; federated, it holds no secret, and the Class 23 rule holds: scope it to a resource group, never the subscription.

The rest of the §4 checklist is Class Twenty-Four's, re-nouned. Agents: Microsoft-hosted for the default case; self-hosted where network reach or custom tooling demands it — and a self-hosted agent is a machine that executes whatever pipelines say, so it gets the same patching, isolation, and least-privilege suspicion as a self-hosted runner. Approvals live on environments, and the audit question from Class Thirty-One's pipeline audit transfers word for word: what can each service connection reach, who can use it, and who reviews the file that invokes it? Run that audit on an inherited ADO estate in week one and you will usually find at least one subscription-scoped, secret-bearing service connection that every pipeline in the org can use. Finding it is the job; federating and scoping it is the first month's quiet win.

§5

Meeting classic in the wild — the migration posture

So it is week one, the estate has seventy-four classic pipelines, and two bad instincts will present themselves. The first is the crusade: "we should migrate everything to YAML" (or, more ambitiously, "to GitHub") — a quarter of rewriting machinery that currently works, producing zero features, carrying real regression risk, and burning the political capital Class Thirty-Seven told you to spend on measured wins. The second is surrender: treat the classic estate as scenery, learn nothing, touch nothing, and let the click-drift compound. The professional posture sits between, and it is a policy you can state in three sentences: new pipelines are born YAML, no exceptions. Existing pipelines convert when touched — the next real change to a classic pipeline is done as its YAML rewrite, so effort lands only where change is already happening. And the riskiest credentials convert first regardless of touch-order, because a secret-bearing, subscription-scoped service connection is a standing liability whether or not its pipeline ever changes again.

One honest caution keeps the policy from becoming its own crusade: a conversion is a behaviour-preserving rewrite, and classic release pipelines hide behaviour in their corners — a variable set at stage scope, a task version pinned years ago, a gate wired to a person who left. Convert with the Class Thirty-Six discipline: one pipeline at a time, the YAML version run in parallel against a non-production target until its output matches, then cut over with the old one disabled but kept for a month, not deleted. It is the database migration from Class Thirty-Eight in miniature — the contents you cannot lose here are the accumulated fixes nobody documented, and the parallel run is how you find them without a Saturday.

Case File · Campux Retail

The acquisition ships on classic

Basecamp Outfitters joins the estate, pipelines and all

Campux buys a smaller competitor — Basecamp Outfitters, nine stores, one warehouse system — and with it an Azure DevOps organisation that has shipped reliably since 2019: Boards full of history, Repos full of code, and thirty-one classic pipelines, including the one that deploys the warehouse system everyone now depends on. The instinct in the first integration meeting is the crusade ("move it all to GitHub, this quarter"), and the §5 policy is what the engineer reads out instead. The estate stays; the nouns get learned; and the audit runs first. It finds what week-one audits find: one service connection, named azure-prod, secret-bearing, scoped to the whole subscription, used by all thirty-one pipelines — and its secret expires in five weeks, which explains a mysterious recurring ticket in the acquired team's backlog titled simply "deploys broken again?? (monthly)".

The first month's work is exactly this class in order. The warehouse pipeline — the one that matters — gets its YAML rewrite via the parallel-run discipline: three weeks side by side against staging, two undocumented behaviours discovered and preserved (a stage-scoped variable and a task pinned to an ancient version for a reason, it turns out), then a quiet cutover. The service connection is replaced by three federated, resource-group-scoped connections — no secret to expire, and the monthly ticket closes forever, which wins the acquired team over more thoroughly than any architecture diagram. Everything else converts when touched, and the Basecamp engineers — who arrived braced to be told their decade of work was legacy — instead watch their own estate get the same respect, the same audit, and the same guardrails as Campux's. Two of them, unprompted, start reading this bootcamp from Class One. That is the integration actually succeeding.

Watch · Microsoft Learn

The official pages, and a CAMPUX overview

The Pipelines overview before the desk lab; the federation page before touching any service connection
Microsoft Learn · Docs

What is Azure Pipelines?
learn.microsoft.com/azure/devops/pipelines/get-started/what-is-azure-pipelines

Service connections with workload identity federation
learn.microsoft.com/azure/devops/pipelines/library/connect-to-azure

CAMPUX overview video

A classic release pipeline and its YAML rewrite side by side, the Table 1 translation narrated over both, and a federated service connection created with no secret anywhere — will live here. Video to be added.

Desk Lab · The translation

Rewrite your Class 22 workflow in the other dialect

~15 minutes · paper or a text editor · Table 1 open beside you

The fastest proof that you already know Azure Pipelines is translating something you wrote yourself. Take the Class 22 build-and-deploy workflow and re-noun it, line by line.

  1. Write the skeleton from memory: trigger (which branch?), pool (which agent image?), then stages → jobs → steps.

    Check yourself: trigger is your old on:, the pool line is your runs-on, and the extra stages layer is where Build and Deploy — which Actions expressed as two jobs — become two named stages with a dependency.
  2. Translate the steps: checkout, build, test. Which become script lines and which become task references?

    Check yourself: your shell commands move across nearly untouched as script steps — the Class 25 investment paying its dividend — while marketplace actions map to their task equivalents. Checkout, notably, is implicit in Pipelines unless you say otherwise.
  3. Now the deploy stage: write the AzureCLI task referencing a service connection by name, and add the environment with an approval.

    Check yourself: the service connection name replaces your Class 23 federated credential setup, the environment approval replaces your protection rule — and notice what is absent, in both dialects: any secret, anywhere in the file. If your translation contains a credential, the translation is wrong in both languages.
  4. Last step: annotate each line of your translation with the Table 1 row it came from, and circle anything that had no equivalent.

    The lesson: the circles will be few and small. Ninety percent of your Phase Three knowledge crossed the bridge intact, because the knowledge was never the syntax — it was plan-before-apply, gates before production, no stored secrets, least privilege. Bring this annotated page to the interview in your head; Situation 02 is where you will spend it.
Note · to run it for real: dev.azure.com, a free organisation, and the free Microsoft-hosted agent grant — though new organisations may need to request the free parallelism grant, which takes a form and some days. The desk version teaches the same translation without the wait.
Think in systems

Zoom out: a pipeline is a delivery system, not a script

You have built a pipeline that gets code to production. Now reason about it as a system with flow, queues, and human behaviour — because a delivery pipeline shapes how a whole team works, not just how one commit ships. Systems thinking is the habit of looking past the box you just built to the loops, dependencies, and limits around it. Take a whiteboard and work these five prompts before the exam.

Feedback loops

Fast, green pipelines build trust, so people merge small and often — a reinforcing loop that makes delivery safer. Flaky tests do the reverse: red builds that "just need a re-run" teach everyone to ignore failures, until a real one slips through. Which loop is your pipeline currently training people into?

Dependencies & coupling

A deploy depends on agents, artifacts, service connections, and the order of its stages. Draw the chain: what has to be healthy for a release to reach production? A shared agent pool or an expiring service-connection credential is a dependency that fails quietly — until everything waits on it at once.

The constraint

Lead time is set by the slowest stage, not the average one. Find the bottleneck — the ten-minute integration test, the approval that waits for a person, the single environment two teams queue for — because speeding up any other stage changes nothing until that one moves.

Second-order effects

You parallelise the build to make it faster. It is — and now you exhaust the agent pool, hit an API rate limit, and two pipelines deadlock over the same environment. More concurrency solved the wait and created a new kind of contention. Name it before it names you at 5pm on a Friday.

What breaks when it scales

At ten times the commits per day, what gives first — agent availability, queue time, or the one shared staging environment everyone fights over? Which is a matter of buying more runners, and which is a redesign of how environments and branches map to the pipeline?

The engineer who ships is asked "does it work?" The engineer who gets promoted is asked "and then what?" — and has already drawn the loop.

On the job

The road that code travels on

You · Cloud Engineer · deliver it end to end

The whole loop is yours now: commit to production, reviewed and repeatable. You build the pipeline — tests, a gated environment, an approval, a deploy that runs the same way every time — so no one ships by clicking and every change is traceable. On your last day of the bootcamp you are not learning the tools; you are the person the team trusts to run the road that code travels on.

Class Forty

Examination

Four drills, then two situations. The situations have no marking scheme — write your answer before you reveal the reasoning, or the exercise is worthless. Nothing is stored; this is between you and the page.

Drill 01Recall · classic vs YAML
A teammate asks why the new project's pipeline must be YAML when the team's classic release pipelines "work fine and are easier to read." What is the load-bearing difference?
Marked

B — and the teammate's "easier to read" deserves a straight answer, because it is true and beside the point. The release view's stage diagram is more legible at a glance; what it cannot do is answer the question that matters at 2:14 on a deploy-broke Saturday: what changed in this pipeline, when, and by whom? A YAML pipeline answers from Git history in one command; a classic pipeline answers with whatever the last person to click remembers. That difference compounds: review before change, branches for pipeline experiments, one diff covering the app and the machinery that ships it. A invents a performance story that does not exist. C overstates the weather — classic is discouraged for new work, not switched off, and telling an inherited team their estate is about to stop working costs you credibility you need (the honest version is §1's). D is simply false, as a decade of classic deploys to Azure attests. The Class 20 sentence, reusable here verbatim: it is not clicking versus typing — it is unrecorded versus reviewed.

Drill 02Recall · translation
In an Azure Pipelines YAML file you meet: a pool declaration, a task reference, and an environment with an approval check. What are their GitHub Actions equivalents?
Marked

Pool is runs-on, task is action, environment approval is protection rule — Table 1's three most-used rows. This drill looks like trivia and is actually the §3 thesis in miniature: the systems are one discipline in two dialects, and fluency in the mapping is what lets you read an inherited pipeline on day one instead of week three. The wrong answers mark the two failure modes of the new joiner. A and B shuffle real nouns into wrong slots — close enough to sound informed, wrong enough to misconfigure something (a variable group is not an approval mechanism, and treating it as one leaves production ungated). D is the expensive belief: engineers who think they are starting over avoid the inherited system, defer to whoever already knows it, and surrender the review seat at exactly the moment the estate needs fresh eyes. You are not starting over. You are reading your own knowledge in translation — which is why the desk lab makes you do it on paper once, before an interview or an incident makes you do it live.

Drill 03Select three
The warehouse pipeline is being converted from classic release to YAML. Which three does the conversion actually buy?
Marked

Review, history, and safe experiments — the pipeline joins the same governance as the code it ships. Notice all three are the same purchase: putting the file in Git buys everything Git buys, and nothing else. The rejects each teach a boundary. The speed claim is folklore — execution time is the agent's and the tasks', not the format's, and justifying a conversion with a performance promise you cannot keep is how migrations lose sponsors mid-way. The secret claim is the dangerous one: conversion and credential hygiene are orthogonal — a YAML pipeline will happily use the same secret-bearing, subscription-scoped service connection the classic one did, forever, and the team that believes conversion "handled security" skips the §4 audit exactly where it matters. The case file did them as two deliberate moves — parallel-run conversion, then federated scoped connections — because they are two moves. Say what a change buys precisely; oversold migrations default on their promises at review time.

Drill 04Spot the error
This migration plan is about to be approved. One line is a serious mistake. Which?
# plan: warehouse pipeline, classic to YAML
1.  Rewrite as azure-pipelines.yml; run in parallel
    against staging until outputs match; keep the
    disabled classic pipeline for 30 days.
2.  Auth: create the service principal a client
    secret, store it as a secret variable in the
    pipeline's variable group, and rotate it yearly.
3.  Production stage gated by an environment approval
    (two named owners).
4.  Agent: Microsoft-hosted; the self-hosted agent VM
    from 2019 is retired after cutover.
Marked

Line two — it carefully secures a secret that has no reason to exist. Read it generously and every word is best-practice-shaped: marked secret, in a variable group, rotation scheduled. But the plan is decorating a liability instead of deleting it. A federated service connection holds nothing: no string to mark secret, no expiry to ticket, nothing for Class 31's scanners to one day find in a log. And "rotate yearly" is the tell — it schedules the exact failure the acquired team already suffered monthly, just less often: the credential expires, deploys break, and the ticket reads "deploys broken again??". The Class 23 rule was never "store secrets carefully"; it was the best secret is the one that does not exist, and ADO has supported that answer for years.

The distractors are the plan at its best: the parallel run is §5's discipline and the thing that catches the undocumented stage variable (A — agent minutes are the cheapest insurance in the document); environment approvals are fully supported in YAML and are precisely the Class 23 gate (C); and retiring an unpatched 2019 agent VM is Class 24's hygiene arriving five years late but arriving (D). The review reflex this drill installs: whenever a plan says "store the secret securely," ask first whether the secret needs to exist. Half the time, in 2026, it does not.

Situation 01Write before you reveal
Week two at the new job. The estate: 74 classic pipelines, all working. Your manager, fresh from a conference: "Should we just migrate everything to YAML this quarter? Or even straight to GitHub Actions? I can get budget." What do you advise?
Budget for a rewrite of working machinery is also budget not spent on something. What does the estate actually need first — and what converts on its own schedule?
Reasoning

The trap is answering the question as asked, because both of its options are crusades. Seventy-four working pipelines rewritten in a quarter is a project with real regression risk, zero feature output, and a success state invisible to everyone outside engineering — the exact shape of initiative that gets cancelled at week eight with a third of the estate half-migrated, which is worse than either end state. And "straight to GitHub Actions" doubles the blast radius by changing the platform and the dialect at once, for an organisation whose Boards history, permissions, and habits all live in ADO. Decline both politely — but do not waste the manager's energy, because a manager offering budget for pipeline hygiene is rare weather. Redirect it.

Give them the §5 policy with a risk-ranked first target. New pipelines born YAML, from today, as policy — free, immediate, and stops the hole deepening. Existing pipelines convert when touched, so effort lands only where change already happens. And the budget goes to the one thing worth doing proactively: the §4 audit and credential cleanup — enumerate every service connection, find the secret-bearing, subscription-scoped ones (there will be at least one, used by everything), and replace them with federated, resource-group-scoped connections. That work is invisible in a demo and priceless in an incident, it de-risks all 74 pipelines at once without rewriting any of them, and it produces a number for the manager's slide: "standing credentials in the deploy path: was 6, now 0."

Close by giving the conference its due, so the manager keeps their win. The instinct behind the question is right — the estate should trend toward YAML, and maybe eventually toward GitHub; the correction is sequencing, not direction. Offer the milestone version: this quarter, the audit plus the top three riskiest pipelines converted via parallel run; next quarter, reassess with data. The sentence for the meeting: the pipelines aren't the risk — the credentials under them are, and fixing credentials doesn't require touching a single pipeline that works.

Situation 02Write before you reveal
The interview is going well until: "One concern — we're an Azure DevOps shop, and your portfolio is entirely GitHub Actions. How long until you're productive here?" Answer it — with the translation, out loud.
Don't argue that the platforms are similar — demonstrate it. Walk your own pipeline across the bridge, noun by noun, in under a minute.
Reasoning

The question is an invitation wearing a concern's clothing — so answer with a demonstration, not a reassurance. "Very quickly, and let me show you rather than claim it" — then walk your own Build III across the bridge, out loud: "My pipeline plans on pull request and applies on merge through an approval gate, with no stored secrets — auth is OIDC federation. In your terms: the workflow becomes an azure-pipelines.yml with stages; my runs-on becomes a pool; my marketplace actions become tasks; the environment protection rule becomes an environment check; and the OIDC setup becomes a service connection with workload identity federation, which I'd scope to a resource group, never the subscription." Sixty seconds, eight nouns, and the concern is not answered — it is dissolved, because you just read their stack back to them in their own vocabulary without having named a single thing you'd have to learn.

Then relocate the skill where it actually lives, because that is the senior move. "The part of my portfolio I'd bring unchanged isn't the YAML dialect — it's the decisions: plan before apply, humans before production, credentials that don't exist rather than credentials well-hidden, pipeline changes reviewed like code. Those are platform-independent, and honestly, they're rarer than dialect fluency." This reframes the interviewer's mental model from "GitHub person who must relearn" to "CI/CD engineer who happens to have receipts on one platform" — and it is simply true, which is why it survives follow-up questions.

End with a question that proves you've already moved in. "Can I ask — are your service connections federated, or still on stored secrets? That's usually where I'd look first in any ADO estate." Whatever the answer, you have done the Class 37 close: turned the interview's hardest question into a working conversation between colleagues, and left them with the distinct impression that the productivity question runs in the other direction. A concern handled this way is worth more than a portfolio that never raised it — and that, one final time, is the whole method of this bootcamp: the gap between you and the job was never the missing noun. It was the proof — and now you carry the proof.

Examination record · first attempt
0/4
Class Forty · Complete
Retain this much

Five things worth carrying out of this class

  1. Azure DevOps is the estate a large share of employers actually run — not legacy, actively supported, with the strategic weather visibly favouring GitHub. Respect it, learn its nouns, keep what you build portable.
  2. Classic build and release pipelines are the click-configured VMs of CI/CD: everywhere, functional, and undiffable — Class 20's argument decides the matter for all new work. A pipeline you can't diff is folklore.
  3. You already know Azure Pipelines: workflow→pipeline, runs-on→pool, action→task, runner→agent, protection rule→environment check. The discipline — plan/apply, gates, no secrets — was never the platform's; it was yours.
  4. The service connection is the credential question again, and federation is the answer again: no stored secret, no expiry ticket, scoped to a resource group. "Store the secret securely" loses to "the secret does not exist."
  5. Meeting classic in the wild: new pipelines born YAML, existing ones convert when touched via parallel run, riskiest credentials convert first regardless. Neither crusade nor surrender — the migration posture of this entire bootcamp, one last time.
Notes
  1. Treat any specific market-share claim about Azure DevOps versus GitHub with suspicion — the numbers are argued about and change yearly; the direction is settled in both halves: an enormous installed base still ships on ADO, and net-new investment flows toward GitHub. Both halves matter to your career, which is precisely why this class exists. Microsoft's own guidance for new projects has favoured GitHub for years while committing to ADO's support — read the current positioning before repeating anyone's prediction of its demise, including one you infer from this page.
  2. This class compresses a large product to its pipeline heart. Boards, Repos with their branch policies, Artifacts feeds, and Test Plans each have their own depth, and an ADO-centric employer will expect you to find your way around all of them — a week of using them answers most of it. The transferable instinct: every one of them is a variation on something Phase Three taught, wearing enterprise trim.
  3. Workload identity federation for service connections went from preview to recommended-default in recent years, and Azure DevOps can convert an existing secret-bearing Azure service connection to federation in place — a genuinely rare case of a security upgrade that is one action rather than a project. Check the current docs for edge cases (some sovereign clouds and legacy configurations lag), but the default posture is settled: new connections federated, existing ones converted, secrets nowhere.