Initial public release
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
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
This commit is contained in:
@@ -0,0 +1,170 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
BASE_URL="${1:-${GE_INTEL_BASE_URL:-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 workbench interaction 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
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
echo "== GeoIntel workbench interaction backing-state 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")"
|
||||
area_id="$(json_field "${TMP_DIR}/demo.json" "data.area_id")"
|
||||
candidate_dataset_id="$(json_field "${TMP_DIR}/demo.json" "data.candidate_dataset_id")"
|
||||
reference_dataset_id="$(json_field "${TMP_DIR}/demo.json" "data.reference_dataset_id")"
|
||||
raster_dataset_id="$(json_field "${TMP_DIR}/demo.json" "data.raster_dataset_id")"
|
||||
quality_check_id="$(json_field "${TMP_DIR}/demo.json" "data.quality_check_id")"
|
||||
|
||||
curl -fsS "${BASE_URL%/}/api/v1/projects" > "${TMP_DIR}/projects.json"
|
||||
require_json_data "${TMP_DIR}/projects.json"
|
||||
curl -fsS "${BASE_URL%/}/api/v1/projects/${project_id}/areas" > "${TMP_DIR}/areas.json"
|
||||
require_json_data "${TMP_DIR}/areas.json"
|
||||
curl -fsS "${BASE_URL%/}/api/v1/projects/${project_id}/datasets" > "${TMP_DIR}/datasets.json"
|
||||
require_json_data "${TMP_DIR}/datasets.json"
|
||||
curl -fsS "${BASE_URL%/}/api/v1/projects/${project_id}/quality-checks" > "${TMP_DIR}/quality_checks.json"
|
||||
require_json_data "${TMP_DIR}/quality_checks.json"
|
||||
|
||||
"${PYTHON_BIN}" - \
|
||||
"${TMP_DIR}/projects.json" \
|
||||
"${TMP_DIR}/areas.json" \
|
||||
"${TMP_DIR}/datasets.json" \
|
||||
"${TMP_DIR}/quality_checks.json" \
|
||||
"${project_id}" \
|
||||
"${area_id}" \
|
||||
"${candidate_dataset_id}" \
|
||||
"${reference_dataset_id}" \
|
||||
"${raster_dataset_id}" \
|
||||
"${quality_check_id}" <<'PY'
|
||||
import json
|
||||
import sys
|
||||
|
||||
projects_path, areas_path, datasets_path, quality_path = sys.argv[1:5]
|
||||
project_id, area_id, candidate_id, reference_id, raster_id, quality_check_id = sys.argv[5:11]
|
||||
|
||||
def load(path):
|
||||
with open(path, "r", encoding="utf-8") as handle:
|
||||
return json.load(handle)["data"]["items"]
|
||||
|
||||
projects = load(projects_path)
|
||||
areas = load(areas_path)
|
||||
datasets = load(datasets_path)
|
||||
checks = load(quality_path)
|
||||
|
||||
project = next((item for item in projects if item["id"] == project_id), None)
|
||||
if not project or project.get("name") != "GeoIntel Demo - Building QA":
|
||||
raise SystemExit("Project switch backing state is missing the demo project")
|
||||
|
||||
area = next((item for item in areas if item["id"] == area_id), None)
|
||||
if not area or area.get("name") != "Demo AOI - Geel buildings":
|
||||
raise SystemExit("Area selection backing state is missing the demo AOI")
|
||||
if not area.get("geometry"):
|
||||
raise SystemExit("Area selection backing state has no map geometry")
|
||||
|
||||
dataset_ids = {item["id"]: item for item in datasets}
|
||||
candidate = dataset_ids.get(candidate_id)
|
||||
reference = dataset_ids.get(reference_id)
|
||||
raster = dataset_ids.get(raster_id)
|
||||
if not candidate:
|
||||
raise SystemExit("candidate dataset backing state is missing")
|
||||
if not reference:
|
||||
raise SystemExit("reference dataset backing state is missing")
|
||||
if not raster:
|
||||
raise SystemExit("raster dataset backing state is missing")
|
||||
if candidate.get("status") != "ready" or reference.get("status") != "ready" or raster.get("status") != "ready":
|
||||
raise SystemExit("Dataset selection backing state is not 3/3 ready")
|
||||
if reference.get("dataset_role") != "reference":
|
||||
raise SystemExit("reference dataset backing state lost its reference role")
|
||||
if raster.get("dataset_type") != "raster" or raster.get("source_name") != "fixture":
|
||||
raise SystemExit("raster dataset backing state lost its fixture raster metadata")
|
||||
|
||||
quality_check = next((item for item in checks if item["id"] == quality_check_id), None)
|
||||
if not quality_check or quality_check.get("status") != "ok":
|
||||
raise SystemExit("QA refresh backing state is missing the seeded ok quality check")
|
||||
metric_keys = {metric["metric_key"] for metric in quality_check.get("metrics", [])}
|
||||
if not {"precision", "recall", "f1", "mean_iou"}.issubset(metric_keys):
|
||||
raise SystemExit("QA refresh backing state is missing core metrics")
|
||||
PY
|
||||
|
||||
curl -fsS -X POST "${BASE_URL%/}/api/v1/exports/metadata" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"project_id\":\"${project_id}\"}" > "${TMP_DIR}/metadata_export.json"
|
||||
require_json_data "${TMP_DIR}/metadata_export.json"
|
||||
metadata_export_id="$(json_field "${TMP_DIR}/metadata_export.json" "data.export_id")"
|
||||
|
||||
curl -fsS "${BASE_URL%/}/api/v1/exports/projects/${project_id}/exports" > "${TMP_DIR}/exports.json"
|
||||
require_json_data "${TMP_DIR}/exports.json"
|
||||
"${PYTHON_BIN}" - "${TMP_DIR}/exports.json" "${metadata_export_id}" <<'PY'
|
||||
import json
|
||||
import sys
|
||||
|
||||
path, export_id = sys.argv[1], sys.argv[2]
|
||||
with open(path, "r", encoding="utf-8") as handle:
|
||||
items = json.load(handle)["data"]["items"]
|
||||
export = next((item for item in items if item["id"] == export_id), None)
|
||||
if not export:
|
||||
raise SystemExit("Export refresh backing state does not list the new metadata export")
|
||||
if export.get("export_type") != "project_metadata_json":
|
||||
raise SystemExit(f"Unexpected export type: {export.get('export_type')}")
|
||||
PY
|
||||
|
||||
echo "Workbench interaction backing-state verification passed"
|
||||
echo "Project switch: GeoIntel Demo - Building QA"
|
||||
echo "Area selection: Demo AOI - Geel buildings"
|
||||
echo "Dataset selection: candidate, reference and raster fixture datasets ready"
|
||||
echo "QA refresh: seeded metrics available"
|
||||
echo "Export refresh: metadata export listed"
|
||||
Reference in New Issue
Block a user