Harden validate stage with safe ACP checks

This commit is contained in:
Haitao Pan 2026-04-10 18:14:14 +08:00
parent 54523d6269
commit 578683c91e
2 changed files with 94 additions and 24 deletions

View File

@ -174,6 +174,11 @@ jobs:
needs: deploy
if: ${{ needs.deploy.result == 'success' && needs.deploy.outputs.run_apply == 'true' }}
runs-on: ubuntu-latest
env:
BRIDGE_SERVER_URL: ${{ vars.BRIDGE_SERVER_URL || 'https://xworkmate-bridge.svc.plus' }}
ACP_INGRESS_URL: ${{ vars.ACP_INGRESS_URL || 'https://acp-server.svc.plus' }}
OPENCLAW_URL: ${{ vars.OPENCLAW_URL || 'wss://openclaw.svc.plus' }}
BRIDGE_AUTH_TOKEN: ${{ secrets.BRIDGE_AUTH_TOKEN || secrets.INTERNAL_SERVICE_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4

View File

@ -1,31 +1,96 @@
#!/usr/bin/env bash
set -euo pipefail
BASE_URL="${1:-https://xworkmate-bridge.svc.plus}"
INGRESS_URL="${2:-https://acp-server.svc.plus}"
normalize_url() {
local value="$1"
if [[ "${value}" =~ ^https:([^/].*)$ ]]; then
printf 'https://%s\n' "${BASH_REMATCH[1]}"
return
fi
if [[ "${value}" =~ ^http:([^/].*)$ ]]; then
printf 'http://%s\n' "${BASH_REMATCH[1]}"
return
fi
printf '%s\n' "${value}"
}
bridge_root="$(curl -fsS "${BASE_URL}/")"
test "${bridge_root}" = "xworkmate-bridge is running"
websocket_probe_url() {
local value="$1"
if [[ "${value}" =~ ^wss://(.*)$ ]]; then
printf 'https://%s\n' "${BASH_REMATCH[1]}"
return
fi
if [[ "${value}" =~ ^ws://(.*)$ ]]; then
printf 'http://%s\n' "${BASH_REMATCH[1]}"
return
fi
printf '%s\n' "${value}"
}
codex_root="$(curl -fsS "${INGRESS_URL}/codex")"
test "${codex_root}" = "xworkmate-bridge is running"
BASE_URL="$(normalize_url "${BRIDGE_SERVER_URL:-${1:-https://xworkmate-bridge.svc.plus}}")"
INGRESS_URL="$(normalize_url "${ACP_INGRESS_URL:-${2:-https://acp-server.svc.plus}}")"
AUTH_TOKEN="${BRIDGE_AUTH_TOKEN:-${INTERNAL_SERVICE_TOKEN:-${3:-}}}"
OPENCLAW_HTTP_PROBE_URL="$(websocket_probe_url "${OPENCLAW_URL:-${4:-wss://openclaw.svc.plus}}")"
codex_rpc="$(
curl -sS "${INGRESS_URL}/codex/acp/rpc" \
-H 'Content-Type: application/json' \
--data '{"jsonrpc":"2.0","id":"cap-1","method":"acp.capabilities"}'
)"
opencode_rpc="$(
curl -sS "${INGRESS_URL}/opencode/acp/rpc" \
-H 'Content-Type: application/json' \
--data '{"jsonrpc":"2.0","id":"cap-1","method":"acp.capabilities"}'
)"
gemini_rpc="$(
curl -sS "${INGRESS_URL}/gemini/acp/rpc" \
-H 'Content-Type: application/json' \
--data '{"jsonrpc":"2.0","id":"cap-1","method":"acp.capabilities"}'
)"
curl_common=(
--silent
--show-error
--fail
--location
--max-time 20
)
grep -q '"missing bearer authorization"' <<<"${codex_rpc}"
grep -q '"missing bearer authorization"' <<<"${opencode_rpc}"
grep -q '"providers"' <<<"${gemini_rpc}"
probe_jsonrpc_capabilities() {
local endpoint="$1"
local response
local headers=(
-H 'Content-Type: application/json'
)
if [[ -n "${AUTH_TOKEN}" ]]; then
headers+=(-H "Authorization: Bearer ${AUTH_TOKEN}")
fi
response="$(
curl "${curl_common[@]}" \
"${headers[@]}" \
--data '{"jsonrpc":"2.0","id":"cap-1","method":"acp.capabilities"}' \
"${endpoint}"
)"
grep -q '"jsonrpc":"2.0"' <<<"${response}"
grep -Eq '"result"|"providers"' <<<"${response}"
}
probe_safe_http_endpoint() {
local endpoint="$1"
local status
status="$(
curl \
--silent \
--show-error \
--output /dev/null \
--write-out '%{http_code}' \
--location \
--max-time 20 \
"${endpoint}"
)"
case "${status}" in
2*|3*|401|403|404|405|426)
return 0
;;
*)
printf 'Unexpected HTTP status %s for %s\n' "${status}" "${endpoint}" >&2
return 1
;;
esac
}
bridge_root="$(curl "${curl_common[@]}" "${BASE_URL}/")"
grep -qi 'xworkmate-bridge' <<<"${bridge_root}"
probe_safe_http_endpoint "${OPENCLAW_HTTP_PROBE_URL}"
probe_jsonrpc_capabilities "${INGRESS_URL}/codex/acp/rpc"
probe_jsonrpc_capabilities "${INGRESS_URL}/opencode/acp/rpc"
probe_jsonrpc_capabilities "${INGRESS_URL}/gemini/acp/rpc"