#!/usr/bin/env bash # Shared machine-readable run summary helper for wrapper scripts. # Usage: # source scripts/lib/run-summary.sh # run_summary_init "" "$RUN_STARTED_AT" "${JSON_OUT:-}" # run_summary_record_step "1" "Config validation" "success" "12" # run_summary_write "$RUN_STATUS" "$SECONDS" "$RUN_MODE" set -euo pipefail RUN_SUMMARY_TMP="" RUN_SUMMARY_SCRIPT_NAME="" RUN_SUMMARY_STARTED_AT="" RUN_SUMMARY_JSON_OUT="" run_summary_init() { RUN_SUMMARY_SCRIPT_NAME="$1" RUN_SUMMARY_STARTED_AT="$2" RUN_SUMMARY_JSON_OUT="${3:-}" if [[ -n "$RUN_SUMMARY_JSON_OUT" ]]; then RUN_SUMMARY_TMP="$(mktemp)" fi } run_summary_record_step() { local step_number="$1" local step_name="$2" local step_status="$3" local duration_seconds="$4" if [[ -z "$RUN_SUMMARY_JSON_OUT" ]]; then return 0 fi printf '%s\t%s\t%s\t%s\n' \ "$step_number" \ "$step_name" \ "$step_status" \ "$duration_seconds" >> "$RUN_SUMMARY_TMP" } run_summary_write() { local overall_status="$1" local total_elapsed_seconds="$2" local run_mode="${3:-run}" if [[ -z "$RUN_SUMMARY_JSON_OUT" ]]; then return 0 fi mkdir -p "$(dirname "$RUN_SUMMARY_JSON_OUT")" python3 - "$RUN_SUMMARY_TMP" "$RUN_SUMMARY_JSON_OUT" "$RUN_SUMMARY_SCRIPT_NAME" "$RUN_SUMMARY_STARTED_AT" "$overall_status" "$total_elapsed_seconds" "$run_mode" <<'PY' import json import sys from pathlib import Path tmp_path = Path(sys.argv[1]) json_out = Path(sys.argv[2]) script_name = sys.argv[3] started_at = sys.argv[4] overall_status = sys.argv[5] total_elapsed_seconds = int(sys.argv[6]) run_mode = sys.argv[7] steps = [] if tmp_path.exists(): for raw_line in tmp_path.read_text(encoding="utf-8").splitlines(): if not raw_line.strip(): continue number, name, status, duration_seconds = raw_line.split("\t", 3) steps.append( { "step": number, "name": name, "status": status, "duration_seconds": int(duration_seconds), } ) payload = { "script": script_name, "started_at_utc": started_at, "overall_status": overall_status, "run_mode": run_mode, "total_elapsed_seconds": total_elapsed_seconds, "steps": steps, } json_out.write_text(json.dumps(payload, indent=2) + "\n", encoding="utf-8") PY } run_summary_cleanup() { if [[ -n "$RUN_SUMMARY_TMP" && -f "$RUN_SUMMARY_TMP" ]]; then rm -f "$RUN_SUMMARY_TMP" fi }