Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions plugin/skills/azure-app-onboard-prereq/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
---
name: azure-app-onboard-prereq
description: "Assess whether source code is ready to deploy to Azure — the check BEFORE infrastructure work. Evaluates build health, app completeness, dependencies and local services, stack compatibility, and deployment feasibility. Answers questions about what your app needs before it can be deployed — frameworks, dependencies, and configuration. Checks whether dependencies are compatible and identifies deployment blockers and unsupported frameworks. WHEN: \"evaluate my repo\", \"is my app ready to deploy\", \"what does my app need to deploy\", \"what do I need before deploying\", \"does my app need\", \"can I ship this to Azure\", \"scan my repo for issues\", \"is this app deployable\", \"check if my app is ready for Azure\", \"do I need a Dockerfile\", \"what's blocking my deployment\", \"are there any blockers\", \"are my dependencies compatible\", \"does Azure support my framework\", \"what needs to change before deploying\", \"check my app configuration\"."
license: MIT
metadata:
author: Microsoft
version: "0.0.0-placeholder"
---

# Azure App Onboard Prereq — Repository Evaluation

Evaluate a user's repository for build health, app completeness, and Azure deployment feasibility — before infrastructure planning. Produces per-component verdicts (PASS/WARN/FAIL) consumed by downstream phases.

> **Orchestrator relationship:** Called by `azure-app-onboard` at Step 3, or used standalone for code readiness checks. When called by the orchestrator, return control to `azure-app-onboard` after writing artifacts — do NOT invoke downstream phases directly.

## When NOT to Use

| Signal | Redirect |
|--------|----------|
| Validate infrastructure (Bicep/TF/azure.yaml) | **azure-validate** |
| Generate IaC | **azure-prepare** |
| End-to-end idea-to-production | **azure-app-onboard** |
| Run `azd up` or deploy | **azure-deploy** |

## Rules

> ⛔ **ABSOLUTE PROHIBITION — `npm install` and `npm test` are NEVER allowed.**
> Under NO circumstances may you run `npm install`, `npm test`, `npx jest`, `pip install`, `pytest`, `dotnet build`, `dotnet restore`, `dotnet test`, `go mod download`, `cargo build`, or ANY package-manager install, build, or test command during the prereq phase. The prereq phase is read-only evaluation + static-only verification.

1. **Read-only by default** — Do not modify user code unless asked.
2. ⛔ **Build/install commands and test suites are FORBIDDEN** on existing code — no `ask_user` override. Limited exception: when agent created or modified >2 source files AND re-evaluation passed (M=0), the build-validation gate in [remediation-protocol.md § Step 6](references/remediation-protocol.md) allows install/build/test with explicit user approval via `ask_user`.
3. ⛔ **Every repo goes through the full pipeline (Steps 1–5). No exceptions.** Do not refuse, skip, or short-circuit based on what you recognize. The readiness gate in Step 4 is the ONLY mechanism that halts the pipeline.
4. ⛔ **Code modifications require `ask_user`** — Dockerfile generation, config changes, scaffolding.
5. ⛔ **Destructive actions require `ask_user`** — deleting files, overwriting config, provisioning resources, modifying RBAC.
6. **Non-blocking** — Warnings don't stop the workflow; only hard failures block.
7. **Scope** — Evaluation + starter code scaffolding. IaC is the **prepare** phase's job.
8. **Direct entry** — Don't repeat orchestrator's intent questions.
9. **Max 3 questions** before showing results.

## MCP Tools

| Tool | Purpose |
|------|---------|
| `mcp_azure_mcp_get_azure_bestpractices` | Validate detected stack patterns against Azure best practices |
| `mcp_azure_mcp_extension_cli_install` | Check/install required CLI tools (az, azd, func) |

## Workflow

### Step 1: Session Check

**If called by orchestrator (`azure-app-onboard`):** Session already exists — read `context.json` and proceed to Step 2.

**If entered directly:** Follow session creation from [session-protocol.md](references/session-protocol.md). Set `currentPhase: "prereq"`, `completedPhases: []`.

### Step 2: Scan Workspace

Scan for project files. Detect components, `repo{}`, `detectedInfra[]`, `detectedServices[]`. Classify Terraform providers. Check CLI availability. For stack or infrastructure detection conflicts, see [conflict-resolution.md](references/conflict-resolution.md).

> ⛔ **Probe data reuse.** If `context.json.quickProbe` exists with populated `manifests[]`: seed components from it, skip re-reading files already captured (`manifests[]`, `dockerfiles[]`, `composeServices[]`, `importSamples[]`). Carry forward `missingFiles[]` as automatic ❌ FAIL, `healthEndpoint: null` as ⚠️ WARN, and `earlyHaltSignal` as 🛑 HALT. Still scan files the probe didn't read (config files, source files beyond import samples, nested manifests the probe missed due to budget cap). The 3-axis evaluation (Steps 3.1–3.3) always runs — probe data accelerates it, doesn't replace it.

> If no project files, no Dockerfile, AND no index.html → ⛔ Read [zero-code-path.md](references/zero-code-path.md).

### Step 3: Per-Component Evaluation

| Sub-step | Action | Reference |
|----------|--------|-----------|
| 3.1 | **Build check** | ⛔ Read [build-check.md](references/build-check.md) |
| 3.2 | **Completeness check** | ⛔ Read [completeness-check.md](references/completeness-check.md) |
| 3.3 | **Deployability check** | ⛔ Read [deployability-check.md](references/deployability-check.md) |
| 3.3a | **Dependency compatibility** (conditional) | Already loaded via deployability-check.md. Apply cloud SDK swap rules from [dependency-compatibility.md](references/dependency-compatibility.md) ONLY IF grep found `aws-sdk\|@aws-sdk\|boto3\|google-cloud\|@google-cloud\|firebase` in manifests |
| 3.3b | **Component mapping** (conditional) | Read [component-mapping.md](references/component-mapping.md) ONLY IF >1 project manifest found (monorepo) |

Populate `buildRequirements` per component after the 3-axis evaluation.

### Step 4: Write Artifacts + Readiness Gate

⛔ Read [readiness-gate.md](references/readiness-gate.md) — contains artifact write rules, severity tiers, critical gate, batch-then-approve flow, and fast-track condition.

### Step 5: Present Findings

Per [readiness-gate.md § Present Findings](references/readiness-gate.md) — show verdicts grouped by severity before proceeding.

### Steps 6-8: Remediation + Final State + Route

Read [remediation-protocol.md](references/remediation-protocol.md) **ONLY IF any ❌ FAIL verdict exists** — contains remediation loop, static verification, re-eval mandate, post-remediation updates. If all verdicts are ✅ PASS or ⚠️ WARN, skip remediation and proceed to final state write + routing (update `context.json`: append `"prereq"` to `completedPhases`, set `currentPhase: null`).

## Verdicts

| Verdict | Meaning |
|---------|---------|
| ✅ PASS | No issues |
| ⚠️ WARN | Non-blocking — can proceed with caveats |
| ❌ FAIL | Blocking — must be resolved before continuing |

## Outputs

| Artifact | Location | Consumer |
|----------|----------|----------|
| Session context | `context.json` → `components[]`, `repo{}`, `detectedInfra[]`, `detectedServices[]` | All downstream phases |
| Prereq output | `prereq-output.json` | prepare phase (via `azure-app-onboard`) |
| Readiness report | `.copilot-azure/sessions/{uuid}/readiness-report.md` | User (offline reference) |
| Schemas | `session-schemas.ts` (`AppOnboardContext`), `prereq-schemas.ts` (`PrereqOutput`, `BuildRequirements`, `CloudSdkSwap`) | Artifact validation |
110 changes: 110 additions & 0 deletions plugin/skills/azure-app-onboard-prereq/references/build-check.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# Build Check

> ⛔ **No build/install/test commands — `npm install`, `npm test`, `dotnet build`, `dotnet restore`, `dotnet test`, `pip install`, `pytest`, `go mod download`, `cargo build`. Use static analysis only during this check.**

Detect the project's language/framework stack and assess build health. Static detection (manifest reading) is the **default mode**. Build execution is an optional escalation requiring user confirmation.

> **Dynamic detection:** The agent determines build commands by reading the actual project manifest (e.g., inspecting `package.json` `scripts` to find the real build script name). The table below is reference guidance, not a fixed lookup.

## Step 1: Detect Stack

Scan the workspace for project files to determine the technology stack. ⛔ **Do NOT run any command from this table — it is for identification only.**

| File | Language/Framework | Build System (⛔ DO NOT RUN) |
|------|--------------------|-------------------------------|
| `package.json` | Node.js | npm/yarn/pnpm (detect pm from lockfile) |
| `package.json` + `tsconfig.json` | TypeScript | npm/yarn/pnpm + tsc |
| `requirements.txt` | Python | pip |
| `pyproject.toml` | Python (modern) | pip / uv / poetry |
| `*.csproj` / `*.sln` | .NET | dotnet CLI |
| `pom.xml` | Java (Maven) | mvn |
| `build.gradle` / `build.gradle.kts` | Java/Kotlin (Gradle) | gradle |
| `go.mod` | Go | go CLI |
| `Cargo.toml` | Rust | cargo |
| `Gemfile` | Ruby | bundler |
| `composer.json` | PHP | composer |
| `docker-compose.yml` / `compose.yml` | (dependency source) | Not a build system — infrastructure dependencies parsed during deployability check (Step 3.3) |
| `build.gradle` + `com.google.cloud.tools.jib` | Java (Jib) | gradle + jib plugin |

**Modern package manager lockfiles:** `uv.lock` → uv (`uv sync`), `bun.lock` / `bun.lockb` → bun (`bun install`). Detect alongside standard lockfiles.

> ⚠️ If **no project file** is found, check for a `Dockerfile`. If a Dockerfile exists, note container-dependent build in findings.

### Multi-Project Detection

Search recursively for project manifests, skip `node_modules`/`.git`/`dist`/`build`/`vendor`/`.venv`/`__pycache__`/`.terraform`/`bin`/`obj`. Each directory with a project file = one component. Evaluate each independently.

## Step 2: Static Detection (Default)

Read project manifests to infer build health **without executing any commands**. This is the default mode for all evaluations.

**What to check:**
- **Missing dependencies** — referenced imports not in manifest
- **Version conflicts** — engine/runtime version mismatches visible in manifest (e.g., `"engines": {"node": ">=20"}` but lockfile pins Node 16 packages)
- **Obvious misconfigurations** — missing `main`/`start` script when expected, empty dependency blocks, circular references
- **Lock file presence** — `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`, `poetry.lock`, `Pipfile.lock` — missing lock file = ⚠️ WARN

> **Package manager detection:** `package-lock.json` → npm, `yarn.lock` → yarn, `pnpm-lock.yaml` → pnpm. Default to npm if no lockfile.

### Import → Manifest Cross-Check

Scan source files to detect packages imported in code but missing from the dependency manifest. This catches pre-existing repo bugs that cause build failures on Azure (e.g., `Cannot find module` during `az acr build`).

**Node.js / TypeScript:**
1. Scan source files (`*.ts`, `*.tsx`, `*.js`, `*.jsx`, `*.mjs`) in the component directory for `import ... from '{package}'` and `require('{package}')` statements
2. Extract the package name (first path segment: `@scope/name` for scoped, `name` for unscoped — ignore relative paths `./`, `../`, `#`)
3. Check each extracted package against `dependencies` + `devDependencies` in `package.json`
4. Skip Node.js built-ins (`fs`, `path`, `crypto`, `http`, `https`, `url`, `os`, `util`, `stream`, `events`, `child_process`, `buffer`, `assert`, `net`, `tls`, `dns`, `cluster`, `zlib`, `readline`, `querystring`, `string_decoder`, `timers`, `worker_threads`, `perf_hooks`, `async_hooks`, `v8`, `vm`, `inspector`, `module`, `process`, `console`, `node:*`)
5. Remaining unresolved packages:

| File location | Severity | Why |
|---|---|---|
| Build-time config (`next.config.*`, `webpack.config.*`, `vite.config.*`, `babel.config.*`, `postcss.config.*`, `tailwind.config.*`) | ❌ FAIL | Build will crash — `Cannot find module` at config load time. Offer to add to `package.json`. |
| Entry point or source code (`src/**`, `app/**`, `pages/**`, `lib/**`) | 🔧 Recommended Fix | App may crash at runtime. Offer to add to `package.json`. |
| Test files only (`test/**`, `tests/**`, `__tests__/**`, `*.test.*`, `*.spec.*`) | ⚠️ WARN | Doesn't affect deployment |

**Python:**
Scan `*.py` for `import {pkg}` / `from {pkg} import`, cross-reference against `requirements.txt` / `pyproject.toml [project.dependencies]`. Skip stdlib modules. Same severity tiers apply.

**Scope:** Always scan ALL config files (`next.config.*`, `webpack.config.*`, `vite.config.*`, `babel.config.*`, `postcss.config.*`, `tailwind.config.*`) — these are a fixed small set (~1-3 per component) and produce ❌ FAIL when a missing import is found. For `src/`/`app/`/`pages/`/`lib/`, limit to 20 source files per component. Do NOT scan `node_modules/`, `.venv/`, `dist/`, `build/`.

**When a ❌ FAIL or 🔧 Fix is found:** Include in the batch-then-approve fix plan: "Add `{package}` to `package.json` dependencies." This is a 1-line manifest change — low risk.

| Outcome | Verdict | Notes |
|---------|---------|-------|
| No issues found in manifest | ✅ PASS | Inferred: build likely succeeds |
| Warnings visible in manifest | ⚠️ WARN | Record specifics |
| Obvious errors in manifest | ❌ FAIL | Record specifics |
| No build system detected | ⚠️ WARN | Likely static site or script-only repo |
| Only Dockerfile found | ⚠️ WARN | Build depends on container — note this |

**Dependency vintage check:** If ALL pinned dependencies are 5+ years old AND the ecosystem has known breaking changes (e.g., Werkzeug 0.x→1.x removed `werkzeug.contrib`, MarkupSafe <1.0 has no Python 3.10+ wheels, `itsdangerous<1.0` API completely changed), classify as ❌ FAIL — `pip install` / `npm install` WILL fail on Azure's current runtimes. Check: grep for imports from removed modules (e.g., `werkzeug.contrib.*`, `flask.ext.*`). If found → ❌ FAIL with "imports from removed module — dependency chain incompatible with modern runtime."

**Transitive dependency check (post-migration):** After upgrading dependencies during 🔶 Major Migration, run `pip install -r requirements.txt` (user consent is already granted for migration) to catch transitive deps that new versions require but old versions bundled inline. These won't appear in any import statement — only `pip install` reveals them. If install fails, read the error, add the missing package to requirements, and retry. Also run `python -c "from app import create_app"` (or equivalent entry-point import) to catch import-time validation errors (e.g., WTForms `Email()` requires `email-validator` at class definition time, not at call time).

**F1 viability signal:** While evaluating dependencies, also check `f1Viable` per the heuristics in [dependency-compatibility.md § F1 Viability](dependency-compatibility.md). A dependency vintage ❌ FAIL that requires 🔶 Major Migration (>5 files) should set `f1Viable: false` — the migration + Oryx rebuild will exhaust F1's CPU budget.

## Step 3: Build Execution (Optional — User-Confirmed)

⛔ **Only run when user explicitly asks** (e.g., "Does my code compile?", "Can you build this?") **and confirms via `ask_user`.**

### Build Execution Rules

1. **Read the manifest dynamically** — determine the actual build script name from the project file (don't assume `npm run build` — read `scripts` field)
2. **Install dependencies first** — Always run the install step before build
3. **Capture full output** — Save stdout and stderr for the report
4. **Timeout** — 5 minutes per component. If exceeded, record as ⚠️ WARN (not FAIL)
5. **Do NOT modify code** — If the build fails, record the failure; do not attempt fixes

### Build Verdict Logic

| Outcome | Verdict | Notes |
|---------|---------|-------|
| Build succeeds (exit code 0) | ✅ PASS | Code compiles cleanly |
| Build succeeds with warnings | ⚠️ WARN | Record warnings in report |
| Build fails (exit code ≠ 0) | ❌ FAIL | Record error output |
| Build times out (>5 min) | ⚠️ WARN | May still be valid — suggest CI/CD |

## Native Module Detection

See [dependency-compatibility.md § Native Module Detection](dependency-compatibility.md) for the canonical detection procedure, edge cases, and package table. Results go to `buildRequirements.hasNativeModules`.
Loading
Loading