#!/usr/bin/env bash set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" SERVICE_URL="${RENDEZVOUS_SMOKE_HTTP_URL:-http://127.0.0.1:8080/}" MEDIATOR="${RENDEZVOUS_SMOKE_UDP_ENDPOINT:-127.0.0.1:9050}" TIMEOUT_SECONDS="${RENDEZVOUS_SMOKE_TIMEOUT_SECONDS:-30}" LOCAL_KEY="${RENDEZVOUS_SMOKE_LOCAL_KEY:-$ROOT/deploy/compose/secrets/signing-key}" PROJECT="$ROOT/src/FinalFactory.Rendezvous.TestClient/FinalFactory.Rendezvous.TestClient.csproj" BUILD_CONFIGURATION="${RENDEZVOUS_SMOKE_CONFIGURATION:-Release}" GAME_ID="${RENDEZVOUS_SMOKE_GAME_ID:-space-game}" ENVIRONMENT_ID="${RENDEZVOUS_SMOKE_ENVIRONMENT_ID:-smoke}" REGION="${RENDEZVOUS_SMOKE_REGION:-local}" PROTOCOL_VERSION="${RENDEZVOUS_SMOKE_PROTOCOL_VERSION:-1}" for command in curl dotnet jq mktemp tail; do command -v "$command" >/dev/null || { printf 'Missing required command: %s\n' "$command" >&2 exit 2 } done if [[ ! "$TIMEOUT_SECONDS" =~ ^[0-9]+$ ]] || (( TIMEOUT_SECONDS < 1 || TIMEOUT_SECONDS > 300 )); then printf 'RENDEZVOUS_SMOKE_TIMEOUT_SECONDS must be an integer from 1 through 300.\n' >&2 exit 2 fi if [[ ! "$PROTOCOL_VERSION" =~ ^[0-9]+$ ]] || (( PROTOCOL_VERSION < 1 )); then printf 'RENDEZVOUS_SMOKE_PROTOCOL_VERSION must be a positive integer.\n' >&2 exit 2 fi for scoped_value in "$GAME_ID" "$ENVIRONMENT_ID" "$REGION"; do if [[ -z "$scoped_value" ]]; then printf 'Smoke game, environment, and region values must not be empty.\n' >&2 exit 2 fi done local_credential() { if [[ "$GAME_ID" != space-game || "$ENVIRONMENT_ID" != smoke \ || "$REGION" != local || "$PROTOCOL_VERSION" != 1 ]]; then printf 'The local credential helper supports only space-game/smoke/local protocol 1. Supply RENDEZVOUS_PUBLISHER_CREDENTIAL for any other scope.\n' >&2 exit 2 fi RENDEZVOUS_SMOKE_LOCAL_KEY="$LOCAL_KEY" \ "$ROOT/scripts/mint-local-publisher-credential.sh" } credential="${RENDEZVOUS_PUBLISHER_CREDENTIAL:-}" if [[ -z "$credential" ]]; then credential="$(local_credential)" fi export RENDEZVOUS_PUBLISHER_CREDENTIAL="$credential" curl --fail --silent --show-error --max-time 5 "${SERVICE_URL%/}/health/live" >/dev/null curl --fail --silent --show-error --max-time 5 "${SERVICE_URL%/}/health/ready" >/dev/null temp_dir="$(mktemp -d)" host_log="$temp_dir/host.jsonl" join_log="$temp_dir/join.jsonl" host_pid='' cleanup() { local status="$?" if [[ -n "$host_pid" ]] && kill -0 "$host_pid" 2>/dev/null; then kill -TERM "$host_pid" 2>/dev/null || true wait "$host_pid" 2>/dev/null || true fi if [[ "$status" -ne 0 ]]; then printf 'Deployment smoke failed; sanitized diagnostic events follow.\n' >&2 [[ -f "$host_log" ]] && jq -c . "$host_log" >&2 || true [[ -f "$join_log" ]] && jq -c . "$join_log" >&2 || true fi rm -rf "$temp_dir" return "$status" } trap cleanup EXIT trap 'exit 130' INT trap 'exit 143' TERM dotnet run --project "$PROJECT" --configuration "$BUILD_CONFIGURATION" --no-build -- \ host --service "$SERVICE_URL" --mediator "$MEDIATOR" \ --game "$GAME_ID" --environment "$ENVIRONMENT_ID" --region "$REGION" --protocol "$PROTOCOL_VERSION" \ --script --json --exit-after-echo --timeout-seconds "$TIMEOUT_SECONDS" \ >"$host_log" 2>&1 & host_pid="$!" ready=false for ((iteration = 0; iteration < TIMEOUT_SECONDS * 4; iteration++)); do if jq -e 'select(.event == "host.ready")' "$host_log" >/dev/null 2>&1; then ready=true break fi if ! kill -0 "$host_pid" 2>/dev/null; then printf 'Host diagnostic stopped before it became ready.\n' >&2 jq -c . "$host_log" >&2 || true exit 1 fi sleep 0.25 done if [[ "$ready" != true ]]; then printf 'Host diagnostic did not become ready within %s seconds.\n' "$TIMEOUT_SECONDS" >&2 exit 1 fi listing_id="$(jq -r 'select(.event == "host.registered") | .listingId' "$host_log" | tail -n 1)" if [[ -z "$listing_id" || "$listing_id" == null ]]; then printf 'Host diagnostic did not report a listing ID.\n' >&2 exit 1 fi dotnet run --project "$PROJECT" --configuration "$BUILD_CONFIGURATION" --no-build -- \ join --service "$SERVICE_URL" --mediator "$MEDIATOR" \ --game "$GAME_ID" --environment "$ENVIRONMENT_ID" --region "$REGION" --protocol "$PROTOCOL_VERSION" \ --listing "$listing_id" --script --json --timeout-seconds "$TIMEOUT_SECONDS" \ >"$join_log" 2>&1 wait "$host_pid" host_pid='' jq -e 'select(.event == "host.direct-traffic" and .status == "verified")' "$host_log" >/dev/null jq -e 'select(.event == "host.deregistered" and .status == "complete")' "$host_log" >/dev/null jq -e 'select(.event == "join.direct-traffic" and .status == "verified")' "$join_log" >/dev/null jq -e 'select(.event == "join.outcome-report" and .status == "accepted")' "$join_log" >/dev/null printf 'Rendezvous deployment smoke passed: HTTP live/ready and authenticated UDP mediation/direct traffic.\n'