#!/usr/bin/env bash set -euo pipefail # Disposable integration gate for multiplayer-next.md ยง8.49. This deliberately # does not touch an existing cluster: kind creates an isolated cluster and the # EXIT trap removes only that named cluster. root_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$root_dir" cluster_name="${KIND_CLUSTER_NAME:-cosmic-clash-agones-smoke}" agones_version="${AGONES_VERSION:-1.49.0}" game_server_image="${GAME_SERVER_IMAGE:-cosmic-clash-game-server:kind}" kind_node_image="${KIND_NODE_IMAGE:-kindest/node:v1.33.1}" work_dir="$(mktemp -d "${TMPDIR:-/tmp}/cosmic-clash-agones.XXXXXX")" cleanup() { local status=$? kind delete cluster --name "$cluster_name" >/dev/null 2>&1 || true rm -rf "$work_dir" exit "$status" } trap cleanup EXIT for tool in docker kind kubectl helm; do command -v "$tool" >/dev/null 2>&1 || { echo "8.49 requires '$tool'; install Docker, kind, kubectl, and Helm to run the disposable gate" >&2 exit 2 } done if ! docker info >/dev/null 2>&1; then echo "8.49 requires a running Docker daemon" >&2 exit 2 fi kind delete cluster --name "$cluster_name" >/dev/null 2>&1 || true if ! docker image inspect "$game_server_image" >/dev/null 2>&1; then echo "Building $game_server_image from the pinned game-server target" docker build --target game-server -t "$game_server_image" . fi kind create cluster --name "$cluster_name" --image "$kind_node_image" --wait 120s kind load docker-image "$game_server_image" --name "$cluster_name" helm repo add agones https://agones.dev/chart/stable >/dev/null helm repo update >/dev/null helm upgrade --install agones agones/agones \ --namespace agones-system --create-namespace \ --version "$agones_version" \ --set agones.crds.cleanup.enabled=true \ --set agones.controller.replicas=1 \ --set agones.extensions.replicas=1 \ --set agones.allocator.replicas=1 \ --wait --timeout 5m kubectl wait --for=condition=available deployment/agones-controller \ -n agones-system --timeout=180s kubectl wait --for=condition=available deployment/agones-allocator \ -n agones-system --timeout=180s # The base Fleet intentionally carries a release-time digest placeholder. For # this isolated run only, replace that exact placeholder with the image loaded # into kind. No repository manifest is modified and no mutable image is used # outside the disposable cluster. # # This runner is intentionally an Agones lifecycle smoke, not a substitute for # the production control-plane gate: there is no PostgreSQL/API/roster backend # in this disposable cluster. Disable only those production-only child paths so # the real supervisor can validate the assigned endpoint, launch the exported # server, and call the Agones SDK Ready endpoint. zero_digest="$(printf '0%.0s' {1..64})" sed -e "s|ghcr.io/cosmic-clash/game-server@sha256:${zero_digest}|$game_server_image|" \ -e 's|--control-plane-url=http://control-plane.cosmic-clash.svc.cluster.local:8080|--control-plane-url=|' \ -e '/- --roster-path=\/run\/cosmic-clash\/join-roster.json/d' \ -e '/- --allocated-mode$/d' \ deploy/k8s/base/fleet.yaml > "$work_dir/fleet.yaml" kubectl apply -f deploy/k8s/base/namespace.yaml kubectl -n cosmic-clash create secret generic cosmic-clash-game-server \ --from-literal=drain-token=kind-smoke-drain-token \ --from-literal=join-signing-key=kind-smoke-signing-key \ --dry-run=client -o yaml | kubectl apply -f - kubectl apply -f deploy/k8s/base/service-accounts.yaml kubectl apply -f "$work_dir/fleet.yaml" kubectl wait --for=jsonpath='{.status.ready}'=2 \ fleet/cosmic-clash-game -n cosmic-clash --timeout=5m cat > "$work_dir/allocation.yaml" <<'EOF' apiVersion: allocation.agones.dev/v1 kind: GameServerAllocation metadata: generateName: cosmic-clash-smoke- namespace: cosmic-clash spec: fleet: name: cosmic-clash-game EOF kubectl create -f "$work_dir/allocation.yaml" -o json > "$work_dir/allocation.json" python3 scripts/verify_agones_allocation_response.py "$work_dir/allocation.json"