#!/usr/bin/env bash # Phase 02 verification script. # Confirms the 8 L1 module folders exist under modules/l1/ with the exact # names from REQ-02, each containing a valid manifest.yaml (D-017 schema) # and a uniform mock_apply.sh (D-007 + D-018) that exits 0 with the # expected echo markers. # # Usage: scripts/verify_phase02.sh # Exit codes: 0 = all checks passed; 1 = one or more checks failed. set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" L1_DIR="${ROOT}/modules/l1" # Expected L1 names per REQ-02 / D-019. EXPECTED_L1S=( l1-eks-fargate l1-iam-role l1-lambda l1-api-gateway l1-eventbridge l1-sqs l1-s3 l1-cloudwatch ) fail_count=0 pass() { printf ' [PASS] %s\n' "$1"; } fail() { printf ' [FAIL] %s\n' "$1"; fail_count=$((fail_count + 1)); } echo "== Phase 02 verification ==" echo "L1 dir: ${L1_DIR}" echo # --- Check 1: exactly 8 L1 folders with the expected names --- echo "-- Check 1: 8 L1 folders with expected names --" if [ ! -d "$L1_DIR" ]; then fail "modules/l1/ does not exist" echo echo "== Summary ==" echo "Phase 02 verification FAILED (${fail_count} check(s) failed)" exit 1 fi actual_folders=$(ls "$L1_DIR" | sort | tr '\n' ' ') expected_folders=$(printf '%s\n' "${EXPECTED_L1S[@]}" | sort | tr '\n' ' ') if [ "$actual_folders" = "$expected_folders" ]; then pass "exactly 8 L1 folders present and named correctly" else fail "L1 folder list mismatch" echo " expected: $expected_folders" echo " actual: $actual_folders" fi # --- Per-L1 checks --- for l1 in "${EXPECTED_L1S[@]}"; do echo "-- L1: ${l1} --" dir="${L1_DIR}/${l1}" # Check 2a: folder exists if [ ! -d "$dir" ]; then fail "${l1}: folder missing" continue fi pass "${l1}: folder exists" # Check 2b: manifest.yaml exists + parses + name matches folder + kind=l1 manifest="${dir}/manifest.yaml" if [ ! -f "$manifest" ]; then fail "${l1}: manifest.yaml missing" else manifest_ok=$(python3 -c " import yaml, sys try: d = yaml.safe_load(open('${manifest}')) name = d.get('name') == '${l1}' kind = d.get('kind') == 'l1' has_inputs = isinstance(d.get('inputs'), dict) sys.exit(0 if (name and kind and has_inputs) else 1) except Exception as e: print(f' parse error: {e}', file=sys.stderr) sys.exit(2) " 2>/dev/null; echo $?) if [ "$manifest_ok" = "0" ]; then pass "${l1}: manifest.yaml valid (name=${l1}, kind=l1, inputs present)" else fail "${l1}: manifest.yaml invalid (name/kind/inputs check failed; rc=${manifest_ok})" fi fi # Check 2c: mock_apply.sh exists + executable + bash -n clean apply="${dir}/mock_apply.sh" if [ ! -f "$apply" ]; then fail "${l1}: mock_apply.sh missing" continue fi if [ ! -x "$apply" ]; then fail "${l1}: mock_apply.sh not executable" else pass "${l1}: mock_apply.sh is executable" fi if ! bash -n "$apply" 2>/dev/null; then fail "${l1}: mock_apply.sh bash -n failed" else pass "${l1}: mock_apply.sh bash -n clean" fi # Check 2d: end-to-end run: exit 0 + expected markers, completes in <2s start=$(date +%s) output=$("$apply" 2>&1) rc=$? elapsed=$(( $(date +%s) - start )) if [ "$rc" -ne 0 ]; then fail "${l1}: mock_apply.sh exited ${rc}" elif ! echo "$output" | grep -qF "[L1: ${l1}] applying..."; then fail "${l1}: missing '[L1: ${l1}] applying...' marker" elif ! echo "$output" | grep -qF "[L1: ${l1}] OK"; then fail "${l1}: missing '[L1: ${l1}] OK' marker" elif [ "$elapsed" -lt 1 ] || [ "$elapsed" -gt 2 ]; then fail "${l1}: run took ${elapsed}s (expected ~1s; 1<=t<=2 ok)" else pass "${l1}: mock_apply.sh runs, exits 0, markers correct (${elapsed}s)" fi done echo echo "== Summary ==" if [ "$fail_count" -eq 0 ]; then echo "Phase 02 verification PASSED (8 L1 modules, all checks ok)" exit 0 else echo "Phase 02 verification FAILED (${fail_count} check(s) failed)" exit 1 fi