diff --git a/plugins/azure-skills/skills/azure-validate/SKILL.md b/plugins/azure-skills/skills/azure-validate/SKILL.md index 34cd94fe3..f14455c58 100644 --- a/plugins/azure-skills/skills/azure-validate/SKILL.md +++ b/plugins/azure-skills/skills/azure-validate/SKILL.md @@ -38,25 +38,23 @@ metadata: ## Steps -| # | Action | Reference | -|---|--------|-----------| -| 1 | **Load Plan** — Read `.azure/deployment-plan.md` for recipe and configuration. If missing → run azure-prepare first | `.azure/deployment-plan.md` | -| 2 | **Add Validation Steps** — Copy recipe "Validation Steps" to `.azure/deployment-plan.md` as children of "All validation checks pass" | [recipes/README.md](references/recipes/README.md), `.azure/deployment-plan.md` | -| 3 | **Run Validation** — Execute recipe-specific validation commands | [recipes/README.md](references/recipes/README.md) | -| 4 | **Build Verification** — Build the project and fix any errors before proceeding | See recipe | -| 5 | **Static Role Verification** — Review Bicep/Terraform for correct RBAC role assignments in code | [role-verification.md](references/role-verification.md) | -| 6 | **Record Proof** — Populate **Section 7: Validation Proof** with commands run and results | `.azure/deployment-plan.md` | -| 7 | **Resolve Errors** — Fix failures before proceeding | See recipe's `errors.md` | -| 8 | **Update Status** — Only after ALL checks pass, set status to `Validated` | `.azure/deployment-plan.md` | -| 9 | **Deploy (only if the user asked to deploy)** — If the user explicitly requested deployment, invoke **azure-deploy**. Otherwise STOP and report validation results | — | +Run the workflow script and follow its instructions. It walks you through each validation step one at a time, recording progress in `.azure/validate-status.json`. Use [references/scripts/workflow.ps1](references/scripts/workflow.ps1) on Windows or [references/scripts/workflow.sh](references/scripts/workflow.sh) on macOS/Linux. + +Start by calling the script **without** the completed-step argument: + +```bash +pwsh references/scripts/workflow.ps1 -WorkspacePath +# macOS/Linux: bash references/scripts/workflow.sh --workspace-path +``` + +Each run prints the next action and the value to pass next. Perform the action, then re-run with that value (`-CompletedStep ` for pwsh, `--completed-step ` for bash). Repeat until it reports the azure-validate workflow is complete. + +The steps reference recipe details in [references/recipes/README.md](references/recipes/README.md) and role checks in [references/role-verification.md](references/role-verification.md). + > **⛔ VALIDATION AUTHORITY** > -> This skill is the officially verified way to set plan status to `Validated`. You MUST follow these steps to make sure every prerequisite is fulfilled before setting status to `Validated`: -> 1. Run actual validation commands (azd provision --preview, bicep build, terraform validate, etc.) -> 2. Populate **Section 7: Validation Proof** with the commands you ran and their results -> 3. Only then set status to `Validated` -> -> Do NOT set status to `Validated` without running checks and recording proof. +> This skill is the officially verified way to set plan status to `Validated`. You MUST follow the script's instructions to completion before setting status to `Validated`. +> Do NOT set status to `Validated` without doing so. --- diff --git a/plugins/azure-skills/skills/azure-validate/references/scripts/workflow.ps1 b/plugins/azure-skills/skills/azure-validate/references/scripts/workflow.ps1 new file mode 100644 index 000000000..bd45a2561 --- /dev/null +++ b/plugins/azure-skills/skills/azure-validate/references/scripts/workflow.ps1 @@ -0,0 +1,129 @@ +<# +.SYNOPSIS + Walks the agent through the azure-validate workflow, one step at a time. +.PARAMETER WorkspacePath + Path to the workspace being validated (required). +.PARAMETER CompletedStep + The workflow step the agent just completed. Omit this on the first call to + start the workflow. The script records the value in + .azure/validate-status.json and returns the next action to take, along with + the value to pass as -CompletedStep on the next call. +#> +param( + [string]$WorkspacePath, + [string]$CompletedStep +) + +enum ValidationStep { + None + LoadPlan + AddValidationSteps + RunValidation + BuildVerification + StaticRoleVerification + RecordProof + ResolveErrors + UpdateStatus +} + +if (-not $WorkspacePath) { + Write-Error "WorkspacePath is required." + exit 2 +} + +if (-not (Test-Path -Path $WorkspacePath -PathType Container)) { + Write-Error "Error: WorkspacePath '$WorkspacePath' does not exist or is not a directory." + exit 2 +} + +# Resolve the step the agent just completed. +# Omitting -CompletedStep signals the start of the workflow (None). +$step = [ValidationStep]::None +if (-not [string]::IsNullOrEmpty($CompletedStep)) { + if (-not [enum]::TryParse([ValidationStep], $CompletedStep, $true, [ref]$step)) { + $validValues = ([enum]::GetNames([ValidationStep])) -join ", " + Write-Error "Error: '-CompletedStep $CompletedStep' is not a valid step. Valid values: $validValues" + exit 2 + } +} + +# Record progress in .azure/validate-status.json (creating it if needed). +$azureDir = Join-Path -Path $WorkspacePath -ChildPath ".azure" +if (-not (Test-Path -Path $azureDir)) { + New-Item -ItemType Directory -Path $azureDir | Out-Null +} +$validateStatusPath = Join-Path -Path $azureDir -ChildPath "validate-status.json" +$validateStatusJson = @{ completedStep = $step.ToString() } | ConvertTo-Json +[System.IO.File]::WriteAllText($validateStatusPath, $validateStatusJson + [Environment]::NewLine, (New-Object System.Text.UTF8Encoding($false))) + +# Emit the next action based on the step just completed. + +# Step 1: Load Plan +if ($step -eq [ValidationStep]::None) { + Write-Output 'Action: Read `.azure/deployment-plan.md` for recipe and configuration. If missing, run azure-prepare first, then come back to workflow.ps1.' + Write-Output "Next: re-run workflow.ps1 with -CompletedStep LoadPlan after completing the action." + Write-Output 'Reference: `.azure/deployment-plan.md' + exit 0 +} + +# Step 2: Add Validation Steps +if ($step -eq [ValidationStep]::LoadPlan) { + Write-Output 'Action: Copy the recipe''s `Validation Steps` into `.azure/deployment-plan.md` as children of `All validation checks pass`.' + Write-Output "Next: re-run workflow.ps1 with -CompletedStep AddValidationSteps after completing the action." + Write-Output 'Reference: references/recipes/README.md, `.azure/deployment-plan.md' + exit 0 +} + +# Step 3: Run Validation +if ($step -eq [ValidationStep]::AddValidationSteps) { + Write-Output "Action: Execute the recipe-specific validation commands." + Write-Output "Next: re-run workflow.ps1 with -CompletedStep RunValidation after completing the action." + Write-Output "Reference: references/recipes/README.md" + exit 0 +} + +# Step 4: Build Verification +if ($step -eq [ValidationStep]::RunValidation) { + Write-Output "Action: Build the project and fix any errors before proceeding." + Write-Output "Next: re-run workflow.ps1 with -CompletedStep BuildVerification after completing the action." + Write-Output "Reference: See the recipe for build details." + exit 0 +} + +# Step 5: Static Role Verification +if ($step -eq [ValidationStep]::BuildVerification) { + Write-Output "Action: Review the Bicep/Terraform for correct RBAC role assignments in code." + Write-Output "Next: re-run workflow.ps1 with -CompletedStep StaticRoleVerification after completing the action." + Write-Output "Reference: references/role-verification.md" + exit 0 +} + +# Step 6: Record Proof +if ($step -eq [ValidationStep]::StaticRoleVerification) { + Write-Output "Action: Populate **Section 7: Validation Proof** in the plan with the commands run and their results." + Write-Output "Next: re-run workflow.ps1 with -CompletedStep RecordProof after completing the action." + Write-Output 'Reference: `.azure/deployment-plan.md' + exit 0 +} + +# Step 7: Resolve Errors +if ($step -eq [ValidationStep]::RecordProof) { + Write-Output "Action: Fix any validation failures before proceeding." + Write-Output "Next: re-run workflow.ps1 with -CompletedStep ResolveErrors after completing the action." + Write-Output "Reference: See the recipe's errors.md." + exit 0 +} + +# Step 8: Update Status +if ($step -eq [ValidationStep]::ResolveErrors) { + Write-Output 'Action: Only after ALL checks pass, set the plan status to `Validated`.' + Write-Output "Next: re-run workflow.ps1 with -CompletedStep UpdateStatus after completing the action." + Write-Output 'Reference: `.azure/deployment-plan.md' + exit 0 +} + +# Step 9: Deploy (workflow complete) +if ($step -eq [ValidationStep]::UpdateStatus) { + Write-Output "Action: The azure-validate workflow is complete. If the user explicitly requested deployment, invoke azure-deploy. Otherwise STOP and report the validation results." + exit 0 +} diff --git a/plugins/azure-skills/skills/azure-validate/references/scripts/workflow.sh b/plugins/azure-skills/skills/azure-validate/references/scripts/workflow.sh new file mode 100644 index 000000000..3896dc3db --- /dev/null +++ b/plugins/azure-skills/skills/azure-validate/references/scripts/workflow.sh @@ -0,0 +1,139 @@ +#!/usr/bin/env bash +# workflow.sh +# Walks the agent through the azure-validate workflow, one step at a time. +# +# Usage: +# ./workflow.sh --workspace-path [--completed-step ] +# +# Options: +# --workspace-path Path to the workspace being validated (required). +# --completed-step The workflow step the agent just completed. Omit +# on the first call to start the workflow. The +# script records the value in +# .azure/validate-status.json and returns the next +# action to take, along with the value to pass as +# --completed-step on the next call. +# +# Exit codes: +# 0 - next action emitted (or workflow complete) +# 2 - usage / argument error (missing workspace path or invalid step) + +set -uo pipefail + +# Valid workflow steps, in order. +VALID_STEPS=(None LoadPlan AddValidationSteps RunValidation BuildVerification \ + StaticRoleVerification RecordProof ResolveErrors UpdateStatus) + +# Ensure an option that consumes a value actually has one ($@ = remaining args). +need_val() { + [ "$#" -ge 2 ] || { echo "ERROR: $1 requires a value." >&2; exit 2; } +} + +WORKSPACE_PATH="" +COMPLETED_STEP="" + +while [ $# -gt 0 ]; do + case "$1" in + --workspace-path) need_val "$@"; WORKSPACE_PATH="$2"; shift 2 ;; + --completed-step) need_val "$@"; COMPLETED_STEP="$2"; shift 2 ;; + -h|--help) + grep '^#' "$0" | grep -v '^#!' | sed 's/^# \{0,1\}//' + exit 0 ;; + *) + echo "Unknown argument: $1" >&2 + exit 2 ;; + esac +done + +if [ -z "$WORKSPACE_PATH" ]; then + echo "ERROR: --workspace-path is required." >&2 + exit 2 +fi + +if [ ! -d "$WORKSPACE_PATH" ]; then + echo "Error: --workspace-path '$WORKSPACE_PATH' does not exist or is not a directory." >&2 + exit 2 +fi + +# Resolve the step the agent just completed (case-insensitive). +# Omitting --completed-step signals the start of the workflow (None). +STEP="None" +if [ -n "$COMPLETED_STEP" ]; then + STEP="" + for valid in "${VALID_STEPS[@]}"; do + if [ "$(printf '%s' "$COMPLETED_STEP" | tr '[:upper:]' '[:lower:]')" = \ + "$(printf '%s' "$valid" | tr '[:upper:]' '[:lower:]')" ]; then + STEP="$valid" + break + fi + done + if [ -z "$STEP" ]; then + printf 'Error: '\''--completed-step %s'\'' is not a valid step. Valid values: %s\n' \ + "$COMPLETED_STEP" "$(printf '%s, ' "${VALID_STEPS[@]}" | sed 's/, $//')" >&2 + exit 2 + fi +fi + +# Record progress in .azure/validate-status.json (creating it if needed). +AZURE_DIR="$WORKSPACE_PATH/.azure" +mkdir -p "$AZURE_DIR" +VALIDATE_STATUS_PATH="$AZURE_DIR/validate-status.json" +printf '{\n "completedStep": "%s"\n}\n' "$STEP" > "$VALIDATE_STATUS_PATH" + +# Emit the next action based on the step just completed. +case "$STEP" in + None) + # Step 1: Load Plan + echo "Action: Read \`.azure/deployment-plan.md\` for recipe and configuration. If missing, run azure-prepare first, then come back to workflow.sh." + echo "Next: re-run workflow.sh with --completed-step LoadPlan after completing the action." + echo "Reference: \`.azure/deployment-plan.md" + ;; + LoadPlan) + # Step 2: Add Validation Steps + echo "Action: Copy the recipe's \`Validation Steps\` into \`.azure/deployment-plan.md\` as children of \`All validation checks pass\`." + echo "Next: re-run workflow.sh with --completed-step AddValidationSteps after completing the action." + echo "Reference: references/recipes/README.md, \`.azure/deployment-plan.md" + ;; + AddValidationSteps) + # Step 3: Run Validation + echo "Action: Execute the recipe-specific validation commands." + echo "Next: re-run workflow.sh with --completed-step RunValidation after completing the action." + echo "Reference: references/recipes/README.md" + ;; + RunValidation) + # Step 4: Build Verification + echo "Action: Build the project and fix any errors before proceeding." + echo "Next: re-run workflow.sh with --completed-step BuildVerification after completing the action." + echo "Reference: See the recipe for build details." + ;; + BuildVerification) + # Step 5: Static Role Verification + echo "Action: Review the Bicep/Terraform for correct RBAC role assignments in code." + echo "Next: re-run workflow.sh with --completed-step StaticRoleVerification after completing the action." + echo "Reference: references/role-verification.md" + ;; + StaticRoleVerification) + # Step 6: Record Proof + echo "Action: Populate **Section 7: Validation Proof** in the plan with the commands run and their results." + echo "Next: re-run workflow.sh with --completed-step RecordProof after completing the action." + echo "Reference: \`.azure/deployment-plan.md" + ;; + RecordProof) + # Step 7: Resolve Errors + echo "Action: Fix any validation failures before proceeding." + echo "Next: re-run workflow.sh with --completed-step ResolveErrors after completing the action." + echo "Reference: See the recipe's errors.md." + ;; + ResolveErrors) + # Step 8: Update Status + echo "Action: Only after ALL checks pass, set the plan status to \`Validated\`." + echo "Next: re-run workflow.sh with --completed-step UpdateStatus after completing the action." + echo "Reference: \`.azure/deployment-plan.md" + ;; + UpdateStatus) + # Step 9: Deploy (workflow complete) + echo "Action: The azure-validate workflow is complete. If the user explicitly requested deployment, invoke azure-deploy. Otherwise STOP and report the validation results." + ;; +esac + +exit 0