CAMPUX Cloud Bootcamp Milestone · Build III · After Class Twenty-Five ← Class Twenty-Five
Phase Three — Milestone
Working time 8–12 hours · Ships to your GitHub
The proof behind Classes 17–25
Build III

The GitOps Loop

The environment from Build II, now described in code and deployed by a robot: a pull request that plans, a merge that ships to non-production, a human gate before production, and — the line that wins interviews — not one stored secret anywhere in the system.

§1

The brief

The client's requirement is now the one senior engineers are actually hired to satisfy: "Nobody should deploy by clicking, ever. Every change to our infrastructure arrives as a reviewed proposal, ships to a test environment automatically, and reaches production only when a named person approves it — and if our whole GitHub organisation leaked tomorrow, no attacker should gain a single credential to our Azure estate." That last clause is the one most portfolios cannot honour, and it is the reason this build exists. Anyone can wire a pipeline; the interview separates candidates on whether the pipeline holds a secret.

Deliverable
The Build II environment expressed as Bicep, deployed by a GitHub Actions pipeline that plans on every pull request and gates production behind an approval — authenticating to Azure by OIDC federation, with gh secret list returning empty.

This build consumes the two before it. The estate is Build I's; the network and private storage are Build II's; here they stop being things you clicked and become things a file asserts and a robot enforces.1 Budget a full weekend — the OIDC trust and the environment gate each have a fiddly first-time setup, and getting them wrong is itself part of the learning the interviewer questions reward.

§2

Requirements — the ledger you build against

Rows in dependency order. R5 is the row the whole build is really about; everything above it is scaffolding for the claim it makes.

Build III — requirements ledger
#RequirementTaught inEvidence
R1The Build II environment as Bicep — VNet, subnets, storage, private endpoint, DNS zone — composed from modules, in a Git repositoryClass 20The repository; a main.bicep that composes named modules rather than one long file
R2Branch protection on main: pull request required, one approval, force-push blocked, a status check required to passClasses 18–19The ruleset screenshot; a direct push to main refused
R3A validation workflow: on every pull request, build the Bicep and post a what-if — the reviewer approves a named list of changes, not a hopeClasses 20, 22A pull request showing the what-if output as a check; a broken template turning the check red
R4A deploy workflow: on merge to main, deploy to nonprod; then request production and stop for approvalClasses 22–23One run showing nonprod deployed automatically and production waiting on a human
R5OIDC federation to Azure — two service principals, each with a federated credential and resource-group-scoped Contributor; no client secret anywhereClass 23gh secret list returning empty; the federated-credential subjects shown; a successful keyless deploy in the logs
R6Environment protection: the production environment carries a required-reviewer rule, and its credential trusts only the environment:production subjectClass 23The approval gate firing; the subject claim shown to be environment-scoped, not branch-wide
R7Pipeline hygiene: timeout-minutes on every job, a least-privilege permissions block, and concurrency control on the deployClass 24The three settings visible in the workflow files; one README paragraph on why each is there

Nothing stored, nothing to steal.

The boundaries. Do not over-build: no monitoring, no cost alerts, no AI — those are Build IV and Phase Four, and adding them here dilutes the one story this build tells cleanly. Do not fake R5: a client secret hidden in a repository secret and called "temporary" is the exact anti-pattern Class Twenty-Three exists to kill, and a reviewer who runs gh secret list finds it in four seconds. The empty list is the deliverable; everything else is how you earn the right to show it.

§3

The rubric — how a reviewer marks it

The bands, sharpened for a build whose subject is trust.

Functional — the floor
The pipeline plans on a pull request, deploys to nonprod on merge, gates production, and authenticates by OIDC with no stored secret. The loop closes; the story is thin.
Reasoned — the target
Functional, plus the README defends the shape: why the what-if is posted before approval, why two service principals instead of one, why the production subject is environment-scoped. The difference between wiring a pipeline and designing one.
Professional — the ceiling
Reasoned, plus the pipeline audit run on your own repository — the four Class Thirty-One questions answered in writing — and evidence that the gate cannot be bypassed: a feature-branch run shown failing to reach the production credential because its subject does not match. This is the version that ends the interview early.

The capping deduction is the build's whole thesis in one line: any stored long-lived credential — a client secret, a publish profile, a storage key — caps the build at Functional, no matter how elegant the rest. The pipeline that holds a secret has not solved the problem; it has relocated it.

§4

What an interviewer will ask

The questions this artifact provokes, in arrival order. R5 draws most of them, which is why it draws most of the marks.

"How does your pipeline authenticate to Azure?"
The whole Class Twenty-Three handshake, aloud: GitHub signs a token about the run, Entra checks it against a federated credential, and issues minutes of access — nothing stored on either side. Walk the three actors and you have answered the question most candidates cannot.
"What does the subject claim protect?"
It is the filter deciding which runs may become which principal. Environment-scoped for production means only a run that already passed the approval gate carries the subject the credential trusts — the gate and the key are the same object.
"Why post the what-if before approval?"
Because approving a pull request should mean approving a named list of creates, changes, and deletes — not trusting that the diff does what its author believes. The delete line is the one that justifies the whole practice.
"A feature branch is compromised — what can it reach?"
Nonprod at most, and only if its subject matches; production's credential shrugs, because the branch's token subject is not environment:production. If you tested this yourself, say so — proven blast-radius limits read as seniority.
"What would you add before calling this production-ready?"
Observability and cost guardrails over the whole loop — which is precisely Build IV, named as the deliberate next step. Scope chosen, not stumbled into, for the third build running.
Case File · Campux Retail

The page Campux shows interviewers

this build is Classes 20–24, assembled into one loop

Campux built this exact loop across Phase Three: the environment became Bicep in Class Twenty, the validation workflow landed in Class Twenty-Two, and Class Twenty-Three closed the credential question with federation — gh secret list returning empty, described there as "the artifact worth walking an interviewer through slowly." This build is you earning that same empty list. When you reach Build IV, this pipeline is what grows monitoring and a budget; keep it, because the observability you add next has to watch something, and this loop is the something.

Notes
  1. If Builds I and II were torn down, you can rebuild their Azure side from this build's Bicep once R1 is written — which is the entire promise of infrastructure as code arriving for real. The federated-credential setup has a genuine ordering trap: the app registration and its federated credential must exist before the first workflow run, or the login step fails with an error that looks like a permissions problem and is actually a timing one. The README should note the order you found.