A reference repository demonstrating advanced GitHub Copilot capabilities — cloud architecture foundations, data and messaging patterns, architecture decision-making, agentic workflows with subagent handoffs, and live MCP integrations.
The deployed application is a mock camping-supplies storefront called Basecamp Outfitters. It gives the lab audience a real, working application to associate with every infrastructure and architecture decision being demonstrated.
Demo flow: Browse the catalog → open a product → add to cart → checkout with a mock email → receive an order confirmation with your order ID.
What's happening under the hood:
GET /api/products— product catalog served from Azure Cache for Redis (cache-aside pattern, Resilience4j circuit breaker)POST /api/orders— order persisted to PostgreSQL in a single transaction (server-side price resolution, integer cents)- Schema managed by Flyway (
V1__init.sql→V2__storefront.sql); migrations apply automatically on container start - Cart state lives in
localStorage— Container Apps can scale to zero without losing user context
ADRs that document this domain:
0003-mock-camping-storefront-domain.md— why a storefront, scope, what's out-of-scope0004-storefront-implementation.md— JPA + Flyway, Redis catalog cache, localStorage cart, integer-cents pricing, Resilience4j
This repo is structured as 8 progressive labs, each introducing new Copilot primitives that build on the last:
| Lab | Topic | Key Primitives |
|---|---|---|
| 1 | Orientation | Custom Instructions, MCP config |
| 2 | Cloud Architecture Foundations | Copilot for IaC, @workspace |
| 3 | Data & Messaging Architecture | Cross-language scaffolding, schema generation |
| 4 | Decision-Making with Rubber Duck | First agent.md, MS Learn in agent |
| 5 | Architecture Reviewer Agent | Multi-tool agent, safe-output patterns |
| 6 | Subagent Handoff Chains | Agent chaining (review → document → ADR) |
| 7 | Live MCP: Cost + Onboarding | Azure pricing API, GitHub MCP in agents |
| 8 | Full Pipeline: OIDC + Deploy | PR deploys, workflow_dispatch, federated identity, environment-scoped deploys |
- IaC: Terraform (modular, trunk-based, environment-parameterized via
.tfvars) - Backend: Java 21 + Spring Boot 3.x
- Frontend: React 18 + TypeScript (Vite)
- Cloud: Azure (Container Apps, PostgreSQL, Service Bus, Event Hubs, Redis, Blob Storage, Key Vault)
- Auth: OIDC via Azure Service Principals — no long-lived secrets
- CI/CD: GitHub Actions with OIDC and environment-scoped workflows
Three environments differentiated by .tfvars parameter files:
infra/environments/dev.tfvars -> rg-ghcp-demo-dev
infra/environments/uat.tfvars -> rg-ghcp-demo-uat
infra/environments/prd.tfvars -> rg-ghcp-demo-prd
Same codebase. Same Terraform modules. Environment behavior is 100% parameter-driven. The current Azure region for all environments is centralus, selected because PostgreSQL Flexible Server provisioning is restricted for this subscription in eastus2.
The Terraform stack deploys the same topology per environment, with SKU and retention differences controlled by infra/environments/*.tfvars.
flowchart TB
gh[GitHub Actions] -->|OIDC federated credential| sp[Environment Service Principal]
sp -->|Terraform apply| envRg
sp -->|Remote state via Entra auth| state[(Terraform State Storage)]
subgraph envRg[rg-ghcp-demo-env]
law[Log Analytics Workspace]
appi[Application Insights]
kv[Key Vault]
acr[Azure Container Registry]
st[Blob Storage Account]
vnet[Virtual Network]
appSubnet[App Subnet]
dataSubnet[Data Subnet<br/>PostgreSQL delegated]
pdns[Private DNS Zone<br/>privatelink.postgres.database.azure.com]
cae[Container Apps Environment]
id[User-assigned Managed Identity]
backend[Backend Container App]
frontend[Frontend Container App]
pg[(PostgreSQL Flexible Server)]
redis[(Azure Cache for Redis)]
sb[Service Bus Namespace<br/>work-items queues]
eh[Event Hubs Namespace<br/>domain-events hub]
alerts[Azure Monitor Metric Alerts]
end
vnet --> appSubnet
vnet --> dataSubnet
vnet --> pdns
pdns --> pg
dataSubnet --> pg
appSubnet --> cae
cae --> backend
cae --> frontend
id --> backend
backend --> kv
backend --> pg
backend --> redis
backend --> sb
backend --> eh
frontend --> backend
appi --> law
alerts --> appi
acr -->|private app images| cae
st -. app object storage .-> backend
All agents are Markdown files under .github/agents/, invokable from VS Code Copilot Chat:
| Agent | Invocation | Purpose |
|---|---|---|
| Rubber Duck | @rubber-duck |
Architecture ideation — asks questions, never gives answers |
| Architecture Reviewer | @architecture-reviewer |
Reviews IaC against standards, flags deviations |
| ADR Generator | @adr-generator |
Generates MADR-formatted Architecture Decision Records |
| Security Scanner | @security-scanner |
Scans IaC and code for security anti-patterns |
| Cost Estimator | @cost-estimator |
Side-by-side cost estimates for dev/uat/prd |
| Onboarding Guide | @onboarding-guide |
Generates contributor onboarding guide from repo context |
| Orchestrator | @orchestrator |
Routes repo requests to specialist agents and coordinates handoff chains |
- VS Code with GitHub Copilot extension
- Terraform >= 1.7
- Java 21 + Maven
- Node.js 20+
- Azure CLI (
az) - GitHub CLI (
gh)
- Fork this repository
- Create three Azure Service Principals for OIDC (see
docs/architecture/adrs/0002-oidc-azure-auth.md):sp-demo-dev— scoped to the dev resource groupsp-demo-uat— scoped to the uat resource groupsp-demo-prd— scoped to the prd resource group
- Configure each SP with a federated credential for GitHub Actions OIDC (no secrets required)
- Bootstrap Terraform state storage:
- Resource group:
rg-ghcp-demo-tfstate - Storage account:
stghcpdemotfstate - Blob container:
tfstate
- Resource group:
- Set the following GitHub Actions variables (IDs are stored as variables only, not in this README):
- Repo-level:
AZURE_TENANT_ID,TF_STATE_RESOURCE_GROUP,TF_STATE_STORAGE_ACCOUNT - Per environment (
dev/uat/prd):AZURE_CLIENT_ID,AZURE_SUBSCRIPTION_ID,DEPLOYER_OBJECT_ID,POSTGRES_PASSWORD_SECRET_ID
- Repo-level:
- Open in VS Code — Copilot will pick up
.github/copilot-instructions.mdautomatically
Deployments are triggered via GitHub Actions with OIDC; no client secrets are stored in GitHub.
| Environment | Workflow | Trigger |
|---|---|---|
| image build | Build Container Images |
Pull request targeting main; manual dispatch for a selected environment registry |
dev |
Deploy — Dev |
Pull request targeting main |
uat |
Deploy — UAT |
Manual workflow_dispatch |
prd |
Deploy — PRD |
Manual workflow_dispatch |
The image build workflow publishes demo-api and demo-ui images to the environment ACR using the commit SHA and <env>-latest tags. Dev deployment waits for the PR image tags before applying Terraform. UAT and PRD deployments accept an optional image_tag input and default to uat-latest / prd-latest.
For private image pulls, the environment service principal needs AcrPush on its ACR, and the Container Apps user-assigned managed identity needs AcrPull on the same registry.
docs/demo-guide.md— Facilitator guide and lab scriptsdocs/architecture/adrs/— Architecture Decision Recordsdocs/architecture/diagrams/— Mermaid architecture diagrams