123 lines
4.6 KiB
Bash
Executable File
123 lines
4.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# Prepare Export Center handoff metadata for mirror thin bundles and optionally schedule a run.
|
|
# Usage (handoff only):
|
|
# scripts/mirror/export-center-wire.sh
|
|
# Usage (handoff + schedule when secrets exist):
|
|
# EXPORT_CENTER_BASE_URL=https://export.example.com \
|
|
# EXPORT_CENTER_TOKEN=token123 \
|
|
# EXPORT_CENTER_TENANT=tenant-a \
|
|
# EXPORT_CENTER_AUTO_SCHEDULE=1 \
|
|
# scripts/mirror/export-center-wire.sh
|
|
# Inputs:
|
|
# - MILESTONE_PATH: path to milestone.json (default: out/mirror/thin/milestone.json)
|
|
# - EXPORT_CENTER_OUT_DIR: output directory for handoff files (default: out/mirror/thin/export-center)
|
|
# - EXPORT_CENTER_PROFILE_ID: profile identifier for the Export Center run (default: mirror:thin)
|
|
# - EXPORT_CENTER_TARGETS_JSON: override targets array sent to Export Center (JSON array string)
|
|
# - EXPORT_CENTER_FORMATS_JSON: override formats array (JSON array string; default: ["tar.gz","json","dsse"])
|
|
# - EXPORT_CENTER_AUTO_SCHEDULE: when "1", schedule a run using schedule-export-center-run.sh
|
|
# - EXPORT_CENTER_BASE_URL / EXPORT_CENTER_TENANT / EXPORT_CENTER_PROJECT / EXPORT_CENTER_TOKEN: forwarded to scheduler
|
|
# - EXPORT_CENTER_AUDIT_LOG: optional override for scheduler audit log path
|
|
|
|
MILESTONE_PATH="${MILESTONE_PATH:-out/mirror/thin/milestone.json}"
|
|
OUT_DIR="${EXPORT_CENTER_OUT_DIR:-out/mirror/thin/export-center}"
|
|
PROFILE_ID="${EXPORT_CENTER_PROFILE_ID:-mirror:thin}"
|
|
FORMATS_JSON="${EXPORT_CENTER_FORMATS_JSON:-[\"tar.gz\",\"json\",\"dsse\"]}"
|
|
AUTO_SCHEDULE="${EXPORT_CENTER_AUTO_SCHEDULE:-0}"
|
|
|
|
HANDOFF_PATH="${OUT_DIR}/export-center-handoff.json"
|
|
TARGETS_PATH="${OUT_DIR}/export-center-targets.json"
|
|
RESPONSE_PATH="${OUT_DIR}/schedule-response.json"
|
|
|
|
export HANDOFF_PATH TARGETS_PATH RESPONSE_PATH PROFILE_ID MILESTONE_PATH
|
|
|
|
mkdir -p "${OUT_DIR}"
|
|
|
|
PROFILE_ID="${PROFILE_ID}" MILESTONE_PATH="${MILESTONE_PATH}" HANDOFF_PATH="${HANDOFF_PATH}" TARGETS_PATH="${TARGETS_PATH}" python3 - <<'PY'
|
|
import datetime
|
|
import json
|
|
import os
|
|
import sys
|
|
from typing import Dict, Any
|
|
|
|
milestone_path = os.environ["MILESTONE_PATH"]
|
|
handoff_path = os.environ["HANDOFF_PATH"]
|
|
targets_path = os.environ["TARGETS_PATH"]
|
|
profile = os.environ.get("PROFILE_ID", "mirror:thin")
|
|
|
|
try:
|
|
with open(milestone_path, encoding="utf-8") as f:
|
|
milestone = json.load(f)
|
|
except FileNotFoundError:
|
|
print(f"milestone file not found: {milestone_path}", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
artifacts = []
|
|
|
|
def add_artifact(name: str, entry: Dict[str, Any] | None) -> None:
|
|
if not isinstance(entry, dict):
|
|
return
|
|
path = entry.get("path")
|
|
sha = entry.get("sha256")
|
|
if path and sha:
|
|
artifacts.append({"name": name, "path": path, "sha256": sha})
|
|
|
|
add_artifact("manifest", milestone.get("manifest"))
|
|
add_artifact("manifest_dsse", milestone.get("dsse"))
|
|
add_artifact("bundle", milestone.get("tarball"))
|
|
add_artifact("bundle_meta", milestone.get("bundle"))
|
|
add_artifact("bundle_meta_dsse", milestone.get("bundle_dsse"))
|
|
add_artifact("time_anchor", milestone.get("time_anchor"))
|
|
|
|
for name, entry in sorted((milestone.get("policies") or {}).items()):
|
|
add_artifact(f"policy_{name}", entry)
|
|
|
|
handoff = {
|
|
"profileId": profile,
|
|
"generatedAt": datetime.datetime.now(datetime.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z"),
|
|
"sourceMilestone": os.path.abspath(milestone_path),
|
|
"artifacts": artifacts,
|
|
}
|
|
|
|
with open(handoff_path, "w", encoding="utf-8") as f:
|
|
json.dump(handoff, f, indent=2)
|
|
|
|
with open(targets_path, "w", encoding="utf-8") as f:
|
|
json.dump([a["name"] for a in artifacts], f)
|
|
PY
|
|
|
|
ARTIFACTS_JSON=$(python3 - <<'PY'
|
|
import json
|
|
import os
|
|
with open(os.environ["HANDOFF_PATH"], encoding="utf-8") as f:
|
|
data = json.load(f)
|
|
print(json.dumps(data.get("artifacts", [])))
|
|
PY
|
|
)
|
|
ARTIFACTS_JSON="${ARTIFACTS_JSON//$'\n'/}"
|
|
|
|
TARGETS_JSON_DEFAULT=$(tr -d '\r\n' < "${TARGETS_PATH}")
|
|
TARGETS_JSON="${EXPORT_CENTER_TARGETS_JSON:-$TARGETS_JSON_DEFAULT}"
|
|
|
|
echo "[info] Export Center handoff written to ${HANDOFF_PATH}"
|
|
echo "[info] Recommended targets: ${TARGETS_JSON}"
|
|
|
|
schedule_note="AUTO_SCHEDULE=0"
|
|
if [[ "${AUTO_SCHEDULE}" == "1" ]]; then
|
|
schedule_note="missing EXPORT_CENTER_BASE_URL"
|
|
if [[ -n "${EXPORT_CENTER_BASE_URL:-}" ]]; then
|
|
export EXPORT_CENTER_ARTIFACTS_JSON="${ARTIFACTS_JSON}"
|
|
schedule_note="scheduled"
|
|
bash src/Mirror/StellaOps.Mirror.Creator/schedule-export-center-run.sh "${PROFILE_ID}" "${TARGETS_JSON}" "${FORMATS_JSON}" | tee "${RESPONSE_PATH}"
|
|
fi
|
|
fi
|
|
|
|
if [[ ! -f "${RESPONSE_PATH}" ]]; then
|
|
cat > "${RESPONSE_PATH}" <<JSON
|
|
{"scheduled": false, "reason": "${schedule_note}"}
|
|
JSON
|
|
fi
|
|
|
|
echo "[info] Scheduler response captured at ${RESPONSE_PATH}"
|