From 7a8d037b4fc2b10e06f9975fbac7961734472bff Mon Sep 17 00:00:00 2001 From: Justin Yoo Date: Mon, 24 Aug 2026 23:06:32 +0900 Subject: [PATCH] docs: add sandbox demo guides Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: dcedf6b4-0ae1-4914-ba14-77e4bac4c4a9 --- .gitignore | 2 + README.md | 11 ++ docs/README.md | 56 ++++++ docs/demo-1-runbook.md | 227 +++++++++++++++++++++++ docs/demo-1-setup.md | 151 ++++++++++++++++ docs/demo-1-validation-and-recovery.md | 184 +++++++++++++++++++ docs/demo-2-runbook.md | 239 +++++++++++++++++++++++++ docs/demo-2-setup.md | 188 +++++++++++++++++++ docs/demo-2-validation-and-recovery.md | 179 ++++++++++++++++++ 9 files changed, 1237 insertions(+) create mode 100644 docs/README.md create mode 100644 docs/demo-1-runbook.md create mode 100644 docs/demo-1-setup.md create mode 100644 docs/demo-1-validation-and-recovery.md create mode 100644 docs/demo-2-runbook.md create mode 100644 docs/demo-2-setup.md create mode 100644 docs/demo-2-validation-and-recovery.md diff --git a/.gitignore b/.gitignore index ac0eadb..ccec682 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,8 @@ # Presentation source and referenced assets. !ai-agent-sandboxing.md !assets/** +!docs/ +!docs/** # Generated GitHub Pages entrypoint. index.html diff --git a/README.md b/README.md index a30efef..ed2a383 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,22 @@ The primary presentation was prepared for various conferences and meetups, and c ├── .github/ ├── assets/ ├── ai-agent-sandboxing.md # Marp presentation source +├── docs/ # Demo setup, runbooks, and recovery guides ├── index.html # Generated presentation (ignored) ├── LICENSE └── README.md ``` +## Demo guides + +The [demo documentation index](docs/README.md) provides two complete, +sequential walkthroughs: + +| Demo | Setup | Runbook | Validation and recovery | +| --- | --- | --- | --- | +| 1. Java modernization in a Docker Sandbox | [Setup](docs/demo-1-setup.md) | [Runbook](docs/demo-1-runbook.md) | [Validation](docs/demo-1-validation-and-recovery.md) | +| 2. Copilot CLI in an ACA Sandbox | [Setup](docs/demo-2-setup.md) | [Runbook](docs/demo-2-runbook.md) | [Validation](docs/demo-2-validation-and-recovery.md) | + ## Preview the presentation 1. Install Node.js 22 or later, then generate an HTML presentation: diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..ca914ba --- /dev/null +++ b/docs/README.md @@ -0,0 +1,56 @@ +# AI agent sandboxing demo guides + +These documents support the live demos in +[`ai-agent-sandboxing.md`](../ai-agent-sandboxing.md). + +## Demo 1: Java modernization in a Docker Sandbox + +1. [Environment setup](demo-1-setup.md) - install `sbx`, prepare credentials, + clone the sample, and establish a clean baseline. +2. [Live demo runbook](demo-1-runbook.md) - create the clone-mode sandbox, + modernize the Java application, and show the isolation evidence. +3. [Validation and recovery](demo-1-validation-and-recovery.md) - inspect, + preserve, troubleshoot, and clean up the result. + +## Demo 2: Copilot CLI in an ACA Sandbox + +1. [Environment setup](demo-2-setup.md) - install `aca`, prepare Azure RBAC and + credentials, and verify the Copilot disk image. +2. [Live demo runbook](demo-2-runbook.md) - create the managed sandbox, + generate a UI design plan, and prove that state survives stop and resume. +3. [Validation and recovery](demo-2-validation-and-recovery.md) - export + evidence, snapshot state, troubleshoot failures, and clean up Azure + resources. + +## Demo 1 outcome + +The demo should make four points visible: + +- Copilot CLI runs inside an isolated microVM. +- The modernization agent assesses, plans, and executes the Java upgrade. +- The agent uses a private Git clone and cannot write to the host repository. +- The sandbox has its own Docker daemon and policy-controlled network access. + +The sample application is +[`UW-Madison-DoIT/uportal-messaging`](https://github.com/UW-Madison-DoIT/uportal-messaging). +Its current baseline makes the change easy to explain: Java 8, Spring Boot +1.5.9.RELEASE, Maven, WAR packaging, and an OpenJDK 8 Travis CI build. + +## Demo 2 outcome + +Demo 2 runs Copilot CLI in an Azure Container Apps Sandbox, asks it to create a +design-only plan for +[`devkimchi/battle-school-lunch`](https://github.com/devkimchi/battle-school-lunch), +stops the remote sandbox, and resumes the same sandbox with its filesystem +state intact. + +## References + +- [Get started with Docker Sandboxes](https://docs.docker.com/ai/sandboxes/get-started/) +- [Run GitHub Copilot in a Docker Sandbox](https://docs.docker.com/ai/sandboxes/agents/copilot/) +- [Docker Sandbox installation](https://docs.docker.com/ai/sandboxes/install/) +- [Docker Sandbox isolation](https://docs.docker.com/ai/sandboxes/security/isolation/) +- [Modernize Java apps with GitHub Copilot modernization](https://learn.microsoft.com/azure/developer/java/migration/github-copilot-app-modernization-for-java-copilot-cli) + +Commands and prerequisites were checked against the linked documentation on +August 24, 2026. diff --git a/docs/demo-1-runbook.md b/docs/demo-1-runbook.md new file mode 100644 index 0000000..86ef6f6 --- /dev/null +++ b/docs/demo-1-runbook.md @@ -0,0 +1,227 @@ +# Demo 1: Java modernization in a Docker Sandbox + +This runbook follows the Demo 1 sequence in +[`ai-agent-sandboxing.md`](../ai-agent-sandboxing.md). Use two terminals: +Terminal A for Copilot CLI and Terminal B for inspection. + +> [!IMPORTANT] +> Run this demo in clone mode. Direct mode protects the host operating system, +> but it gives the agent read-write access to the host working tree. + +## What the demo proves + +- Copilot CLI runs inside an isolated microVM. +- The modernization agent assesses, plans, and executes the Java upgrade. +- The agent works in a private clone and cannot write to the host repository. +- The sandbox has its own Docker daemon and policy-controlled network access. + +## Before you begin + +Complete the [Demo 1 environment setup](demo-1-setup.md). Confirm that: + +- `sbx`, GitHub CLI, and Git are available. +- Docker and GitHub authentication succeed. +- The **Balanced** network policy is active. +- `uportal-messaging` is clean and checked out on `demo/baseline`. +- No stale `java-modernize` sandbox contains unpreserved work. + +## 1. Start Copilot in a private clone + +From the host checkout of `uportal-messaging`, run in Terminal A: + +```powershell +sbx secret set github --command 'gh auth token' +sbx run --clone --name java-modernize copilot . +``` + +On first use, choose the **Balanced** network preset when prompted. + +`--clone` is the important boundary: + +- `/run/sandbox/source` is a read-only mount of the host repository. +- Copilot works in a separate read-write clone inside the microVM. +- `sbx` adds a `sandbox-java-modernize` Git remote to the host repository. +- Nothing reaches the host working tree until an explicit fetch, checkout, or + push. + +Copilot's Docker Sandbox template starts with its approval-skipping mode. This +does not remove the microVM, workspace, credential, Docker daemon, or network +boundaries. + +## 2. Prepare the modernization agent + +### Install the plugin + +In the Copilot CLI session, enter: + +```text +/plugin marketplace add microsoft/github-copilot-modernization +/plugin install github-copilot-modernization@github-copilot-modernization +/plugin list +``` + +Confirm that the list contains: + +```text +github-copilot-modernization@github-copilot-modernization +``` + +The equivalent non-interactive shell commands are: + +```bash +copilot plugin marketplace add microsoft/github-copilot-modernization +copilot plugin install github-copilot-modernization@github-copilot-modernization +``` + +### Select the orchestrator + +Enter `/agent`, then select: + +```text +github-copilot-modernization:modernize +``` + +Do not run the upgrade with the default Copilot agent. The `modernize` agent +provides the assessment, planning, specialized executors, retries, and +per-task commits used in this demo. + +## 3. Run the modernization + +Use this prompt: + +```text +Before making changes, create and switch to a branch named demo/modernized. +Upgrade this application to Java 21 and Spring Boot 4.1. Assess the current +application, create a reviewable plan, execute the plan, update tests and build +configuration, run the relevant Maven verification, check dependencies for +known vulnerabilities, and commit each completed task separately. Do not push +the branch or open a pull request. +``` + +The expected workflow is: + +1. **Assessment** - discovers Java version, framework, dependencies, and risks; + writes `.github/modernize/assessment/`. +2. **Planning** - writes `.github/modernize//plan.md` and `tasks.json`. +3. **Execution** - delegates tasks, updates the application, verifies the + build, and creates detailed task commits. + +A specific upgrade prompt can go directly to planning and execution. Asking +for assessment explicitly keeps all three phases visible for the demo. + +## 4. Inspect the sandbox while the agent works + +In Terminal B: + +```powershell +sbx ls +sbx policy ls +sbx exec -it java-modernize bash +``` + +Inside the sandbox shell: + +```bash +pwd +node --version +git branch --show-current +git status --short +docker info +find .github/modernize -maxdepth 3 -type f -print 2>/dev/null +``` + +Show that the host source mount is read-only: + +```bash +touch /run/sandbox/source/__sandbox-write-test +``` + +The command should fail with a read-only filesystem error. Do not use a path +inside the private clone for this test; the private clone is intentionally +writable. + +Show the isolated Docker daemon without changing the host: + +```bash +docker run --rm hello-world +docker ps -a +``` + +The container and image exist only in the sandbox's Docker Engine. Docker +Sandboxes do not mount the host Docker socket. + +Exit the inspection shell: + +```bash +exit +``` + +Run `sbx` with no arguments on the host to open the dashboard. Switch to its +network panel to show allowed and denied outbound connections and the rules +that made each decision. + +## 5. Prove that the host stayed clean + +While the agent's commits remain in the private clone, run from the host +checkout: + +```powershell +git status --short +git branch --show-current +git remote --verbose +``` + +Expected result: + +- `git status --short` prints nothing. +- The host remains on `demo/baseline`. +- A `sandbox-java-modernize` remote is present. + +## 6. Verify the result + +After the modernization agent finishes, use the inspection shell or ask the +agent to report: + +```bash +git branch --show-current +git status --short +git --no-pager log --oneline --decorate -15 +find .github/modernize -maxdepth 3 -type f -print +``` + +Confirm that the branch is `demo/modernized`, the expected assessment and plan +artifacts exist, verification results are reported, and task commits are +present. + +## 7. Preserve evidence and clean up + +Continue with +[Demo 1 validation and recovery](demo-1-validation-and-recovery.md) to: + +1. Fetch `sandbox-java-modernize/demo/modernized`. +2. Review application, build, CI, and modernization artifacts. +3. Materialize only the reviewed branch on the host. +4. Stop and remove the sandbox after its work is preserved. + +## Troubleshooting + +Use the +[Demo 1 troubleshooting guide](demo-1-validation-and-recovery.md#troubleshooting) +for plugin installation, Java discovery, network policy, Maven, sandbox mode, +and fetch failures. + +## References + +- [Get started with Docker Sandboxes](https://docs.docker.com/ai/sandboxes/get-started/) +- [Run GitHub Copilot in a Docker Sandbox](https://docs.docker.com/ai/sandboxes/agents/copilot/) +- [Docker Sandbox isolation](https://docs.docker.com/ai/sandboxes/security/isolation/) +- [Use Git with Docker Sandboxes](https://docs.docker.com/ai/sandboxes/workflows/git/) +- [Modernize Java apps with GitHub Copilot modernization](https://learn.microsoft.com/azure/developer/java/migration/github-copilot-app-modernization-for-java-copilot-cli) + +Commands and behavior were checked against the linked documentation on +August 24, 2026. + +## Navigation + +[Previous: Demo 1 environment setup](demo-1-setup.md) | +[Next: Demo 1 validation and recovery](demo-1-validation-and-recovery.md) diff --git a/docs/demo-1-setup.md b/docs/demo-1-setup.md new file mode 100644 index 0000000..c16852a --- /dev/null +++ b/docs/demo-1-setup.md @@ -0,0 +1,151 @@ +# Demo 1 environment setup + +Complete this setup before presenting the live runbook. + +## 1. Check the host + +Docker Sandboxes do not require Docker Desktop or Docker Engine on the host. +The supported host requirements are: + +| Platform | Requirement | +| --- | --- | +| Windows | Windows 11, 64-bit Intel or AMD CPU, Windows Hypervisor Platform | +| macOS | macOS Sonoma 14 or later on Apple silicon | +| Linux | Ubuntu 24.04 or later with KVM enabled | + +On Windows, enable Windows Hypervisor Platform from an elevated PowerShell +session, then restart if Windows requests it: + +```powershell +Enable-WindowsOptionalFeature -Online -FeatureName HypervisorPlatform -All +``` + +The Java modernization plugin requires a GitHub Copilot subscription. If the +subscription is organization-managed, the organization must enable its +Copilot CLI policy. An Azure account is not required for a source upgrade. + +The Copilot sandbox template supplies Copilot CLI and its runtime. The +modernization plugin's documented standalone prerequisite is Node.js 22 or +later; verify the template before the demo: + +```powershell +sbx --version +gh auth status +``` + +## 2. Install and sign in to `sbx` + +### Windows + +```powershell +winget install -h Docker.sbx +sbx login +``` + +### macOS + +```bash +brew trust docker/tap +brew install docker/tap/sbx +sbx login +``` + +### Ubuntu + +Install `sbx` without adding Docker Engine to the host: + +```bash +curl -fsSL https://get.docker.com | sudo REPO_ONLY=1 sh +sudo apt install docker-sbx +sbx login +``` + +## 3. Store the GitHub credential + +Authenticate GitHub CLI on the host first. Store the resulting token through +the sandbox secret mechanism rather than copying it into the microVM: + +```powershell +gh auth login +sbx secret set github --command 'gh auth token' +``` + +The host-side proxy injects supported credentials into outbound requests. The +token is not exposed to the agent as a file or environment variable. + +## 4. Initialize a network policy + +Use the **Balanced** preset for the demo. It is default-deny with a baseline +allowlist for common AI providers, code hosts, package registries, and +development services. + +```powershell +sbx policy init balanced +sbx policy ls +``` + +If a preset already exists, do not reset it during the demo. The +`sbx policy reset` command stops running sandboxes. + +Do not switch to the Open preset to resolve a single blocked dependency. Add a +narrow rule only after confirming the denied host in the dashboard: + +```powershell +sbx policy allow network --sandbox java-modernize artifacts.doit.wisc.edu +sbx policy allow network --sandbox java-modernize artifactorydoit.jfrog.io +``` + +The sample `pom.xml` declares both hosts. A build might not contact them if all +required artifacts resolve from Maven Central. + +## 5. Prepare the sample repository + +Use the main checkout, not a linked Git worktree: clone mode does not support a +secondary worktree as its primary workspace. + +```powershell +git clone https://github.com/UW-Madison-DoIT/uportal-messaging.git +Set-Location uportal-messaging +git switch -c demo/baseline +git status --short +``` + +The final command should produce no output. Clone mode follows the host's +checked-out ref when the sandbox is created, but it does not create a task +branch automatically. + +Record the baseline for the audience: + +```powershell +git --no-pager grep -n '\|spring-boot-starter-parent' +git --no-pager log -1 --oneline +``` + +The repository's `pom.xml` declares Java 8 and Spring Boot 1.5.9.RELEASE. The +live target from Demo 1 is Java 21 and Spring Boot 4.1. + +## 6. Preflight + +Run these checks before presenting: + +```powershell +sbx ls +sbx policy check network github.com +sbx policy check network repo.maven.apache.org +``` + +If a stale `java-modernize` sandbox exists, preserve any work before removing +it: + +```powershell +git fetch sandbox-java-modernize +sbx stop java-modernize +sbx rm java-modernize +``` + +Do not remove a clone-mode sandbox until its commits have been fetched or +pushed. Removing it deletes the private clone. + +## Navigation + +Next: [Demo 1 live runbook](demo-1-runbook.md) diff --git a/docs/demo-1-validation-and-recovery.md b/docs/demo-1-validation-and-recovery.md new file mode 100644 index 0000000..6893cbf --- /dev/null +++ b/docs/demo-1-validation-and-recovery.md @@ -0,0 +1,184 @@ +# Demo 1 validation and recovery + +Use this guide after the agent finishes, or when the live path needs recovery. + +## Preserve and review the private branch + +Keep the sandbox running while fetching because its Git daemon is available +only while the sandbox runs. + +From the host `uportal-messaging` checkout: + +```powershell +git fetch sandbox-java-modernize +git --no-pager log --oneline --decorate sandbox-java-modernize/demo/modernized +git --no-pager diff --stat demo/baseline..sandbox-java-modernize/demo/modernized +git --no-pager diff demo/baseline..sandbox-java-modernize/demo/modernized +``` + +Review executable and trust-sensitive changes in addition to application code: + +```powershell +git --no-pager diff --name-status demo/baseline..sandbox-java-modernize/demo/modernized +git --no-pager diff demo/baseline..sandbox-java-modernize/demo/modernized -- pom.xml .github +``` + +Pay particular attention to: + +- Maven plugins, repositories, and dependency versions in `pom.xml`. +- CI definitions and automation under `.github/`. +- `.github/modernize/assessment/`, `plan.md`, and `tasks.json`. +- Newly added scripts, Dockerfiles, agent configuration, and Git hooks. +- Build and vulnerability-scan output reported by the agent. + +Clone mode prevents writes to the host, but the source mount is readable. Do +not keep `.env`, tokens, private keys, or other secrets inside the repository, +even when they are ignored by Git. + +## Materialize the reviewed branch + +After reviewing the remote-tracking branch: + +```powershell +git switch -c demo/modernized --track sandbox-java-modernize/demo/modernized +git status +``` + +Run host-side build or test commands only after reviewing the changes as +untrusted code. The demo can stop at the diff if executing fetched code on the +host is outside the presentation's safety boundary. + +## Validation checklist + +| Evidence | Expected result | +| --- | --- | +| `git status --short` on the host before fetch | No output | +| Write under `/run/sandbox/source` | Fails as read-only | +| `docker info` in the sandbox | Reports the sandbox's Docker Engine | +| `sbx policy ls` and dashboard | Balanced policy and connection decisions visible | +| Modernization artifacts | Assessment, `plan.md`, and `tasks.json` present | +| Git history | Separate modernization task commits | +| Maven verification | Result reported; failures have a specific cause and next action | +| Vulnerability check | Result or explicit tool limitation reported | + +## Troubleshooting + +### The plugin is missing + +From a sandbox shell: + +```bash +copilot plugin marketplace list +copilot plugin marketplace add microsoft/github-copilot-modernization +copilot plugin install github-copilot-modernization@github-copilot-modernization +``` + +Back in Copilot CLI, run `/plugin list`, then select +`github-copilot-modernization:modernize` again with `/agent`. + +### No Java application is found + +Confirm that Copilot started in the private clone root: + +```bash +pwd +test -f pom.xml && echo "pom.xml found" +git rev-parse --show-toplevel +``` + +Start the modernization agent from the directory containing `pom.xml`. + +### A network request is denied + +Use the dashboard's network panel to identify the exact host, then check its +decision: + +```powershell +sbx policy check network --sandbox java-modernize example.com +``` + +If the host is required and approved, add only that host: + +```powershell +sbx policy allow network --sandbox java-modernize example.com +``` + +If organization governance is active, local allow rules cannot expand the +organization policy. Ask the organization administrator to allow the host. +Local deny rules still apply. + +For this sample, legacy Maven repositories that might require a scoped rule +include: + +```powershell +sbx policy check network --sandbox java-modernize artifacts.doit.wisc.edu +sbx policy check network --sandbox java-modernize artifactorydoit.jfrog.io +``` + +### The Maven build fails + +Do not present a failed build as a completed modernization. Capture: + +```bash +java -version +mvn -version +mvn -U verify +``` + +Classify the failure before retrying: + +- A denied hostname requires a reviewed policy rule. +- A missing legacy artifact might require replacing or removing the obsolete + repository or dependency as part of the modernization plan. +- Compilation errors require another modernization task and commit. +- Test failures require either a fix or an explicit, documented blocker. + +### The sandbox reused the wrong mode or state + +Clone mode is fixed when the sandbox is created. Preserve useful commits, then +recreate it: + +```powershell +git fetch sandbox-java-modernize +sbx stop java-modernize +sbx rm java-modernize +sbx run --clone --name java-modernize copilot . +``` + +### Fetch fails + +The private clone's Git daemon is unavailable while the sandbox is stopped. +Restart it and fetch again: + +```powershell +sbx run --name java-modernize +git fetch sandbox-java-modernize +``` + +If the agent used a different branch name, inspect branches inside the sandbox: + +```powershell +sbx exec -it java-modernize bash +``` + +```bash +git branch --all +``` + +## Cleanup + +Fetch or push every branch you want to preserve before cleanup: + +```powershell +git fetch sandbox-java-modernize +sbx stop java-modernize +sbx rm java-modernize +``` + +Removing the sandbox deletes its microVM, private clone, installed tools, +Docker images and containers, and the `sandbox-java-modernize` host remote. It +does not modify the host working tree. + +## Navigation + +Previous: [Demo 1 live runbook](demo-1-runbook.md) diff --git a/docs/demo-2-runbook.md b/docs/demo-2-runbook.md new file mode 100644 index 0000000..2141105 --- /dev/null +++ b/docs/demo-2-runbook.md @@ -0,0 +1,239 @@ +# Demo 2: Copilot CLI in an ACA Sandbox + +This runbook follows the Demo 2 sequence in +[`ai-agent-sandboxing.md`](../ai-agent-sandboxing.md). It runs GitHub Copilot +CLI against +[`devkimchi/battle-school-lunch`](https://github.com/devkimchi/battle-school-lunch) +and proves that `design-update.md` survives a stop and resume cycle. + +> [!IMPORTANT] +> Use the same sandbox ID throughout the stop and resume sequence. +> `aca sandbox create` creates a different environment and does not prove state +> restoration. + +## What the demo proves + +- A sandbox group is the Azure resource, RBAC, image, and policy boundary. +- Each sandbox is a hardware-isolated microVM with its own filesystem and + lifecycle. +- Copilot CLI can work inside the remote sandbox without placing its token in + the repository. +- Stopping the sandbox suspends compute while retaining state according to its + suspend mode. +- Resuming the same sandbox restores the repository and generated design plan. + +## Before you begin + +Complete the [Demo 2 environment setup](demo-2-setup.md). Confirm that: + +- Azure CLI and the preview `aca` CLI are authenticated. +- `aca doctor` passes all group, region, and RBAC checks. +- The GitHub Copilot provider credential is configured. +- The `copilot` public disk is available. +- No stale `copilot-demo` sandbox contains unpreserved work. + +## 1. Create and harden the sandbox + +Create a labeled sandbox and capture its ID: + +```powershell +aca sandbox create ` + --disk copilot ` + --label name=copilot-demo + +$SandboxId = ( + aca sandbox list -l "name=copilot-demo" -o json | + ConvertFrom-Json +)[0].id + +$SandboxId +aca sandbox get --id $SandboxId -o json +``` + +The expected state is `Running`. + +For production agent workloads, use deny-by-default egress and add only +reviewed destinations. This baseline covers the public repository and common +Copilot endpoints: + +```powershell +aca sandbox egress set ` + --id $SandboxId ` + --default Deny ` + --rule "github.com:Allow" ` + --rule "api.github.com:Allow" ` + --rule "api.githubcopilot.com:Allow" ` + --rule "*.githubusercontent.com:Allow" ` + --traffic-inspection Full + +aca sandbox egress show --id $SandboxId +``` + +If the portal reports another denied Copilot or GitHub hostname, review it and +add that exact hostname rather than changing the default to Allow. + +Set an explicit memory suspend policy for the state-restoration demonstration: + +```powershell +aca sandbox lifecycle set ` + --id $SandboxId ` + --auto-suspend enable ` + --mode Memory ` + --idle-timeout-seconds 900 +``` + +## 2. Prepare Copilot in the interactive shell + +Open a real PTY using the label from the presentation: + +```powershell +aca sandbox shell -l "name=copilot-demo" +``` + +There is no SSH daemon in an ACA Sandbox. Use `aca sandbox shell` for an +interactive terminal or `aca sandbox exec` for a one-shot command. + +Inside the sandbox: + +```bash +git --version +copilot --version +git clone https://github.com/devkimchi/battle-school-lunch.git +cd battle-school-lunch +git status --short +copilot +``` + +The sample is a full-stack school lunch application with a React 19, Vite, +TypeScript, and Tailwind v4 web UI under `src/web`. + +## 3. Run the design-planning task + +Use the prompt from the presentation: + +```text +이 프로젝트의 Web UI를 Brutal Design 스타일로 변경하려고 해. 코드는 수정하지 +말고, 변경 계획을 design-update.md 파일로 작성해 줘 +``` + +An English equivalent is: + +```text +I want to restyle this project's web UI using Brutalist design. Do not modify +any source code. Inspect the existing UI and write a concrete implementation +plan to design-update.md at the repository root. +``` + +## 4. Inspect the sandbox result + +Exit Copilot after it finishes, then verify from the sandbox shell: + +```bash +test -f design-update.md +sed -n '1,160p' design-update.md +git status --short +``` + +Expected result: `design-update.md` exists and source files remain unchanged. +The only `git status --short` entry should be the untracked plan file. + +Record the working directory and checksum: + +```bash +pwd +sha256sum design-update.md +git diff --name-only +exit +``` + +`git diff --name-only` does not list untracked files, so use it together with +`git status --short`. + +## 5. Prove the stop and resume lifecycle + +Back in the host PowerShell session, capture the original identity and state: + +```powershell +$Before = aca sandbox get --id $SandboxId -o json | ConvertFrom-Json +$Before.id +$Before.state +``` + +Stop the sandbox: + +```powershell +aca sandbox stop --id $SandboxId +(aca sandbox get --id $SandboxId -o json | ConvertFrom-Json).state +``` + +Wait for `Stopped`. In this state, CPU and memory compute charges stop; stored +state and related resources can still incur charges. + +Resume the same sandbox: + +```powershell +aca sandbox resume --id $SandboxId +(aca sandbox get --id $SandboxId -o json | ConvertFrom-Json).state +``` + +Wait for `Running`, then reconnect: + +```powershell +aca sandbox shell --id $SandboxId +``` + +## 6. Verify the resumed state + +Inside the resumed sandbox: + +```bash +cd battle-school-lunch +pwd +test -f design-update.md +sha256sum design-update.md +sed -n '1,40p' design-update.md +git status --short +exit +``` + +Confirm that: + +- The sandbox ID before and after resume is identical. +- The repository is still present. +- `design-update.md` is present with the same checksum. +- No application source file was modified. + +Memory suspend mode also preserves running-process state. This demo validates +filesystem state because it is deterministic and visible to the audience. + +## 7. Preserve evidence and clean up + +Continue with +[Demo 2 validation and recovery](demo-2-validation-and-recovery.md) to: + +1. Export `design-update.md`. +2. Review the state and validation evidence. +3. Snapshot the sandbox if its remote state must be preserved. +4. Delete the sandbox and optional demo resource group. + +## Troubleshooting + +Use the +[Demo 2 troubleshooting guide](demo-2-validation-and-recovery.md#troubleshooting) +for RBAC, disk image, Copilot authentication, egress, lifecycle, and preview +CLI failures. + +## References + +- [Azure Container Apps Sandboxes overview](https://learn.microsoft.com/azure/container-apps/sandboxes-overview) +- [Sandboxes](https://sandboxes.azure.com/docs/sandboxes/sandboxes) +- [Interactive shell](https://sandboxes.azure.com/docs/sandboxes/sandbox/interactive-shell) +- [Sandbox lifecycle](https://sandboxes.azure.com/docs/sandboxes/sandbox/lifecycle) + +Commands and preview behavior were checked against the linked documentation on +August 24, 2026. + +## Navigation + +[Previous: Demo 2 environment setup](demo-2-setup.md) | +[Next: Demo 2 validation and recovery](demo-2-validation-and-recovery.md) diff --git a/docs/demo-2-setup.md b/docs/demo-2-setup.md new file mode 100644 index 0000000..ea43841 --- /dev/null +++ b/docs/demo-2-setup.md @@ -0,0 +1,188 @@ +# Demo 2 environment setup + +Complete this setup before presenting +[Demo 2](demo-2-runbook.md). The demo uses Azure Container Apps Sandboxes, +GitHub Copilot CLI, and +[`devkimchi/battle-school-lunch`](https://github.com/devkimchi/battle-school-lunch). + +> [!IMPORTANT] +> Azure Container Apps Sandboxes and the dedicated `aca` CLI are in public +> preview. Commands and resources created during preview can change or require +> recreation. Run `aca --help` against the installed version during +> rehearsal. + +## 1. Install the preview CLI + +The `aca` CLI is separate from both Azure CLI and `az containerapp`. It uses +the Azure CLI identity for authentication. + +### Windows PowerShell + +```powershell +irm https://aka.ms/aca-cli-install-ps | iex +aca --version +``` + +### Linux or macOS + +```bash +curl -fsSL https://aka.ms/aca-cli-install | sh +aca --version +``` + +The same install path can also be used inside sandboxes and containers for +agent-driven self-installs. + +Authenticate only when the current sessions are missing: + +```powershell +az account show -o none 2>$null +if ($LASTEXITCODE -ne 0) { + az login +} + +aca auth status +if ($LASTEXITCODE -ne 0) { + aca auth login +} +``` + +Select the intended subscription: + +```powershell +$SubscriptionId = az account show --query id -o tsv +az account set --subscription $SubscriptionId +``` + +Only Microsoft Entra ID accounts can access ACA Sandboxes. Personal Microsoft +accounts are not supported. + +## 2. Create the sandbox group + +Choose a supported region. Demo 2 uses Korea Central: + +```powershell +$ResourceGroup = "rg-ghcp-sandbox-demo" +$SandboxGroup = "ghcp-sandbox-demo" +$Location = "koreacentral" + +az group create ` + --name $ResourceGroup ` + --location $Location + +aca sandboxgroup create ` + --name $SandboxGroup ` + --location $Location ` + --set-config +``` + +`--set-config` stores the subscription, resource group, group, and region for +later `aca sandbox` commands. + +The caller needs permission to create the `Microsoft.App/SandboxGroups` +resource. Sandbox data-plane operations require **Container Apps SandboxGroup +Data Owner**. Group creation grants that role to the caller by default. Grant +it explicitly only to an additional presenter or automation principal: + +```powershell +$PrincipalId = az ad signed-in-user show --query id -o tsv + +aca sandboxgroup role create ` + --group $SandboxGroup ` + --role "Container Apps SandboxGroup Data Owner" ` + --principal-id $PrincipalId +``` + +Treat a clean `aca doctor` result as the gate for the rest of the demo: + +```powershell +aca doctor +aca config show +``` + +RBAC changes can take several minutes to propagate. Retry `aca doctor` before +changing the role assignment. + +## 3. Configure the Copilot provider credential + +Create a fine-grained GitHub personal access token with Copilot access. It must +start with `github_pat_`; classic `ghp_` tokens are not supported. + +1. Open [ACA Sandboxes](https://sandboxes.azure.com/sandbox-groups). +2. Open `ghcp-sandbox-demo`. +3. Open **Credentials** and select **Set Token** for **GitHub Copilot**. +4. Paste the fine-grained token and save it. +5. Confirm that its status is **Configured**. + +Provider credentials are stored as sandbox-group connections. The platform +injects authentication for the provider when a sandbox starts; the saved token +is not displayed again in the portal. Recreate or restart sandboxes after +rotating the token. + +The presentation slide includes this older preview command shape: + +```text +aca sandbox create --disk copilot --credential +``` + +The current preview credential documentation configures the credential at +group scope, and the current published CLI reference does not document +`--credential`. Use `aca sandbox create --help` during rehearsal. Add the +flag only if the installed CLI documents it and the portal supplies a +connection ID; never pass the raw PAT on the command line. + +## 4. Verify the Copilot disk image + +List the public disk names accepted by `--disk`: + +```powershell +aca sandboxgroup disk list-public +``` + +Confirm that `copilot` is present. Public images use `--disk `. Private +or committed images use `--disk-id `. + +If the public `copilot` image is unavailable in the selected region or CLI +release, stop the rehearsal and choose a supported region or a reviewed custom +disk image. Do not silently substitute `ubuntu`: Demo 2 expects Copilot CLI to +be preinstalled and authenticated. + +## 5. Preflight + +Confirm the environment immediately before presenting: + +```powershell +aca --version +aca auth status +aca doctor +aca config show +aca sandboxgroup disk list-public +aca sandbox list -l "name=copilot-demo" +``` + +The expected result is: + +- Azure and ACA authentication succeed. +- `aca doctor` reports a valid group and Data Owner role. +- The configured group is `ghcp-sandbox-demo`. +- The `copilot` public disk is available. +- No stale `copilot-demo` sandbox contains state that must be preserved. + +If a stale sandbox exists, follow +[Demo 2 validation and recovery](demo-2-validation-and-recovery.md) before +deleting it. + +## References + +- [Azure Container Apps Sandboxes overview](https://learn.microsoft.com/azure/container-apps/sandboxes-overview) +- [ACA CLI quickstart](https://sandboxes.azure.com/docs/sandboxes/quickstart/setup-cli) +- [Sandbox groups](https://sandboxes.azure.com/docs/sandboxes/sandbox-groups) +- [Provider credentials](https://sandboxes.azure.com/docs/sandboxes/credentials) +- [Disk images](https://sandboxes.azure.com/docs/sandboxes/disk-images) + +Commands and preview behavior were checked against the linked documentation on +August 24, 2026. + +## Navigation + +Next: [Demo 2 live runbook](demo-2-runbook.md) diff --git a/docs/demo-2-validation-and-recovery.md b/docs/demo-2-validation-and-recovery.md new file mode 100644 index 0000000..6f07ccd --- /dev/null +++ b/docs/demo-2-validation-and-recovery.md @@ -0,0 +1,179 @@ +# Demo 2 validation and recovery + +Use this guide after the Demo 2 run, or when the live path needs recovery. + +## Preserve the generated plan + +Confirm the repository path inside the sandbox: + +```powershell +aca sandbox exec ` + --id $SandboxId ` + -c "cd battle-school-lunch && pwd && sha256sum design-update.md" +``` + +Export the generated plan with the data-plane file API rather than `scp`: + +```powershell +aca sandbox fs cat ` + --id $SandboxId ` + --path /home/coder/battle-school-lunch/design-update.md | + Set-Content -Encoding utf8 .\design-update.md +``` + +Adjust `--path` if `pwd` shows that the `copilot` image uses a different home +directory. + +## Snapshot the remote state + +Snapshot before deletion when the repository and sandbox state are worth +preserving: + +```powershell +aca sandbox snapshot ` + --id $SandboxId ` + --name demo2-complete +``` + +A snapshot preserves state independently of the running sandbox. A new sandbox +can be created from it: + +```powershell +aca sandbox create --snapshot demo2-complete +``` + +## Validation checklist + +| Evidence | Expected result | +| --- | --- | +| `aca doctor` | Group configuration and Data Owner role pass | +| Initial sandbox state | `Running` | +| Copilot authentication | Starts without placing a token in the repository | +| Repository status before the task | Clean | +| Generated artifact | `design-update.md` exists | +| Source changes | No application source file changed | +| State after stop | `Stopped` | +| State after resume | `Running` | +| Sandbox identity | Same ID before and after resume | +| Plan checksum | Same before and after resume | + +## Troubleshooting + +### `aca doctor` reports an RBAC failure + +Verify that the presenter has **Container Apps SandboxGroup Data Owner** at the +group or parent scope. Wait for propagation, then rerun `aca doctor`. + +### `copilot` is not a public disk + +Run: + +```powershell +aca sandboxgroup disk list-public +``` + +Preview image availability can vary by release and region. Use a supported +region or build a reviewed custom disk from an OCI image: + +```powershell +aca sandboxgroup disk create ` + --image /: ` + --name copilot-demo-image + +aca sandboxgroup disk list +``` + +Create from the returned private image ID with `--disk-id`, not `--disk`. + +### Copilot authentication fails + +Confirm that the group credential status is **Configured**, the token is a +fine-grained `github_pat_` token with Copilot access, and the sandbox was +created after the credential was saved. Recreate the sandbox after credential +rotation. + +### Git clone or Copilot traffic is blocked + +Inspect the sandbox egress policy: + +```powershell +aca sandbox egress show --id $SandboxId +``` + +Review denied connection decisions and add only the required hostname. Do not +disable deny-by-default policy to work around one missing rule. + +### The plan disappears after resume + +Confirm that the same sandbox ID was resumed: + +```powershell +$SandboxId +aca sandbox get --id $SandboxId -o json +``` + +Confirm that the shell returned to the same repository path. The +`aca sandbox create` command creates a different sandbox; +`aca sandbox resume --id $SandboxId` resumes the existing one. + +### The sandbox remains stopped + +Resume it explicitly and wait for `Running`: + +```powershell +aca sandbox resume --id $SandboxId +(aca sandbox get --id $SandboxId -o json | ConvertFrom-Json).state +``` + +If resume fails, inspect the Azure activity log and retry only after identifying +the provisioning or policy error. + +### A preview command rejects a flag + +Use the installed CLI help as the source of truth: + +```powershell +aca --version +aca sandbox create --help +aca sandbox lifecycle set --help +aca sandbox egress set --help +``` + +Do not mix commands from different preview releases. + +## Cleanup + +Export or snapshot every artifact you want to preserve before deletion. +Deleting a sandbox is destructive: + +```powershell +aca sandbox delete --id $SandboxId --yes +``` + +Confirm that the labeled sandbox is gone: + +```powershell +aca sandbox list -l "name=copilot-demo" +``` + +If the whole demo environment is no longer needed, deleting its group also +deletes all remaining sandboxes, snapshots, disk images, volumes, secrets, +identities, and connector attachments: + +```powershell +$ResourceGroup = "rg-ghcp-sandbox-demo" +$SandboxGroup = "ghcp-sandbox-demo" + +aca sandboxgroup delete ` + --name $SandboxGroup ` + --yes + +az group delete ` + --name $ResourceGroup ` + --yes ` + --no-wait +``` + +## Navigation + +Previous: [Demo 2 live runbook](demo-2-runbook.md)