This guide explains how this delivery session curriculum manages external dependencies, source apps, and third-party tools. Course content lives in this repository; private predecessor repositories are not required or referenced by the course.
- Content lives in-tree — course modules are embedded under
modules/*/resources/andmodules/*/challenges/; no participant or organiser needs a private upstream repo. - Local app dependencies managed as lazy submodules — Juice Shop and the Azure SRE Agent starter lab are registered at exact commits but fetched only when needed.
- Explicit pinning — all refs (commit SHAs, tags) are documented and validated.
- External repo references stay current —
external-repos.jsonlists only active external repositories required by the course.
- Source: https://github.com/juice-shop/juice-shop
- Pinned ref:
v20.0.0(tag) = commitf356a09207c7a9550eb6fc4c3945e081922cf998 - Used by: GHEC activities (ch11–ch15), GHAS setup
- Import mode (org repo): Activity setup scripts (
setup.sh provision) import the repo into org-owned GitHub repositories — each activity gets its own isolated, disposable copy (e.g.,ghec-ch11-juice-shop,ghec-ghas-00-juice-shop). GHAS alerts run on that org repo. - Local runtime (GHAS participants): GHAS activities also run Juice Shop locally for manual exploit testing. This local instance has no GHAS alerts — it is the app only, not the security-scanning target. See Local app provisioning (submodules) below for how to get it running.
- Why Juice Shop is large but not vendored: At ~61 MB it would bloat the curriculum repo and slow container creation for participants who never need it. It is registered as a git submodule and fetched on demand.
- Source: https://github.com/microsoft/sre-agent
- Pinned ref: commit
673f88765b27d4a74ebc660875bf605a382b6d28 - Used by: SRE Agent activities 00, 01, 03, 04, and 05
- Local runtime: The full upstream repo is registered as
external/sre-agent; the lab commands useexternal/sre-agent/labs/starter-lab. - Why it is a submodule: The official Microsoft lab stays tied to a specific upstream commit without vendoring the full repository into this curriculum repo.
When: Module content and support assets are included directly in this repository.
- No participant action required — content is already in this repo.
- Organisers run
npm run verify:reposto confirm vendored paths are intact.
When: A large external app or lab repo is needed at runtime but should not bloat the repo.
- Flow:
npm run setup:juice-shop npm run setup:sre-agent-lab
- Outcome: The submodule is fetched at the pinned SHA. Juice Shop also creates the
appsymlink; the SRE Agent lab helper prints thelabs/starter-labpath.
When: A activity setup script creates a GitHub repository with external content imported.
- Example: GHEC/GHAS activities — setup scripts import Juice Shop at
v20.0.0into a new org repo (e.g.,ghec-ch11-juice-shoporghec-ghas-00-juice-shop). - Flow:
# Creates <org>/ghec-ch11-juice-shop with Juice Shop imported cd modules/ghec/resources/provisioning/scripts ./setup.sh provision ghas-00 --org <org>
- Outcome: New repo exists in the delivery team member's/team's/organizer's org; for GHAS S00 the script also seeds CodeQL/Dependabot config and attempts to enable GHAS features. Repo admins manually add any participants who need access.
- Not a submodule: These repos are disposable activity targets that participants clone and push to, and that GitHub Advanced Security scans. They intentionally remain normal GitHub repositories.
Organisers and curriculum maintainers run:
npm run verify:repos # Validates challenge metadata against external-repos.json + vendored paths
npm run verify:repos:external # Confirms Juice Shop ref is reachable; skips retired entries
npm run audit:external # Optional content URL auditverify:repos:external checks only active external dependencies that participants or maintainers may need to fetch.
If a new version of Juice Shop or another active dependency is needed:
- Coordinate with curriculum: Update
external-repos.jsonwith the new ref (tag and/or full SHA). - Bump the submodule pointer (for submodule-backed apps):
cd external/<name> && git fetch --depth 1 origin <new-sha> && git checkout <new-sha>, thengit add external/<name>in the repo root. - Test: Run
npm run verify:reposandnpm run verify:repos:externalto confirm the manifest SHA and gitlink are in sync. - Document: Add a note to the activity's
COACH.mdif the new ref introduces breaking changes. - Rebuild: Run
npm run buildto regenerate catalogs with the new refs.
Tag vs. SHA nuance:
external-repos.jsonstores both the friendly tag (v20.0.0) and the exact commit SHA. Git submodules track the SHA only — the tag is purely for human reference. The drift check (npm run verify:repos) asserts the gitlink SHA equalssource.sha; always update both together.
Locally-run apps and labs (things participants start in their Codespace or dev container) are managed as lazy git submodules. Each submodule is registered (.gitmodules + gitlink) in this repo at the pinned commit, but the actual clone is deferred to when a participant first needs it. This keeps container creation fast for participants who don't use that module.
external/
juice-shop/ ← git submodule, pinned to f356a09... (v20.0.0)
sre-agent/ ← git submodule, pinned to 673f887... (starter lab source)
app -> external/juice-shop ← committed symlink, stable path for challenge instructions
external-repos.json carries a provisioning block for each submodule-backed app:
"provisioning": {
"method": "submodule",
"submodule_path": "external/juice-shop",
"symlinks": ["app"],
"npm_script": "setup:juice-shop"
}GHAS participants run this once after the container starts:
npm run setup:juice-shopThe script (scripts/provision-app.sh):
- Runs
git submodule update --init --depth 1 -- external/juice-shop(shallow, fast) - Verifies the checked-out HEAD SHA equals the manifest
source.sha(fails loudly on drift) - Ensures the
app → external/juice-shopsymlink exists - Prints next steps:
cd app && npm install && npm start
This submodule is the LOCAL RUNTIME only. It does NOT replace the org-imported repository that carries the GHAS alerts (CodeQL, Dependabot, secret scanning). Those run on the shared org repo your organizer provisions. Never confuse the two.
SRE Agent participants run this once before the live Azure lab commands:
npm run setup:sre-agent-labThe npm script uses the same manifest-driven provisioner as Juice Shop:
- Runs
bash scripts/provision-app.sh grubify-starter-lab - Fetches
external/sre-agentas a pinned lazy submodule - Verifies the checked-out HEAD SHA equals the manifest
source.sha - Verifies the manifest
provisioning.content_pathexists
Then enter the lab:
npm run setup:sre-agent-lab
cd external/sre-agent/labs/starter-labFor automation that needs to capture the lab path, modules/sre-agent/resources/scripts/ensure-starter-lab.sh is a thin wrapper around the same provisioner and prints the absolute lab directory.
For a fresh clone, participants can choose either lazy or eager submodule fetching:
# Lazy: fastest initial clone; fetch each lab/app only when needed.
git clone https://github.com/microsoft/frontier-agentic-devops-rvas.git
cd frontier-agentic-devops-rvas
npm run setup:juice-shop # when GHAS local runtime is needed
npm run setup:sre-agent-lab # when SRE Agent starter lab is needed
# Eager: fetch all registered submodules during clone.
git clone --recurse-submodules https://github.com/microsoft/frontier-agentic-devops-rvas.gitFor an existing clone after pulling curriculum updates:
git pull --recurse-submodules
git submodule update --init --recursive --depth 1npm run verify:repos asserts that, for every provisioning.method == "submodule" entry:
.gitmodulescontains a URL for the declaredsubmodule_path- The
.gitmodulesURL matchesexternal-repos.json - The gitlink SHA in the index matches
source.sha - If the submodule is checked out, the HEAD SHA also matches
In-tree course content is validated by npm run build and the content audit scripts.
- Add the submodule:
git submodule add --depth 1 <url> external/<name>then check out the pinned SHA. - Set
shallow = truein.gitmodules. - Create the committed symlink(s) if activity instructions expect a stable path.
- Add a
provisioningblock inexternal-repos.json(same schema asjuice-shop). - Add an npm script
setup:<name>inpackage.jsonpointing toprovision-app.sh <key>. - Run
npm run verify:reposto confirm drift check passes. - Document in this file and in the relevant activity's
README.md.
- Juice Shop (OWASP app) — pinned at
v20.0.0 - GHAS source material — vendored in-tree at
modules/ghas/resources/; provenance commit4abc7439f0cab329b659263845e20139fbbe5359 - Local Docker image —
bkimminich/juice-shop(used as fallback for quick local runs)
- GHAW source material — vendored in-tree at
modules/ghaw/; provenance commit9f0957ed3be978b2143c7048f5396183ad189d6e - No app — activities focus on workflow authoring, not a deployed service
- Azure SRE Agent starter lab — pinned lazy submodule at
external/sre-agent, lab pathlabs/starter-lab - Azure (runtime target) — customer delivery team members provision their own (not pinned, varies by subscription)
- Juice Shop (for ch11–ch15) — pinned at
v20.0.0 - GHEC provisioning machinery — vendored in-tree at
modules/ghec/resources/provisioning/ - Varies — some activities use no external app (auth, team roles, org governance)
-
Local Juice Shop (Docker or devcontainer)
- Used for manual exploit testing in activities
- Started with
cd app && npm startordocker run bkimminich/juice-shop - Runs on port 3000
- No GHAS alerts here — it's just the app
-
Shared org repository (GitHub repo in the organization)
- CodeQL, Dependabot, secret scanning run here
- Customer delivery team members clone or work on branches
- Alerts, security features, and all GHAS configuration are org/repo-scoped
- "GHAS" refers to the alerts and features on this shared repo, not the local Juice Shop runtime
- Runs locally in the delivery team member environment (or Codespaces)
- No external deploy needed — included at
modules/sre-agent/resources/sample-app/ - Used for incident simulation and agent response testing
- Keep pinned refs stable across a curriculum release cycle.
- Keep
external-repos.jsonlimited to active external repositories used by the course. - When external projects release major versions, evaluate and document breaking changes before updating the pin.
- Test setup scripts (
setup.sh provision) against the pinned refs in a CI/CD gate or manual verification step.
- Follow setup instructions in each activity's
README.mdorCOACH.md. - All module content is in-tree; you do not need to clone or fork the retired upstream repos.
- If setup fails to pull Juice Shop, check your GitHub token scopes and network access.
- Report setup failures via your delivery session organizer so coaches can investigate.
- Validate that Juice Shop ref is reachable before running a cohort (run
npm run verify:repos:external). - Retired Microsoft repos do not need to be reachable; the verify script skips them automatically.
- Keep customer delivery team members informed if external services (GitHub, Docker Hub) have outages.
- README.md — Build, validate, and deploy the curriculum.
- CONTRIBUTING.md — Authoring activities and meta.yml field reference.
- modules/README.md — Activity directory structure.