#!/usr/bin/env bash set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$ROOT" KEEP_LATEST="${KEEP_LATEST:-10}" MAX_DELETE="${MAX_DELETE:-100}" EXPORT_TYPE="${EXPORT_TYPE:-project_report_html}" CLEANUP_MODE="${CLEANUP_MODE:-auto}" CLEANUP_CONTAINER="${CLEANUP_CONTAINER:-geointel}" cleanup_args=( "--keep-latest" "${KEEP_LATEST}" "--max-delete" "${MAX_DELETE}" "--export-type" "${EXPORT_TYPE}" ) run_cleanup() { case "${CLEANUP_MODE}" in local) python scripts/cleanup_demo_artifacts.py "${cleanup_args[@]}" ;; compose) docker compose exec -T backend python scripts/cleanup_demo_artifacts.py "${cleanup_args[@]}" ;; container) docker exec "${CLEANUP_CONTAINER}" /opt/geointel/venv/bin/python /app/scripts/cleanup_demo_artifacts.py "${cleanup_args[@]}" ;; auto) if command -v docker >/dev/null 2>&1 && docker compose ps --services --filter status=running 2>/dev/null | grep -qx "backend"; then docker compose exec -T backend python scripts/cleanup_demo_artifacts.py "${cleanup_args[@]}" elif command -v docker >/dev/null 2>&1 && docker ps --format '{{.Names}}' | grep -qx "${CLEANUP_CONTAINER}"; then docker exec "${CLEANUP_CONTAINER}" /opt/geointel/venv/bin/python /app/scripts/cleanup_demo_artifacts.py "${cleanup_args[@]}" else cat >&2 <&2 return 1 ;; esac } tmp_output="$(mktemp)" trap 'rm -f "${tmp_output}"' EXIT run_cleanup | tee "${tmp_output}" >/dev/null python - "${tmp_output}" "${KEEP_LATEST}" "${MAX_DELETE}" "${EXPORT_TYPE}" <<'PY' from __future__ import annotations import json import sys from pathlib import Path output_path = Path(sys.argv[1]) expected_keep_latest = int(sys.argv[2]) expected_max_delete = int(sys.argv[3]) expected_export_type = sys.argv[4] summary = json.loads(output_path.read_text(encoding="utf-8")) if summary.get("dry_run") is not True: raise SystemExit("cleanup smoke expected dry_run=true") if summary.get("deleted_export_count") != 0: raise SystemExit("cleanup smoke expected deleted_export_count=0") if summary.get("deleted_files") != []: raise SystemExit("cleanup smoke expected deleted_files=[]") if summary.get("keep_latest") != expected_keep_latest: raise SystemExit("cleanup smoke keep_latest drifted") if summary.get("max_delete") != expected_max_delete: raise SystemExit("cleanup smoke max_delete drifted") if summary.get("export_types") != [expected_export_type]: raise SystemExit("cleanup smoke export_types drifted") if "candidate_exports" not in summary: raise SystemExit("cleanup smoke expected candidate_exports in dry-run output") if "candidate_files" not in summary: raise SystemExit("cleanup smoke expected candidate_files in dry-run output") if "matched_export_count" not in summary: raise SystemExit("cleanup smoke expected matched_export_count in dry-run output") if "selected_export_count" not in summary: raise SystemExit("cleanup smoke expected selected_export_count in dry-run output") print( "Demo cleanup dry-run smoke passed: " f"matched={summary.get('matched_export_count')} " f"type_filtered={summary.get('type_filtered_export_count')} " f"selected={summary.get('selected_export_count')} " f"deleted={summary.get('deleted_export_count')}" ) PY