#!/usr/bin/env bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" ROOT_DIR="$(cd "${SCRIPT_DIR}/../.." && pwd)" ENV_FILE="${1:-${SCRIPT_DIR}/.env.minimax-dev}" OUT_DIR="${ROOT_DIR}/reports/gates" ART_DIR_BASE="${ROOT_DIR}/tests/supply/artifacts" TS="$(date +%F_%H%M%S)" mkdir -p "${OUT_DIR}" "${ART_DIR_BASE}" if [[ ! -f "${ENV_FILE}" ]]; then echo "[FAIL] missing env file: ${ENV_FILE}" exit 1 fi # shellcheck disable=SC1090 source "${ENV_FILE}" require_var() { local n="$1" if [[ -z "${!n:-}" ]]; then echo "[FAIL] missing required env var: ${n}" exit 1 fi } require_bin() { local b="$1" if ! command -v "${b}" >/dev/null 2>&1; then echo "[FAIL] missing required binary: ${b}" exit 1 fi } join_url() { local base="$1" local path="$2" base="${base%/}" if [[ "${path}" != /* ]]; then path="/${path}" fi echo "${base}${path}" } classify_http_code() { local code="$1" case "${code}" in 200|201|202) echo "PASS" ;; 400|422|429) echo "PASS_AUTH_REACHED" ;; 401|403) echo "FAIL_AUTH" ;; 404|405) echo "FAIL_PATH" ;; 000) echo "FAIL_NETWORK" ;; *) echo "FAIL_OTHER" ;; esac } require_var API_BASE_URL require_var OWNER_BEARER_TOKEN require_bin curl require_bin jq MINIMAX_SMOKE_PATH="${MINIMAX_SMOKE_PATH:-/v1/messages}" MINIMAX_SMOKE_MODEL="${MINIMAX_SMOKE_MODEL:-minimax-smoke-model}" MINIMAX_TIMEOUT_SECONDS="${MINIMAX_TIMEOUT_SECONDS:-20}" MINIMAX_SMOKE_DRY_RUN="${MINIMAX_SMOKE_DRY_RUN:-0}" TARGET_URL="$(join_url "${API_BASE_URL}" "${MINIMAX_SMOKE_PATH}")" ART_DIR="${ART_DIR_BASE}/minimax_smoke_${TS}" mkdir -p "${ART_DIR}" BASE_RESP_FILE="${ART_DIR}/01_base_probe_body.txt" BASE_ERR_FILE="${ART_DIR}/01_base_probe_stderr.log" ACTIVE_RESP_FILE="${ART_DIR}/02_active_probe_body.json" ACTIVE_ERR_FILE="${ART_DIR}/02_active_probe_stderr.log" REPORT_FILE="${OUT_DIR}/minimax_upstream_smoke_${TS}.md" LOG_FILE="${OUT_DIR}/minimax_upstream_smoke_${TS}.log" echo "[INFO] minimax smoke started ts=${TS}" | tee "${LOG_FILE}" echo "[INFO] env_file=${ENV_FILE}" | tee -a "${LOG_FILE}" echo "[INFO] api_base_url=${API_BASE_URL}" | tee -a "${LOG_FILE}" echo "[INFO] target_url=${TARGET_URL}" | tee -a "${LOG_FILE}" echo "[INFO] dry_run=${MINIMAX_SMOKE_DRY_RUN}" | tee -a "${LOG_FILE}" if [[ "${MINIMAX_SMOKE_DRY_RUN}" == "1" ]]; then { echo "# Minimax 上游 Smoke 报告" echo echo "- 时间戳:${TS}" echo "- 执行脚本:\`scripts/supply-gate/minimax_upstream_smoke.sh\`" echo "- 环境文件:\`${ENV_FILE}\`" echo "- API_BASE_URL:\`${API_BASE_URL}\`" echo "- 目标路径:\`${MINIMAX_SMOKE_PATH}\`" echo "- 探测 URL:\`${TARGET_URL}\`" echo "- 总体结论:**PASS_DRY_RUN**" echo echo "## 1. 说明" echo echo "- 本次为 dry-run,未发起任何外部网络请求。" echo "- 用于流水联调与产物校验,不可替代真实上游验证证据。" } > "${REPORT_FILE}" { echo "[INFO] report=${REPORT_FILE}" echo "[RESULT] PASS_DRY_RUN" } | tee -a "${LOG_FILE}" exit 0 fi BASE_HTTP_CODE="000" BASE_RC=0 BASE_HTTP_CODE="$(curl -sS -m "${MINIMAX_TIMEOUT_SECONDS}" \ -o "${BASE_RESP_FILE}" \ -w '%{http_code}' \ "${API_BASE_URL}" 2>"${BASE_ERR_FILE}")" || BASE_RC=$? ACTIVE_HTTP_CODE="000" ACTIVE_RC=0 ACTIVE_PAYLOAD_FILE="${ART_DIR}/02_active_probe_request.json" jq -n \ --arg model "${MINIMAX_SMOKE_MODEL}" \ '{model:$model,max_tokens:1,messages:[{role:"user",content:"ping"}]}' > "${ACTIVE_PAYLOAD_FILE}" ACTIVE_HTTP_CODE="$(curl -sS -m "${MINIMAX_TIMEOUT_SECONDS}" \ -o "${ACTIVE_RESP_FILE}" \ -w '%{http_code}' \ -X POST "${TARGET_URL}" \ -H "Authorization: Bearer ${OWNER_BEARER_TOKEN}" \ -H "Content-Type: application/json" \ -H "anthropic-version: 2023-06-01" \ --data @"${ACTIVE_PAYLOAD_FILE}" 2>"${ACTIVE_ERR_FILE}")" || ACTIVE_RC=$? BASE_CLASS="PASS_CONNECTIVITY" if [[ "${BASE_RC}" -ne 0 ]]; then BASE_CLASS="FAIL_NETWORK" elif [[ "${BASE_HTTP_CODE}" == "000" ]]; then BASE_CLASS="FAIL_NETWORK" fi ACTIVE_CLASS="FAIL_OTHER" if [[ "${ACTIVE_RC}" -ne 0 ]]; then ACTIVE_CLASS="FAIL_NETWORK" else ACTIVE_CLASS="$(classify_http_code "${ACTIVE_HTTP_CODE}")" fi OVERALL="PASS" if [[ "${BASE_CLASS}" == FAIL_* ]] || [[ "${ACTIVE_CLASS}" == FAIL_* ]]; then OVERALL="FAIL" fi { echo "# Minimax 上游 Smoke 报告" echo echo "- 时间戳:${TS}" echo "- 执行脚本:\`scripts/supply-gate/minimax_upstream_smoke.sh\`" echo "- 环境文件:\`${ENV_FILE}\`" echo "- API_BASE_URL:\`${API_BASE_URL}\`" echo "- 目标路径:\`${MINIMAX_SMOKE_PATH}\`" echo "- 探测 URL:\`${TARGET_URL}\`" echo "- 总体结论:**${OVERALL}**" echo echo "## 1. Base 连通探测" echo echo "- curl rc:${BASE_RC}" echo "- http_code:${BASE_HTTP_CODE}" echo "- 分类:**${BASE_CLASS}**" echo "- 产物:\`${BASE_RESP_FILE}\` / \`${BASE_ERR_FILE}\`" echo echo "## 2. Active 鉴权探测" echo echo "- curl rc:${ACTIVE_RC}" echo "- http_code:${ACTIVE_HTTP_CODE}" echo "- 分类:**${ACTIVE_CLASS}**" echo "- 产物:\`${ACTIVE_PAYLOAD_FILE}\` / \`${ACTIVE_RESP_FILE}\` / \`${ACTIVE_ERR_FILE}\`" echo echo "## 3. 判定规则" echo echo "1. Base 探测仅判断连通:curl 成功且非 \`000\` 记为 \`PASS_CONNECTIVITY\`。" echo "2. Active 探测 \`2xx\` => PASS(请求成功)。" echo "3. Active 探测 \`400/422/429\` => PASS_AUTH_REACHED(已到达业务层,通常说明鉴权头被接收)。" echo "4. Active 探测 \`401/403\` => FAIL_AUTH(鉴权失败)。" echo "5. Active 探测 \`404/405\` => FAIL_PATH(路径或方法不匹配)。" echo "6. 任一探测 \`000\` 或 curl 非零 => FAIL_NETWORK(网络/解析/连接失败)。" } > "${REPORT_FILE}" { echo "[INFO] report=${REPORT_FILE}" echo "[INFO] base_http=${BASE_HTTP_CODE} active_http=${ACTIVE_HTTP_CODE}" echo "[RESULT] ${OVERALL}" } | tee -a "${LOG_FILE}" if [[ "${OVERALL}" == "FAIL" ]]; then exit 1 fi