183 lines
7.3 KiB
Bash
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
|