feat: add ops center and node onboarding flow
This commit is contained in:
182
domain-api/deploy/multi-region/check_go_live_signoff.sh
Normal file
182
domain-api/deploy/multi-region/check_go_live_signoff.sh
Normal file
@@ -0,0 +1,182 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck disable=SC1091
|
||||
source "${SCRIPT_DIR}/lib_ops_center.sh"
|
||||
ops_center_load_config "${SCRIPT_DIR}"
|
||||
|
||||
TARGET_OR_BASE_URL="${1:-}"
|
||||
SECOND_ARG="${2:-}"
|
||||
|
||||
REPORT_DIR=""
|
||||
MANIFEST_PATH=""
|
||||
GENERATED_BUNDLE="false"
|
||||
MAINLAND_BASE_URL=""
|
||||
OVERSEAS_BASE_URL=""
|
||||
|
||||
if [[ -n "${TARGET_OR_BASE_URL}" && ( -f "${TARGET_OR_BASE_URL}" || -d "${TARGET_OR_BASE_URL}" ) ]]; then
|
||||
if [[ -d "${TARGET_OR_BASE_URL}" ]]; then
|
||||
REPORT_DIR="${TARGET_OR_BASE_URL%/}"
|
||||
MANIFEST_PATH="${REPORT_DIR}/manifest.json"
|
||||
else
|
||||
MANIFEST_PATH="${TARGET_OR_BASE_URL}"
|
||||
REPORT_DIR="$(cd "$(dirname "${MANIFEST_PATH}")" && pwd)"
|
||||
fi
|
||||
else
|
||||
MAINLAND_BASE_URL="${TARGET_OR_BASE_URL:-$(ops_center_resolve_mainland_api_base_url)}"
|
||||
OVERSEAS_BASE_URL="$(normalize_optional_base_url_arg "${SECOND_ARG:-}" "$(ops_center_resolve_overseas_api_base_url)")"
|
||||
REPORT_DIR="${OPS_CENTER_REPORT_ROOT}/go-live-bundles/go-live-signoff-$(timestamp_now)"
|
||||
ops_center_ensure_report_dir "${REPORT_DIR}"
|
||||
bash "${SCRIPT_DIR}/export_go_live_bundle.sh" "${REPORT_DIR}" "${MAINLAND_BASE_URL}" "${OVERSEAS_BASE_URL}" >/dev/null
|
||||
MANIFEST_PATH="${REPORT_DIR}/manifest.json"
|
||||
GENERATED_BUNDLE="true"
|
||||
fi
|
||||
|
||||
if [[ ! -f "${MANIFEST_PATH}" ]]; then
|
||||
echo "manifest not found: ${MANIFEST_PATH}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
REVIEW_JSON="$(bash "${SCRIPT_DIR}/review_go_live_bundle.sh" "${MANIFEST_PATH}")"
|
||||
DOCTOR_JSON="$(bash "${SCRIPT_DIR}/drive_ops_center.sh" doctor-decision "${MANIFEST_PATH}")"
|
||||
|
||||
python3 - <<'PY' \
|
||||
"${REVIEW_JSON}" \
|
||||
"${DOCTOR_JSON}" \
|
||||
"${GENERATED_BUNDLE}" \
|
||||
"${REPORT_DIR}" \
|
||||
"${MANIFEST_PATH}" \
|
||||
"${MAINLAND_BASE_URL}" \
|
||||
"${OVERSEAS_BASE_URL}"
|
||||
import json
|
||||
import sys
|
||||
|
||||
review = json.loads(sys.argv[1])
|
||||
doctor = json.loads(sys.argv[2])
|
||||
generated_bundle = str(sys.argv[3]).strip().lower() == "true"
|
||||
report_dir = str(sys.argv[4] or "").strip()
|
||||
manifest_path = str(sys.argv[5] or "").strip()
|
||||
mainland_base_url = str(sys.argv[6] or "").strip()
|
||||
overseas_base_url = str(sys.argv[7] or "").strip()
|
||||
|
||||
go_live_summary = dict(review.get("go_live_summary") or {})
|
||||
stack_diagnosis = dict(review.get("stack_diagnosis") or {})
|
||||
driver_feed = dict(review.get("driver_feed") or {})
|
||||
codex_brief = dict(review.get("codex_brief") or {})
|
||||
launchpad_alignment = dict(review.get("launchpad_alignment") or {})
|
||||
doctor_decision = dict(doctor.get("decision") or {})
|
||||
doctor_summary = dict(doctor.get("summary") or {})
|
||||
|
||||
review_status = str(review.get("status") or "").strip()
|
||||
doctor_status = str(doctor_decision.get("status") or "").strip()
|
||||
go_live_status = str(go_live_summary.get("go_live_status") or "").strip()
|
||||
publish_status = str(go_live_summary.get("publish_status") or "").strip()
|
||||
stack_status = str(stack_diagnosis.get("stack_status") or "").strip()
|
||||
driver_launch_status = str(driver_feed.get("launch_status") or "").strip()
|
||||
codex_launch_status = str(codex_brief.get("launch_status") or "").strip()
|
||||
|
||||
|
||||
def dedupe_commands(values):
|
||||
result = []
|
||||
seen = set()
|
||||
for item in values:
|
||||
text = str(item or "").strip()
|
||||
if not text or text in seen:
|
||||
continue
|
||||
seen.add(text)
|
||||
result.append(text)
|
||||
return result
|
||||
|
||||
|
||||
blocked_reasons = dedupe_commands(
|
||||
[]
|
||||
+ ([f"review:{review_status}"] if review_status == "blocked" else [])
|
||||
+ ([f"doctor:{doctor_status}"] if doctor_status == "blocked" else [])
|
||||
+ ([f"go_live:{go_live_status}"] if go_live_status == "blocked" else [])
|
||||
+ ([f"publish:{publish_status}"] if publish_status == "blocked" else [])
|
||||
+ ([f"stack:{stack_status}"] if stack_status == "blocked" else [])
|
||||
+ ([f"driver_launch:{driver_launch_status}"] if driver_launch_status == "blocked" else [])
|
||||
+ ([f"codex_launch:{codex_launch_status}"] if codex_launch_status == "blocked" else [])
|
||||
)
|
||||
|
||||
attention_reasons = dedupe_commands(
|
||||
[]
|
||||
+ ([f"review:{review_status}"] if review_status == "attention" else [])
|
||||
+ ([f"doctor:{doctor_status}"] if doctor_status == "attention" else [])
|
||||
+ ([f"go_live:{go_live_status}"] if go_live_status == "attention" else [])
|
||||
+ ([f"publish:{publish_status}"] if publish_status == "attention" else [])
|
||||
+ ([f"stack:{stack_status}"] if stack_status == "attention" else [])
|
||||
+ ([f"driver_launch:{driver_launch_status}"] if driver_launch_status == "attention" else [])
|
||||
+ ([f"codex_launch:{codex_launch_status}"] if codex_launch_status == "attention" else [])
|
||||
+ (["launchpad_alignment:inconsistent"] if not bool(launchpad_alignment.get("consistent", False)) else [])
|
||||
)
|
||||
|
||||
if blocked_reasons:
|
||||
signoff_status = "blocked"
|
||||
headline = (
|
||||
str(review.get("headline") or "").strip()
|
||||
or str(doctor_decision.get("headline") or "").strip()
|
||||
or "当前发布前验证仍存在阻断项,不应直接签字上线。"
|
||||
)
|
||||
elif attention_reasons:
|
||||
signoff_status = "attention"
|
||||
headline = (
|
||||
str(doctor_decision.get("headline") or "").strip()
|
||||
or str(review.get("headline") or "").strip()
|
||||
or "当前现场已进入收口区间,但仍建议先完成 attention 项再正式签字。"
|
||||
)
|
||||
else:
|
||||
signoff_status = "ready"
|
||||
headline = "当前证据包、doctor 结论与发布门禁一致,可进入最终人工签字或正式发布。"
|
||||
|
||||
recommended_commands = dedupe_commands(
|
||||
[]
|
||||
+ list(doctor_decision.get("recommended_commands") or [])
|
||||
+ [
|
||||
f"bash domain-api/deploy/multi-region/drive_ops_center.sh go-live-review {manifest_path}",
|
||||
f"bash domain-api/deploy/multi-region/drive_ops_center.sh doctor-decision {manifest_path}",
|
||||
]
|
||||
)
|
||||
|
||||
payload = {
|
||||
"signoff_status": signoff_status,
|
||||
"headline": headline,
|
||||
"generated_bundle": generated_bundle,
|
||||
"report_dir": report_dir or str(doctor.get("report_dir") or review.get("report_dir") or ""),
|
||||
"manifest_path": manifest_path or str(doctor.get("manifest_path") or ""),
|
||||
"base_urls": {
|
||||
"mainland": mainland_base_url,
|
||||
"overseas": overseas_base_url,
|
||||
},
|
||||
"release_gate": {
|
||||
"go_live_status": go_live_status,
|
||||
"publish_status": publish_status,
|
||||
"stack_status": stack_status,
|
||||
"driver_launch_status": driver_launch_status,
|
||||
"codex_launch_status": codex_launch_status,
|
||||
"bundle_review_status": review_status,
|
||||
"doctor_status": doctor_status,
|
||||
},
|
||||
"blocked_reasons": blocked_reasons,
|
||||
"attention_reasons": attention_reasons,
|
||||
"decision": {
|
||||
"operator_title": str(go_live_summary.get("operator_title") or "").strip(),
|
||||
"next_step_action_code": str(go_live_summary.get("next_step_action_code") or "").strip(),
|
||||
"doctor_reason_code": str(doctor_decision.get("reason_code") or "").strip(),
|
||||
"doctor_preferred_surface": str(doctor_decision.get("preferred_surface") or "").strip(),
|
||||
"launchpad_recommended_target_node_code": str(go_live_summary.get("launchpad_recommended_target_node_code") or "").strip(),
|
||||
"launchpad_recommended_recovery_label": str(go_live_summary.get("launchpad_recommended_recovery_label") or "").strip(),
|
||||
"launchpad_recommended_recovery_summary": str(go_live_summary.get("launchpad_recommended_recovery_summary") or "").strip(),
|
||||
},
|
||||
"launchpad_alignment": launchpad_alignment,
|
||||
"recommended_commands": recommended_commands,
|
||||
"bundle_review": review,
|
||||
"doctor_decision": {
|
||||
"summary": doctor_summary,
|
||||
"decision": doctor_decision,
|
||||
},
|
||||
}
|
||||
|
||||
print(json.dumps(payload, ensure_ascii=False, indent=2))
|
||||
PY
|
||||
Reference in New Issue
Block a user