generated from coulomb/repo-seed
Add guide-board pilot ingestion
This commit is contained in:
133
scripts/link-guide-board-package.py
Normal file
133
scripts/link-guide-board-package.py
Normal file
@@ -0,0 +1,133 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Record guide-board artifact package linkage in State Hub."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import urllib.error
|
||||
import urllib.request
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
|
||||
def main() -> None:
|
||||
state_hub_url = _env("STATE_HUB_URL", "http://127.0.0.1:8000").rstrip("/")
|
||||
artifact_api_url = _env("ARTIFACTSTORE_API_URL", "http://127.0.0.1:8000").rstrip("/")
|
||||
run_dir = Path(_required("GUIDE_BOARD_RUN_DIR"))
|
||||
run_json = _read_json(run_dir / "run.json")
|
||||
retention_summary = _read_json(run_dir / "retention-summary.json")
|
||||
ingest_result = _ingest_result()
|
||||
|
||||
package_id = _env("ARTIFACTSTORE_PACKAGE_ID") or _required_from(
|
||||
ingest_result,
|
||||
"package_id",
|
||||
"ARTIFACTSTORE_PACKAGE_ID",
|
||||
)
|
||||
manifest_digest = _env("ARTIFACTSTORE_MANIFEST_DIGEST") or _required_from(
|
||||
ingest_result,
|
||||
"manifest_digest",
|
||||
"ARTIFACTSTORE_MANIFEST_DIGEST",
|
||||
)
|
||||
run_id = _env("GUIDE_BOARD_RUN_ID") or str(
|
||||
run_json.get("run_id") or run_json.get("id") or retention_summary.get("run_id")
|
||||
)
|
||||
summary = retention_summary.get("summary", {})
|
||||
if not isinstance(summary, dict):
|
||||
summary = {}
|
||||
result_status = _env("GUIDE_BOARD_RESULT_STATUS") or str(
|
||||
run_json.get("result_status") or run_json.get("status") or summary.get("status")
|
||||
)
|
||||
|
||||
detail: dict[str, Any] = {
|
||||
"producer": "guide-board",
|
||||
"artifact_store_api_url": artifact_api_url,
|
||||
"run_dir": str(run_dir),
|
||||
"run_id": run_id,
|
||||
"target_profile_ref": str(run_json["target_profile_ref"]),
|
||||
"assessment_profile_ref": str(run_json["assessment_profile_ref"]),
|
||||
"result_status": result_status,
|
||||
"package_id": package_id,
|
||||
"manifest_digest": manifest_digest,
|
||||
}
|
||||
if "file_count" in ingest_result:
|
||||
detail["file_count"] = ingest_result["file_count"]
|
||||
retention_class = _env("ARTIFACTSTORE_RETENTION_CLASS")
|
||||
if retention_class:
|
||||
detail["retention_class"] = retention_class
|
||||
|
||||
payload: dict[str, Any] = {
|
||||
"event_type": _env("STATE_HUB_EVENT_TYPE", "artifact_link"),
|
||||
"author": _env("STATE_HUB_AUTHOR", "artifact-store"),
|
||||
"summary": _env(
|
||||
"STATE_HUB_SUMMARY",
|
||||
f"guide-board run {run_id} artifacts stored in artifact-store package {package_id}",
|
||||
),
|
||||
"detail": detail,
|
||||
}
|
||||
for field, env_name in (
|
||||
("topic_id", "STATE_HUB_TOPIC_ID"),
|
||||
("workstream_id", "STATE_HUB_WORKSTREAM_ID"),
|
||||
("task_id", "STATE_HUB_TASK_ID"),
|
||||
("session_id", "STATE_HUB_SESSION_ID"),
|
||||
):
|
||||
value = _env(env_name)
|
||||
if value:
|
||||
payload[field] = value
|
||||
|
||||
request = urllib.request.Request(
|
||||
f"{state_hub_url}/progress/",
|
||||
data=json.dumps(payload).encode("utf-8"),
|
||||
headers={"Content-Type": "application/json", "Accept": "application/json"},
|
||||
method="POST",
|
||||
)
|
||||
try:
|
||||
with urllib.request.urlopen(request, timeout=30) as response:
|
||||
print(response.read().decode("utf-8"))
|
||||
except urllib.error.HTTPError as exc:
|
||||
detail_text = exc.read().decode("utf-8", errors="replace")
|
||||
raise SystemExit(f"HTTP {exc.code}: {detail_text}") from exc
|
||||
|
||||
|
||||
def _env(name: str, default: str = "") -> str:
|
||||
return os.environ.get(name, default)
|
||||
|
||||
|
||||
def _required(name: str) -> str:
|
||||
value = _env(name)
|
||||
if not value:
|
||||
raise SystemExit(f"missing required environment variable: {name}")
|
||||
return value
|
||||
|
||||
|
||||
def _required_from(payload: dict[str, Any], key: str, env_name: str) -> str:
|
||||
value = payload.get(key)
|
||||
if isinstance(value, str) and value:
|
||||
return value
|
||||
raise SystemExit(f"missing {key!r}; set {env_name} or ARTIFACTSTORE_INGEST_RESULT_PATH")
|
||||
|
||||
|
||||
def _ingest_result() -> dict[str, Any]:
|
||||
raw_json = _env("ARTIFACTSTORE_INGEST_RESULT_JSON")
|
||||
if raw_json:
|
||||
payload = json.loads(raw_json)
|
||||
if not isinstance(payload, dict):
|
||||
raise SystemExit("ARTIFACTSTORE_INGEST_RESULT_JSON must be a JSON object")
|
||||
return payload
|
||||
|
||||
result_path = _env("ARTIFACTSTORE_INGEST_RESULT_PATH")
|
||||
if result_path:
|
||||
return _read_json(Path(result_path))
|
||||
return {}
|
||||
|
||||
|
||||
def _read_json(path: Path) -> dict[str, Any]:
|
||||
with path.open("r", encoding="utf-8") as fh:
|
||||
payload = json.load(fh)
|
||||
if not isinstance(payload, dict):
|
||||
raise SystemExit(f"{path} must contain a JSON object")
|
||||
return payload
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
44
scripts/register-guide-board-schema.py
Normal file
44
scripts/register-guide-board-schema.py
Normal file
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Register the guide-board pilot metadata schema through the HTTP API."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import urllib.error
|
||||
import urllib.request
|
||||
from pathlib import Path
|
||||
|
||||
SCHEMA_SLUG = "guide-board.run.v1"
|
||||
|
||||
|
||||
def main() -> None:
|
||||
api_url = os.environ.get("ARTIFACTSTORE_API_URL", "http://127.0.0.1:8000").rstrip("/")
|
||||
token = os.environ["ARTIFACTSTORE_API_TOKEN"]
|
||||
schema_path = Path(
|
||||
os.environ.get("ARTIFACTSTORE_GUIDE_BOARD_SCHEMA", "schemas/guide-board.run.v1.json")
|
||||
)
|
||||
payload = {
|
||||
"slug": SCHEMA_SLUG,
|
||||
"json_schema": json.loads(schema_path.read_text(encoding="utf-8")),
|
||||
}
|
||||
request = urllib.request.Request(
|
||||
f"{api_url}/metadata-schemas",
|
||||
data=json.dumps(payload).encode(),
|
||||
headers={
|
||||
"Authorization": f"Bearer {token}",
|
||||
"Content-Type": "application/json",
|
||||
"Accept": "application/json",
|
||||
},
|
||||
method="POST",
|
||||
)
|
||||
try:
|
||||
with urllib.request.urlopen(request, timeout=30) as response:
|
||||
print(response.read().decode("utf-8"))
|
||||
except urllib.error.HTTPError as exc:
|
||||
detail = exc.read().decode("utf-8", errors="replace")
|
||||
raise SystemExit(f"HTTP {exc.code}: {detail}") from exc
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user