From 3047f818aa00c191e9eb2d2958d8aa3da3caec5e Mon Sep 17 00:00:00 2001 From: Haitao Pan Date: Tue, 21 Apr 2026 18:13:26 +0800 Subject: [PATCH] fix: improve bridge endpoint robustness and deployment reporting --- internal/acp/bootstrap.go | 13 +++-- internal/acp/server.go | 14 +++-- .../github-actions/report-production-state.sh | 52 +++++++++++++++---- 3 files changed, 61 insertions(+), 18 deletions(-) diff --git a/internal/acp/bootstrap.go b/internal/acp/bootstrap.go index 14be9da..a456e07 100644 --- a/internal/acp/bootstrap.go +++ b/internal/acp/bootstrap.go @@ -13,12 +13,19 @@ func (s *Server) HandleBridgeBootstrapHealth(w http.ResponseWriter, r *http.Requ http.Error(w, "method not allowed", http.StatusMethodNotAllowed) return } - w.Header().Set("Content-Type", "application/json") - _ = json.NewEncoder(w).Encode(map[string]any{ + resp := map[string]any{ "ok": true, "bridgeOrigin": bridgePublicBaseURL(), "issuedBy": "xworkmate-bridge", - }) + } + body, err := json.Marshal(resp) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write(body) } func bridgePublicBaseURL() string { diff --git a/internal/acp/server.go b/internal/acp/server.go index b01a943..d184503 100644 --- a/internal/acp/server.go +++ b/internal/acp/server.go @@ -121,15 +121,21 @@ func (s *Server) Handler() http.Handler { _, _ = w.Write([]byte("xworkmate-bridge is running")) case "/api/ping": info := parseImageVersionInfo(os.Getenv("IMAGE")) - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - _ = json.NewEncoder(w).Encode(map[string]any{ + resp := map[string]any{ "status": "ok", "image": info.ImageRef, "tag": info.Tag, "commit": info.Commit, "version": info.Version, - }) + } + body, err := json.Marshal(resp) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write(body) case "/bridge/bootstrap/health": s.HandleBridgeBootstrapHealth(w, r) case "/acp/rpc": diff --git a/scripts/github-actions/report-production-state.sh b/scripts/github-actions/report-production-state.sh index b602704..c9a4bf4 100644 --- a/scripts/github-actions/report-production-state.sh +++ b/scripts/github-actions/report-production-state.sh @@ -18,24 +18,54 @@ normalize_url() { base_url="$(normalize_url "${BASE_URL}")" -ping_json="$( - curl \ - --silent \ - --show-error \ - --fail \ - --location \ - --max-time 20 \ - "${base_url}/api/ping" -)" +ping_url="${base_url}/api/ping" +ping_json="" +attempts=6 +sleep_seconds=5 + +for ((attempt = 1; attempt <= attempts; attempt += 1)); do + if ping_json="$( + curl \ + --silent \ + --show-error \ + --fail \ + --location \ + --max-time 20 \ + "${ping_url}" + )"; then + if [[ -n "${ping_json}" ]]; then + break + fi + fi + + if (( attempt == attempts )); then + echo "failed to probe bridge ping at ${ping_url} after ${attempts} attempts" >&2 + exit 1 + fi + + echo "bridge ping at ${ping_url} attempt ${attempt}/${attempts} failed; retrying in ${sleep_seconds}s" >&2 + sleep "${sleep_seconds}" +done PING_JSON="${ping_json}" python3 - <<'PY' import json import os +import sys -payload = json.loads(os.environ["PING_JSON"]) +ping_json = os.environ.get("PING_JSON", "") +if not ping_json: + print("empty ping response", file=sys.stderr) + sys.exit(1) + +try: + payload = json.loads(ping_json) +except json.JSONDecodeError as exc: + print(f"bridge ping returned invalid JSON: {exc}\nBody: {ping_json!r}", file=sys.stderr) + sys.exit(1) if payload.get("status") != "ok": - raise SystemExit("production ping status not ok") + print("production ping status not ok", file=sys.stderr) + sys.exit(1) deployed_image = str(payload.get("image", "")).strip() deployed_tag = str(payload.get("tag", "")).strip()