Files
getDomain/domain-api/deploy/multi-region/check_go_live_signoff.sh
2026-04-18 23:52:51 +08:00

183 lines
7.3 KiB
Bash

#!/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