diff --git a/.forge/role-reviewer-live-1522-001-attempt-2-run-71d436e6354c.md b/.forge/role-reviewer-live-1522-001-attempt-2-run-71d436e6354c.md new file mode 100644 index 0000000..5ea9d9c --- /dev/null +++ b/.forge/role-reviewer-live-1522-001-attempt-2-run-71d436e6354c.md @@ -0,0 +1,3 @@ +# role-reviewer-live-1522-001-attempt-2-run-71d436e6354c + +Forge 이슈 작업 브랜치 `forge/role-reviewer-live-1522-001-attempt-2-run-71d436e6354c`. diff --git a/verification/evidence-report.json b/verification/evidence-report.json new file mode 100644 index 0000000..a5a5a41 --- /dev/null +++ b/verification/evidence-report.json @@ -0,0 +1,120 @@ +{ + "evidence_report_version": "1.0", + "generated_at": "2026-07-14T15:22:00Z", + "source_report": "verification/smoke-test-report.json", + "summary": { + "total_checks": 17, + "passed": 0, + "failed": 0, + "warnings": 0, + "skipped": 0 + }, + "ci_pipeline_checklist": [ + { + "id": "ci_build", + "description": "Build stage configured", + "status": "PENDING", + "message": "Run smoke-test.sh to populate" + }, + { + "id": "ci_test", + "description": "Test stage configured", + "status": "PENDING", + "message": "Run smoke-test.sh to populate" + }, + { + "id": "ci_package", + "description": "Package stage configured", + "status": "PENDING", + "message": "Run smoke-test.sh to populate" + }, + { + "id": "ci_deploy", + "description": "Deploy/CI-CD pipeline configured", + "status": "PENDING", + "message": "Run smoke-test.sh to populate" + } + ], + "operational_risks_checklist": [ + { + "id": "risk_deployment", + "description": "Deployment strategy defined", + "status": "PENDING", + "message": "Run smoke-test.sh to populate" + }, + { + "id": "risk_monitoring", + "description": "Monitoring configured", + "status": "PENDING", + "message": "Run smoke-test.sh to populate" + }, + { + "id": "risk_backup", + "description": "Backup mechanism in place", + "status": "PENDING", + "message": "Run smoke-test.sh to populate" + }, + { + "id": "risk_secret", + "description": "Secret management configured", + "status": "PENDING", + "message": "Run smoke-test.sh to populate" + }, + { + "id": "risk_health", + "description": "Health check endpoints defined", + "status": "PENDING", + "message": "Run smoke-test.sh to populate" + }, + { + "id": "risk_logging", + "description": "Logging framework configured", + "status": "PENDING", + "message": "Run smoke-test.sh to populate" + }, + { + "id": "risk_error", + "description": "Error handling implemented", + "status": "PENDING", + "message": "Run smoke-test.sh to populate" + }, + { + "id": "risk_rollback", + "description": "Rollback strategy documented", + "status": "PENDING", + "message": "Run smoke-test.sh to populate" + }, + { + "id": "risk_shutdown", + "description": "Graceful shutdown handling", + "status": "PENDING", + "message": "Run smoke-test.sh to populate" + } + ], + "core_tests": [ + { + "id": "compilation", + "description": "Code compilation", + "status": "PENDING", + "message": "Run smoke-test.sh to populate" + }, + { + "id": "unit_tests", + "description": "Unit test execution", + "status": "PENDING", + "message": "Run smoke-test.sh to populate" + }, + { + "id": "role_matrix", + "description": "Role matrix implementation", + "status": "PENDING", + "message": "Run smoke-test.sh to populate" + }, + { + "id": "runtime", + "description": "Runtime integration", + "status": "PENDING", + "message": "Run smoke-test.sh to populate" + } + ] +} diff --git a/verification/generate-evidence.sh b/verification/generate-evidence.sh new file mode 100644 index 0000000..7bf4563 --- /dev/null +++ b/verification/generate-evidence.sh @@ -0,0 +1,190 @@ +#!/bin/bash +# Evidence Report Generator +# Parses smoke-test-report.json and generates evidence-report.json + +set -e + +SMOKE_REPORT="verification/smoke-test-report.json" +EVIDENCE_REPORT="verification/evidence-report.json" + +echo "=== Generating Evidence Report ===" + +# Check if smoke test report exists +if [ ! -f "$SMOKE_REPORT" ]; then + echo "Error: $SMOKE_REPORT not found. Run smoke-test.sh first." + exit 1 +fi + +# Check if jq is available +if ! command -v jq &>/dev/null; then + echo "Error: jq is required but not installed." + exit 1 +fi + +# Extract summary counts +TOTAL=$(jq '.summary.total' "$SMOKE_REPORT") +PASSED=$(jq '.summary.passed' "$SMOKE_REPORT") +FAILED=$(jq '.summary.failed' "$SMOKE_REPORT") +WARNED=$(jq '.summary.warned' "$SMOKE_REPORT") +SKIPPED=$(jq '.summary.skipped' "$SMOKE_REPORT") + +# Extract test results using proper JSON array parsing +get_test_status() { + local test_name="$1" + jq -r ".results[] | select(.test == \"$test_name\") | .status" "$SMOKE_REPORT" 2>/dev/null || echo "UNKNOWN" +} + +get_test_message() { + local test_name="$1" + jq -r ".results[] | select(.test == \"$test_name\") | .message" "$SMOKE_REPORT" 2>/dev/null || echo "No message" +} + +# CI Pipeline Checklist (4 items) +CI_BUILD=$(get_test_status "ci_build_stage") +CI_BUILD_MSG=$(get_test_message "ci_build_stage") +CI_TEST=$(get_test_status "ci_test_stage") +CI_TEST_MSG=$(get_test_message "ci_test_stage") +CI_PACKAGE=$(get_test_status "ci_package_stage") +CI_PACKAGE_MSG=$(get_test_message "ci_package_stage") +CI_DEPLOY=$(get_test_status "ci_deploy_stage") +CI_DEPLOY_MSG=$(get_test_message "ci_deploy_stage") + +# Operational Risks Checklist (9 items) +RISK_DEPLOY=$(get_test_status "risk_deployment_strategy") +RISK_DEPLOY_MSG=$(get_test_message "risk_deployment_strategy") +RISK_MONITOR=$(get_test_status "risk_monitoring") +RISK_MONITOR_MSG=$(get_test_message "risk_monitoring") +RISK_BACKUP=$(get_test_status "risk_backup") +RISK_BACKUP_MSG=$(get_test_message "risk_backup") +RISK_SECRET=$(get_test_status "risk_secret_management") +RISK_SECRET_MSG=$(get_test_message "risk_secret_management") +RISK_HEALTH=$(get_test_status "risk_health_check") +RISK_HEALTH_MSG=$(get_test_message "risk_health_check") +RISK_LOGGING=$(get_test_status "risk_logging") +RISK_LOGGING_MSG=$(get_test_message "risk_logging") +RISK_ERROR=$(get_test_status "risk_error_handling") +RISK_ERROR_MSG=$(get_test_message "risk_error_handling") +RISK_ROLLBACK=$(get_test_status "risk_rollback") +RISK_ROLLBACK_MSG=$(get_test_message "risk_rollback") +RISK_SHUTDOWN=$(get_test_status "risk_graceful_shutdown") +RISK_SHUTDOWN_MSG=$(get_test_message "risk_graceful_shutdown") + +# Core Tests +COMPILATION=$(get_test_status "compilation") +COMPILATION_MSG=$(get_test_message "compilation") +UNIT_TESTS=$(get_test_status "unit_tests") +UNIT_TESTS_MSG=$(get_test_message "unit_tests") +ROLE_MATRIX=$(get_test_status "role_matrix_impl") +ROLE_MATRIX_MSG=$(get_test_message "role_matrix_impl") +RUNTIME=$(get_test_status "runtime_integration") +RUNTIME_MSG=$(get_test_message "runtime_integration") + +# Generate evidence report +cat > "$EVIDENCE_REPORT" << 'EOF' +{ + "evidence_report_version": "1.0", + "generated_at": "__TIMESTAMP__", + "source_report": "verification/smoke-test-report.json", + "summary": { + "total_checks": 0, + "passed": 0, + "failed": 0, + "warnings": 0, + "skipped": 0 + }, + "ci_pipeline_checklist": [], + "operational_risks_checklist": [], + "core_tests": [] +} +EOF + +# Build CI pipeline checklist JSON +CI_CHECKLIST=$(cat << JQEOF +[ + {"id": "ci_build", "description": "Build stage configured", "status": "$CI_BUILD", "message": "$CI_BUILD_MSG"}, + {"id": "ci_test", "description": "Test stage configured", "status": "$CI_TEST", "message": "$CI_TEST_MSG"}, + {"id": "ci_package", "description": "Package stage configured", "status": "$CI_PACKAGE", "message": "$CI_PACKAGE_MSG"}, + {"id": "ci_deploy", "description": "Deploy/CI-CD pipeline configured", "status": "$CI_DEPLOY", "message": "$CI_DEPLOY_MSG"} +] +JQEOF +) + +# Build operational risks checklist JSON +RISK_CHECKLIST=$(cat << JQEOF +[ + {"id": "risk_deployment", "description": "Deployment strategy defined", "status": "$RISK_DEPLOY", "message": "$RISK_DEPLOY_MSG"}, + {"id": "risk_monitoring", "description": "Monitoring configured", "status": "$RISK_MONITOR", "message": "$RISK_MONITOR_MSG"}, + {"id": "risk_backup", "description": "Backup mechanism in place", "status": "$RISK_BACKUP", "message": "$RISK_BACKUP_MSG"}, + {"id": "risk_secret", "description": "Secret management configured", "status": "$RISK_SECRET", "message": "$RISK_SECRET_MSG"}, + {"id": "risk_health", "description": "Health check endpoints defined", "status": "$RISK_HEALTH", "message": "$RISK_HEALTH_MSG"}, + {"id": "risk_logging", "description": "Logging framework configured", "status": "$RISK_LOGGING", "message": "$RISK_LOGGING_MSG"}, + {"id": "risk_error", "description": "Error handling implemented", "status": "$RISK_ERROR", "message": "$RISK_ERROR_MSG"}, + {"id": "risk_rollback", "description": "Rollback strategy documented", "status": "$RISK_ROLLBACK", "message": "$RISK_ROLLBACK_MSG"}, + {"id": "risk_shutdown", "description": "Graceful shutdown handling", "status": "$RISK_SHUTDOWN", "message": "$RISK_SHUTDOWN_MSG"} +] +JQEOF +) + +# Build core tests JSON +CORE_TESTS=$(cat << JQEOF +[ + {"id": "compilation", "description": "Code compilation", "status": "$COMPILATION", "message": "$COMPILATION_MSG"}, + {"id": "unit_tests", "description": "Unit test execution", "status": "$UNIT_TESTS", "message": "$UNIT_TESTS_MSG"}, + {"id": "role_matrix", "description": "Role matrix implementation", "status": "$ROLE_MATRIX", "message": "$ROLE_MATRIX_MSG"}, + {"id": "runtime", "description": "Runtime integration", "status": "$RUNTIME", "message": "$RUNTIME_MSG"} +] +JQEOF +) + +# Calculate checklist counts +CI_PASSED=$(echo "$CI_CHECKLIST" | jq '[.[] | select(.status == "PASS")] | length') +CI_FAILED=$(echo "$CI_CHECKLIST" | jq '[.[] | select(.status == "FAIL")] | length') +CI_WARNED=$(echo "$CI_CHECKLIST" | jq '[.[] | select(.status == "WARN")] | length') + +RISK_PASSED=$(echo "$RISK_CHECKLIST" | jq '[.[] | select(.status == "PASS")] | length') +RISK_FAILED=$(echo "$RISK_CHECKLIST" | jq '[.[] | select(.status == "FAIL")] | length') +RISK_WARNED=$(echo "$RISK_CHECKLIST" | jq '[.[] | select(.status == "WARN")] | length') + +CORE_PASSED=$(echo "$CORE_TESTS" | jq '[.[] | select(.status == "PASS")] | length') +CORE_FAILED=$(echo "$CORE_TESTS" | jq '[.[] | select(.status == "FAIL")] | length') +CORE_WARNED=$(echo "$CORE_TESTS" | jq '[.[] | select(.status == "WARN")] | length') +CORE_SKIPPED=$(echo "$CORE_TESTS" | jq '[.[] | select(.status == "SKIP")] | length') + +TOTAL_CHECKS=$((4 + 9 + 4)) +TOTAL_PASSED=$((CI_PASSED + RISK_PASSED + CORE_PASSED)) +TOTAL_FAILED=$((CI_FAILED + RISK_FAILED + CORE_FAILED)) +TOTAL_WARNED=$((CI_WARNED + RISK_WARNED + CORE_WARNED)) +TOTAL_SKIPPED=$((0 + 0 + CORE_SKIPPED)) + +# Update evidence report +REPORT_CONTENT=$(cat "$EVIDENCE_REPORT") +REPORT_CONTENT=$(echo "$REPORT_CONTENT" | sed "s/__TIMESTAMP__/$(date -Iseconds)/") +REPORT_CONTENT=$(echo "$REPORT_CONTENT" | jq \ + --argjson total "$TOTAL_CHECKS" \ + --argjson passed "$TOTAL_PASSED" \ + --argjson failed "$TOTAL_FAILED" \ + --argjson warned "$TOTAL_WARNED" \ + --argjson skipped "$TOTAL_SKIPPED" \ + '.summary = {"total_checks": $total, "passed": $passed, "failed": $failed, "warnings": $warned, "skipped": $skipped}') + +REPORT_CONTENT=$(echo "$REPORT_CONTENT" | jq --argjson cil "$CI_CHECKLIST" '.ci_pipeline_checklist = $cil') +REPORT_CONTENT=$(echo "$REPORT_CONTENT" | jq --argjson rcl "$RISK_CHECKLIST" '.operational_risks_checklist = $rcl') +REPORT_CONTENT=$(echo "$REPORT_CONTENT" | jq --argjson ct "$CORE_TESTS" '.core_tests = $ct') + +echo "$REPORT_CONTENT" > "$EVIDENCE_REPORT" + +echo "" +echo "=== Evidence Report Summary ===" +echo "Total Checks: $TOTAL_CHECKS" +echo "Passed: $TOTAL_PASSED" +echo "Failed: $TOTAL_FAILED" +echo "Warnings: $TOTAL_WARNED" +echo "Skipped: $TOTAL_SKIPPED" +echo "" +echo "CI Pipeline (4 items): $CI_PASSED passed, $CI_FAILED failed, $CI_WARNED warnings" +echo "Operational Risks (9 items): $RISK_PASSED passed, $RISK_FAILED failed, $RISK_WARNED warnings" +echo "Core Tests (4 items): $CORE_PASSED passed, $CORE_FAILED failed, $CORE_WARNED warnings, $CORE_SKIPPED skipped" +echo "" +echo "Evidence report saved to: $EVIDENCE_REPORT" + +exit 0 diff --git a/verification/run-verification.sh b/verification/run-verification.sh new file mode 100644 index 0000000..e5b8bb2 --- /dev/null +++ b/verification/run-verification.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# Complete Verification Runner +# Runs smoke-test.sh then generate-evidence.sh + +set -e + +echo "==========================================" +echo "Runtime Role Matrix - Verification Suite" +echo "==========================================" +echo "" + +# Step 1: Run smoke tests +echo ">>> Step 1: Running Smoke Tests..." +echo "" +bash verification/smoke-test.sh +SMOKE_EXIT=$? +echo "" + +# Step 2: Generate evidence report +echo ">>> Step 2: Generating Evidence Report..." +echo "" +bash verification/generate-evidence.sh +EVIDENCE_EXIT=$? +echo "" + +# Step 3: Display results +echo "==========================================" +echo "Verification Complete" +echo "==========================================" +echo "" +echo "Output files:" +echo " - verification/smoke-test-report.json" +echo " - verification/evidence-report.json" +echo "" + +# Show evidence report summary if jq available +if command -v jq &>/dev/null; then + echo "Evidence Report Summary:" + jq '.summary' verification/evidence-report.json 2>/dev/null || true + echo "" + echo "CI Pipeline Checklist:" + jq -r '.ci_pipeline_checklist[] | " [\(.status)] \(.description)"' verification/evidence-report.json 2>/dev/null || true + echo "" + echo "Operational Risks Checklist:" + jq -r '.operational_risks_checklist[] | " [\(.status)] \(.description)"' verification/evidence-report.json 2>/dev/null || true +fi + +echo "" + +# Exit with appropriate code +exit $((SMOKE_EXIT || EVIDENCE_EXIT)) diff --git a/verification/smoke-test.sh b/verification/smoke-test.sh new file mode 100644 index 0000000..799bd4e --- /dev/null +++ b/verification/smoke-test.sh @@ -0,0 +1,259 @@ +#!/bin/bash +# Smoke Test Script for Runtime Role Matrix +# Validates: Compilation, Unit Tests, CI Pipeline, Operational Risks + +REPORT_FILE="verification/smoke-test-report.json" + +echo "=== Runtime Role Matrix Smoke Test ===" +echo "Timestamp: $(date -Iseconds)" +echo "" + +# Initialize results array +declare -a RESULTS=() + +# Test result helper +add_result() { + local test_name="$1" + local status="$2" + local message="$3" + RESULTS+=("{\"test\": \"$test_name\", \"status\": \"$status\", \"message\": \"$message\"}") +} + +# CI Pipeline Stage Verification (4 items) +test_ci_pipeline() { + echo "--- CI Pipeline Stage Verification ---" + + # 1. Build stage + if [ -f "pom.xml" ] || [ -f "build.gradle" ]; then + add_result "ci_build_stage" "PASS" "Build configuration exists" + else + add_result "ci_build_stage" "FAIL" "No build configuration found" + fi + + # 2. Test stage + if [ -f "pom.xml" ] && grep -q "maven-surefire-plugin" pom.xml 2>/dev/null; then + add_result "ci_test_stage" "PASS" "Test stage configured" + elif [ -f "build.gradle" ] && grep -q "test" build.gradle 2>/dev/null; then + add_result "ci_test_stage" "PASS" "Test stage configured" + else + add_result "ci_test_stage" "WARN" "Test stage configuration unclear" + fi + + # 3. Package stage + if [ -f "pom.xml" ] && grep -q "jar" pom.xml 2>/dev/null; then + add_result "ci_package_stage" "PASS" "Package stage configured" + else + add_result "ci_package_stage" "WARN" "Package stage configuration unclear" + fi + + # 4. Deploy stage + if [ -f ".github/workflows" ] || [ -f ".gitlab-ci.yml" ] || [ -f "Jenkinsfile" ]; then + add_result "ci_deploy_stage" "PASS" "CI/CD pipeline detected" + else + add_result "ci_deploy_stage" "WARN" "No CI/CD pipeline configuration found" + fi +} + +# Operational Risk Checks (9 items) +test_operational_risks() { + echo "--- Operational Risk Verification ---" + + # 1. Deployment Strategy + if [ -f "deployment.yaml" ] || [ -f "docker-compose.yml" ] || [ -f "helm/" ]; then + add_result "risk_deployment_strategy" "PASS" "Deployment configuration exists" + else + add_result "risk_deployment_strategy" "WARN" "No explicit deployment strategy found" + fi + + # 2. Monitoring + if [ -f "monitoring/prometheus.yml" ] || [ -f "monitoring/grafana.json" ] || grep -rq "prometheus\|grafana\|metrics" . 2>/dev/null; then + add_result "risk_monitoring" "PASS" "Monitoring configuration detected" + else + add_result "risk_monitoring" "WARN" "No monitoring configuration found" + fi + + # 3. Backup + if grep -rq "backup\|restore" . 2>/dev/null; then + add_result "risk_backup" "PASS" "Backup mechanism referenced" + else + add_result "risk_backup" "WARN" "No backup mechanism documented" + fi + + # 4. Secret Management + if [ -f ".env.example" ] || [ -f "secrets.yaml" ] || grep -rq "vault\|secretsmanager\|k8s-secret" . 2>/dev/null; then + add_result "risk_secret_management" "PASS" "Secret management approach detected" + else + add_result "risk_secret_management" "WARN" "No secret management configuration found" + fi + + # 5. Health Check + if grep -rq "health\|liveness\|readiness" . 2>/dev/null; then + add_result "risk_health_check" "PASS" "Health check endpoints defined" + else + add_result "risk_health_check" "WARN" "No health check configuration found" + fi + + # 6. Logging + if grep -rq "logging\|logback\|log4j\|slf4j" . 2>/dev/null; then + add_result "risk_logging" "PASS" "Logging framework configured" + else + add_result "risk_logging" "WARN" "No logging configuration found" + fi + + # 7. Error Handling + if grep -rq "exception\|error\|try-catch" . 2>/dev/null; then + add_result "risk_error_handling" "PASS" "Error handling patterns detected" + else + add_result "risk_error_handling" "WARN" "No explicit error handling found" + fi + + # 8. Rollback Strategy + if grep -rq "rollback\|revert\|undo" . 2>/dev/null; then + add_result "risk_rollback" "PASS" "Rollback strategy documented" + else + add_result "risk_rollback" "WARN" "No rollback strategy found" + fi + + # 9. Graceful Shutdown + if grep -rq "shutdown\|terminate\|destroy\|@PreDestroy" . 2>/dev/null; then + add_result "risk_graceful_shutdown" "PASS" "Graceful shutdown handling detected" + else + add_result "risk_graceful_shutdown" "WARN" "No graceful shutdown handling found" + fi +} + +# Core Functionality Tests +test_compilation() { + echo "--- Test: Compilation ---" + if [ -f "pom.xml" ]; then + if command -v mvn &>/dev/null; then + mvn compile -q 2>/dev/null && add_result "compilation" "PASS" "Maven compilation successful" || add_result "compilation" "FAIL" "Maven compilation failed" + else + add_result "compilation" "SKIP" "Maven not installed" + fi + elif [ -f "build.gradle" ]; then + if command -v gradle &>/dev/null; then + gradle compileJava -q 2>/dev/null && add_result "compilation" "PASS" "Gradle compilation successful" || add_result "compilation" "FAIL" "Gradle compilation failed" + else + add_result "compilation" "SKIP" "Gradle not installed" + fi + else + add_result "compilation" "WARN" "No build configuration found" + fi +} + +test_unit_tests() { + echo "--- Test: Unit Tests ---" + if [ -f "pom.xml" ]; then + if command -v mvn &>/dev/null; then + mvn test -q 2>/dev/null && add_result "unit_tests" "PASS" "Unit tests passed" || add_result "unit_tests" "FAIL" "Unit tests failed" + else + add_result "unit_tests" "SKIP" "Maven not installed" + fi + elif [ -f "build.gradle" ]; then + if command -v gradle &>/dev/null; then + gradle test -q 2>/dev/null && add_result "unit_tests" "PASS" "Unit tests passed" || add_result "unit_tests" "FAIL" "Unit tests failed" + else + add_result "unit_tests" "SKIP" "Gradle not installed" + fi + else + add_result "unit_tests" "WARN" "No build configuration found" + fi +} + +test_role_matrix() { + echo "--- Test: Role Matrix Implementation ---" + if [ -d "src/main/java" ]; then + if grep -rq "Role\|Permission\|Principal" src/main/java 2>/dev/null; then + add_result "role_matrix_impl" "PASS" "Role matrix classes detected" + else + add_result "role_matrix_impl" "WARN" "Role matrix implementation unclear" + fi + else + add_result "role_matrix_impl" "WARN" "Source directory not found" + fi +} + +test_runtime_integration() { + echo "--- Test: Runtime Integration ---" + if grep -rq "runtime\|dynamic\|reflection" . 2>/dev/null; then + add_result "runtime_integration" "PASS" "Runtime integration patterns detected" + else + add_result "runtime_integration" "WARN" "Runtime integration patterns not found" + fi +} + +# Run all tests (without set -e to allow WARN/SKIP handling) +test_ci_pipeline +test_operational_risks +test_compilation +test_unit_tests +test_role_matrix +test_runtime_integration + +# Generate JSON report +echo "" +echo "=== Generating Report ===" + +cat > "$REPORT_FILE" << 'EOF' +{ + "timestamp": "__TIMESTAMP__", + "summary": { + "total": 0, + "passed": 0, + "failed": 0, + "warned": 0, + "skipped": 0 + }, + "results": [] +} +EOF + +# Build results JSON array +RESULTS_JSON="[" +first=true +for r in "${RESULTS[@]}"; do + if [ "$first" = true ]; then + first=false + else + RESULTS_JSON+=", " + fi + RESULTS_JSON+="$r" +done +RESULTS_JSON+="]" + +# Update report with results +REPORT_CONTENT=$(cat "$REPORT_FILE") +REPORT_CONTENT=$(echo "$REPORT_CONTENT" | sed "s/__TIMESTAMP__/$(date -Iseconds)/") +REPORT_CONTENT=$(echo "$REPORT_CONTENT" | jq --argjson results "$RESULTS_JSON" '.results = $results') + +# Calculate summary +TOTAL=$(echo "$RESULTS_JSON" | jq 'length') +PASSED=$(echo "$RESULTS_JSON" | jq '[.[] | select(.status == "PASS")] | length') +FAILED=$(echo "$RESULTS_JSON" | jq '[.[] | select(.status == "FAIL")] | length') +WARNED=$(echo "$RESULTS_JSON" | jq '[.[] | select(.status == "WARN")] | length') +SKIPPED=$(echo "$RESULTS_JSON" | jq '[.[] | select(.status == "SKIP")] | length') + +REPORT_CONTENT=$(echo "$REPORT_CONTENT" | jq \ + --argjson total "$TOTAL" \ + --argjson passed "$PASSED" \ + --argjson failed "$FAILED" \ + --argjson warned "$WARNED" \ + --argjson skipped "$SKIPPED" \ + '.summary = {"total": $total, "passed": $passed, "failed": $failed, "warned": $warned, "skipped": $skipped}') + +echo "$REPORT_CONTENT" > "$REPORT_FILE" + +# Print summary +echo "" +echo "=== Test Summary ===" +echo "Total: $TOTAL" +echo "Passed: $PASSED" +echo "Failed: $FAILED" +echo "Warnings: $WARNED" +echo "Skipped: $SKIPPED" +echo "" +echo "Report saved to: $REPORT_FILE" + +# Exit with appropriate code +exit 0