#!/usr/bin/env bash # Run the platform pipeline for a single pattern (plan-only or check-only). # # Usage: run_pattern_plan.sh [--check-only] # # --check-only: offline mode (no AWS) — resolves the sample contract for the # module, runs the adapter, validates the emitted Terraform structure. # (default): requires AWS — runs terraform plan on the emitted Terraform. set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$ROOT" CHECK_ONLY=0 MODULE="" for arg in "$@"; do case "$arg" in --check-only) CHECK_ONLY=1 ;; --*) echo "FAIL: unknown flag: $arg" >&2; exit 1 ;; *) MODULE="$arg" ;; esac done [ -n "$MODULE" ] || { echo "FAIL: module name required" >&2; exit 1; } CONTRACT="contracts/$MODULE.yaml" [ -f "$CONTRACT" ] || { echo "FAIL: no sample contract at $CONTRACT for module '$MODULE'" >&2; exit 1; } WORK="/tmp/nova_pattern_plan_$MODULE" rm -rf "$WORK"; mkdir -p "$WORK" echo "=== Pattern plan: $MODULE ===" echo "" echo "--- Step 1: environment check ---" python3 core/environment_check.py "$CONTRACT" || { echo "FAIL: environment not bound" >&2; exit 1; } echo "" echo "--- Step 2: validate contract ---" python3 -c " import json, yaml, jsonschema schema = json.load(open('schemas/contract.schema.json')) contract = yaml.safe_load(open('$CONTRACT')) jsonschema.validate(contract, schema) print(f'contract: module={contract[\"module\"]} env={contract[\"environment\"]}') " echo "" echo "--- Step 3: resolve contract -> stack ---" python3 core/contract_resolver.py "$CONTRACT" "$WORK/stack.json" || { echo "FAIL: resolver failed" >&2; exit 1; } python3 -c "import json; d=json.load(open('$WORK/stack.json')); print(f'stack: {d[\"stack\"][\"name\"]} {len(d[\"resources\"])} resource(s)')" echo "" echo "--- Step 4: adapter compiles stack -> terraform ---" OUT_DIR="$WORK/terraform" python3 adapters/terraform/adapter.py "$WORK/stack.json" "$OUT_DIR" || { echo "FAIL: adapter failed" >&2; exit 1; } echo "adapter: emitted $OUT_DIR/{main.tf,terraform.tf,providers.tf}" if [ "$CHECK_ONLY" = "1" ]; then echo "" echo "--- Step 5: validate adapter output structure (offline) ---" python3 -c " import json, os d = json.load(open('$WORK/stack.json')) assert d['stack']['kind'] == 'l2', f\"expected l2, got {d['stack']['kind']}\" assert len(d['resources']) >= 1 tf_dir = '$OUT_DIR' for f in ('main.tf', 'terraform.tf', 'providers.tf'): assert os.path.isfile(os.path.join(tf_dir, f)), f'{f} missing' main = open(os.path.join(tf_dir, 'main.tf')).read() assert len(main) > 0, 'main.tf is empty' print(f'pattern $MODULE: adapter output OK ({len(d[\"resources\"])} resource(s))') " echo "" echo "=== PATTERN CHECK OK ($MODULE) ===" exit 0 fi echo "" echo "--- Step 5: terraform init + validate + plan ---" cd "$OUT_DIR" terraform init -backend=false -input=false terraform validate terraform plan -lock=false -input=false -out=tfplan echo "=== PATTERN PLAN OK ($MODULE) ==="