GeoIntel release gates / Compile, test, contracts and builds (push) Successful in 1m49s
GeoIntel release gates / Python and npm vulnerability policy (push) Successful in 21s
GeoIntel release gates / Production AI image, SBOM and container scan (push) Successful in 5m39s
GeoIntel release gates / Deploy exact gated revision to Unraid (push) Failing after 58m43s
195 lines
7.4 KiB
Bash
195 lines
7.4 KiB
Bash
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
BASE_URL="${1:-http://localhost:1202}"
|
|
TMP_DIR="$(mktemp -d)"
|
|
trap 'rm -rf "${TMP_DIR}"' EXIT
|
|
|
|
if ! command -v curl >/dev/null 2>&1; then
|
|
echo "curl is required for demo raster workflow verification" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ -n "${PYTHON_BIN:-}" ]; then
|
|
PYTHON_BIN="${PYTHON_BIN}"
|
|
else
|
|
PYTHON_BIN=""
|
|
for candidate in python3 python.exe python; do
|
|
if command -v "${candidate}" >/dev/null 2>&1 && "${candidate}" -c "import json, sys" >/dev/null 2>&1; then
|
|
PYTHON_BIN="${candidate}"
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
|
|
if [ -z "${PYTHON_BIN}" ]; then
|
|
echo "A Python interpreter is required for JSON parsing" >&2
|
|
exit 1
|
|
fi
|
|
|
|
json_field() {
|
|
local file_path="$1"
|
|
local expression="$2"
|
|
"${PYTHON_BIN}" - "$file_path" "$expression" <<'PY'
|
|
import json
|
|
import sys
|
|
|
|
path, expression = sys.argv[1], sys.argv[2]
|
|
with open(path, "r", encoding="utf-8") as handle:
|
|
payload = json.load(handle)
|
|
value = payload
|
|
for part in expression.split("."):
|
|
if part:
|
|
value = value[part]
|
|
print(value)
|
|
PY
|
|
}
|
|
|
|
require_json_data() {
|
|
local file_path="$1"
|
|
"${PYTHON_BIN}" - "$file_path" <<'PY'
|
|
import json
|
|
import sys
|
|
|
|
with open(sys.argv[1], "r", encoding="utf-8") as handle:
|
|
payload = json.load(handle)
|
|
if "data" not in payload:
|
|
raise SystemExit("Response is not a canonical GeoIntel data envelope")
|
|
PY
|
|
}
|
|
|
|
echo "== GeoIntel demo raster workflow verification =="
|
|
echo "Base URL: ${BASE_URL}"
|
|
|
|
curl -fsS -X POST "${BASE_URL%/}/api/v1/demo/workflow" > "${TMP_DIR}/demo.json"
|
|
require_json_data "${TMP_DIR}/demo.json"
|
|
project_id="$(json_field "${TMP_DIR}/demo.json" "data.project_id")"
|
|
raster_dataset_id="$(json_field "${TMP_DIR}/demo.json" "data.raster_dataset_id")"
|
|
|
|
if [ -z "${raster_dataset_id}" ] || [ "${raster_dataset_id}" = "None" ] || [ "${raster_dataset_id}" = "null" ]; then
|
|
echo "Demo workflow did not return a raster_dataset_id" >&2
|
|
exit 1
|
|
fi
|
|
|
|
curl -fsS "${BASE_URL%/}/api/v1/projects/${project_id}/datasets" > "${TMP_DIR}/datasets.json"
|
|
require_json_data "${TMP_DIR}/datasets.json"
|
|
"${PYTHON_BIN}" - "${TMP_DIR}/datasets.json" "${raster_dataset_id}" <<'PY'
|
|
import json
|
|
import sys
|
|
|
|
path, raster_id = sys.argv[1], sys.argv[2]
|
|
with open(path, "r", encoding="utf-8") as handle:
|
|
items = json.load(handle)["data"]["items"]
|
|
raster = next((item for item in items if item["id"] == raster_id), None)
|
|
if not raster:
|
|
raise SystemExit("Demo raster dataset is missing from dataset list")
|
|
if raster.get("name") != "demo_context_raster.tif":
|
|
raise SystemExit(f"Unexpected demo raster name: {raster.get('name')}")
|
|
if raster.get("dataset_type") != "raster":
|
|
raise SystemExit(f"Unexpected demo raster dataset_type: {raster.get('dataset_type')}")
|
|
if raster.get("source_name") != "fixture":
|
|
raise SystemExit(f"Unexpected demo raster source_name: {raster.get('source_name')}")
|
|
if raster.get("status") != "ready":
|
|
raise SystemExit(f"Unexpected demo raster status: {raster.get('status')}")
|
|
if raster.get("crs") != "EPSG:4326":
|
|
raise SystemExit(f"Unexpected demo raster CRS: {raster.get('crs')}")
|
|
PY
|
|
|
|
curl -fsS "${BASE_URL%/}/api/v1/projects/${project_id}/datasets/${raster_dataset_id}/raster/inspect" > "${TMP_DIR}/inspect.json"
|
|
require_json_data "${TMP_DIR}/inspect.json"
|
|
"${PYTHON_BIN}" - "${TMP_DIR}/inspect.json" "${raster_dataset_id}" <<'PY'
|
|
import json
|
|
import sys
|
|
|
|
path, raster_id = sys.argv[1], sys.argv[2]
|
|
with open(path, "r", encoding="utf-8") as handle:
|
|
data = json.load(handle)["data"]
|
|
if data.get("dataset_id") != raster_id:
|
|
raise SystemExit("Raster inspect returned the wrong dataset_id")
|
|
if data.get("ready") is not True:
|
|
raise SystemExit("Raster inspect did not report ready=true")
|
|
metadata = data.get("metadata") or {}
|
|
if metadata.get("crs") != "EPSG:4326":
|
|
raise SystemExit(f"Raster inspect metadata CRS drifted: {metadata.get('crs')}")
|
|
if int(metadata.get("width") or 0) < 1 or int(metadata.get("height") or 0) < 1:
|
|
raise SystemExit("Raster inspect metadata does not expose width/height")
|
|
PY
|
|
|
|
curl -fsS "${BASE_URL%/}/api/v1/projects/${project_id}/datasets/${raster_dataset_id}/raster/preview" > "${TMP_DIR}/preview.json"
|
|
require_json_data "${TMP_DIR}/preview.json"
|
|
"${PYTHON_BIN}" - "${TMP_DIR}/preview.json" <<'PY'
|
|
import json
|
|
import sys
|
|
|
|
with open(sys.argv[1], "r", encoding="utf-8") as handle:
|
|
data = json.load(handle)["data"]
|
|
if data.get("ready") is not True:
|
|
raise SystemExit("Raster preview did not report ready=true")
|
|
preview = data.get("preview") or {}
|
|
if str(preview.get("format") or "").lower() != "png":
|
|
raise SystemExit(f"Unexpected preview format: {preview.get('format')}")
|
|
if int(preview.get("width") or 0) < 1 or int(preview.get("height") or 0) < 1:
|
|
raise SystemExit("Raster preview did not expose image dimensions")
|
|
PY
|
|
|
|
curl -fsS "${BASE_URL%/}/api/v1/projects/${project_id}/datasets/${raster_dataset_id}/raster/stats" > "${TMP_DIR}/stats.json"
|
|
require_json_data "${TMP_DIR}/stats.json"
|
|
"${PYTHON_BIN}" - "${TMP_DIR}/stats.json" "${raster_dataset_id}" <<'PY'
|
|
import json
|
|
import sys
|
|
|
|
path, raster_id = sys.argv[1], sys.argv[2]
|
|
with open(path, "r", encoding="utf-8") as handle:
|
|
data = json.load(handle)["data"]
|
|
if data.get("dataset_id") != raster_id:
|
|
raise SystemExit("Raster stats returned the wrong dataset_id")
|
|
bands = data.get("bands") or []
|
|
if not bands:
|
|
raise SystemExit("Raster stats did not report band statistics")
|
|
band = bands[0]
|
|
if band.get("valid_pixel_count", 0) < 1:
|
|
raise SystemExit("Raster stats valid_pixel_count is empty")
|
|
if band.get("min") is None or band.get("max") is None:
|
|
raise SystemExit("Raster stats min/max are missing")
|
|
PY
|
|
|
|
curl -fsS -X POST "${BASE_URL%/}/api/v1/projects/${project_id}/datasets/${raster_dataset_id}/raster/tile" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"tile_size":64,"overlap":0,"output_name":"demo_raster_smoke_tiles"}' > "${TMP_DIR}/tile.json"
|
|
require_json_data "${TMP_DIR}/tile.json"
|
|
"${PYTHON_BIN}" - "${TMP_DIR}/tile.json" "${raster_dataset_id}" <<'PY'
|
|
import json
|
|
import sys
|
|
|
|
path, raster_id = sys.argv[1], sys.argv[2]
|
|
with open(path, "r", encoding="utf-8") as handle:
|
|
job = json.load(handle)["data"]
|
|
if job.get("job_type") != "raster.tile":
|
|
raise SystemExit(f"Unexpected tile job_type: {job.get('job_type')}")
|
|
if job.get("status") not in {"success", "completed"}:
|
|
raise SystemExit(f"Raster tile job did not complete: {job.get('status')}")
|
|
result = job.get("result_json") or {}
|
|
if result.get("dataset_id") != raster_id:
|
|
raise SystemExit("Raster tile result returned the wrong dataset_id")
|
|
if result.get("ready") is not True:
|
|
raise SystemExit("Raster tile result did not report ready=true")
|
|
if result.get("operation") != "raster.tile":
|
|
raise SystemExit(f"Unexpected raster tile operation: {result.get('operation')}")
|
|
if not result.get("manifest_path"):
|
|
raise SystemExit("Raster tile result is missing manifest_path")
|
|
manifest = result.get("manifest") or {}
|
|
tile_paths = manifest.get("tile_paths") or []
|
|
tiles = manifest.get("tiles") or []
|
|
if result.get("count") != len(tile_paths) or len(tile_paths) != len(tiles):
|
|
raise SystemExit("Raster tile manifest count does not match tile_paths/tiles")
|
|
if not tile_paths:
|
|
raise SystemExit("Raster tile manifest did not include any tile paths")
|
|
if manifest.get("source_dataset_id") != raster_id:
|
|
raise SystemExit("Raster tile manifest source_dataset_id drifted")
|
|
PY
|
|
|
|
echo "Demo raster workflow verification passed"
|
|
echo "Project: ${project_id}"
|
|
echo "Raster dataset: ${raster_dataset_id}"
|
|
echo "Operations: inspect, preview, stats and raster.tile"
|