@@ -61,6 +61,9 @@ GATEWAY_PID=""
6161GATEWAY_LOG=" ${WORKDIR} /gateway.log"
6262GATEWAY_CONFIG_DIR=" "
6363E2E_NAMESPACE=" "
64+ DOCKER_NETWORK_NAME=" "
65+ DOCKER_NETWORK_CONNECTED_CONTAINER=" "
66+ DOCKER_NETWORK_MANAGED=0
6467GPU_MODE=" ${OPENSHELL_E2E_DOCKER_GPU:- 0} "
6568
6669# Isolate CLI/SDK gateway metadata from the developer's real config.
@@ -107,6 +110,20 @@ cleanup() {
107110 fi
108111 fi
109112
113+ if [ -n " ${DOCKER_NETWORK_CONNECTED_CONTAINER} " ] \
114+ && [ -n " ${DOCKER_NETWORK_NAME} " ] \
115+ && command -v docker > /dev/null 2>&1 ; then
116+ docker network disconnect -f \
117+ " ${DOCKER_NETWORK_NAME} " \
118+ " ${DOCKER_NETWORK_CONNECTED_CONTAINER} " > /dev/null 2>&1 || true
119+ fi
120+
121+ if [ " ${DOCKER_NETWORK_MANAGED} " = " 1" ] \
122+ && [ -n " ${DOCKER_NETWORK_NAME} " ] \
123+ && command -v docker > /dev/null 2>&1 ; then
124+ docker network rm " ${DOCKER_NETWORK_NAME} " > /dev/null 2>&1 || true
125+ fi
126+
110127 if [ " ${exit_code} " -ne 0 ] && [ -f " ${GATEWAY_LOG} " ]; then
111128 echo " === gateway log (preserved for debugging) ==="
112129 cat " ${GATEWAY_LOG} "
@@ -172,6 +189,70 @@ pick_port() {
172189 python3 -c ' import socket; s=socket.socket(); s.bind(("",0)); print(s.getsockname()[1]); s.close()'
173190}
174191
192+ ensure_e2e_docker_network () {
193+ local network=$1
194+
195+ if docker network inspect " ${network} " > /dev/null 2>&1 ; then
196+ return 0
197+ fi
198+
199+ docker network create \
200+ --driver bridge \
201+ --attachable \
202+ --label openshell.ai/managed-by=openshell \
203+ --label " openshell.ai/sandbox-namespace=${E2E_NAMESPACE} " \
204+ " ${network} " > /dev/null
205+ DOCKER_NETWORK_MANAGED=1
206+ }
207+
208+ github_actions_container_id () {
209+ if [ " ${GITHUB_ACTIONS:- } " != " true" ] || [ ! -f /.dockerenv ]; then
210+ return 1
211+ fi
212+
213+ local container
214+ container=" $( hostname) "
215+ if docker inspect " ${container} " > /dev/null 2>&1 ; then
216+ printf ' %s\n' " ${container} "
217+ return 0
218+ fi
219+
220+ return 1
221+ }
222+
223+ connect_current_container_to_docker_network () {
224+ local network=$1
225+ local container
226+
227+ if ! container=" $( github_actions_container_id) " ; then
228+ return 1
229+ fi
230+
231+ local connect_err=" ${WORKDIR} /docker-network-connect.err"
232+ if ! docker network connect \
233+ --alias host.openshell.internal \
234+ " ${network} " \
235+ " ${container} " 2> " ${connect_err} " ; then
236+ if ! grep -qi " already exists" " ${connect_err} " ; then
237+ cat " ${connect_err} " >&2
238+ return 1
239+ fi
240+ fi
241+
242+ DOCKER_NETWORK_CONNECTED_CONTAINER=" ${container} "
243+
244+ local container_ip
245+ container_ip=" $( docker inspect \
246+ --format " {{with index .NetworkSettings.Networks \" ${network} \" }}{{.IPAddress}}{{end}}" \
247+ " ${container} " ) "
248+ if [ -z " ${container_ip} " ]; then
249+ echo " ERROR: failed to resolve current job container IP on Docker network ${network} " >&2
250+ return 1
251+ fi
252+
253+ GATEWAY_HOST_ALIAS_IP=" ${container_ip} "
254+ }
255+
175256if [ -n " ${OPENSHELL_GATEWAY_ENDPOINT:- } " ]; then
176257 case " ${OPENSHELL_GATEWAY_ENDPOINT} " in
177258 http://* ) ;;
@@ -327,13 +408,23 @@ mkdir -p "${STATE_DIR}"
327408
328409GATEWAY_ENDPOINT=" https://host.openshell.internal:${HOST_PORT} "
329410E2E_NAMESPACE=" e2e-docker-$$ -${HOST_PORT} "
411+ DOCKER_NETWORK_NAME=" ${E2E_NAMESPACE} "
412+ GATEWAY_HOST_ALIAS_IP=" "
413+
414+ ensure_e2e_docker_network " ${DOCKER_NETWORK_NAME} "
415+ if connect_current_container_to_docker_network " ${DOCKER_NETWORK_NAME} " ; then
416+ echo " Connected CI job container to Docker network ${DOCKER_NETWORK_NAME} (${GATEWAY_HOST_ALIAS_IP} )."
417+ else
418+ GATEWAY_HOST_ALIAS_IP=" "
419+ fi
330420
331421echo " Starting openshell-gateway on port ${HOST_PORT} (namespace: ${E2E_NAMESPACE} )..."
332- " ${GATEWAY_BIN} " \
422+ GATEWAY_ARGS=(
333423 --bind-address 0.0.0.0 \
334424 --port " ${HOST_PORT} " \
335425 --drivers docker \
336426 --sandbox-namespace " ${E2E_NAMESPACE} " \
427+ --docker-network-name " ${DOCKER_NETWORK_NAME} " \
337428 --tls-cert " ${PKI_DIR} /server.crt" \
338429 --tls-key " ${PKI_DIR} /server.key" \
339430 --tls-client-ca " ${PKI_DIR} /ca.crt" \
@@ -344,8 +435,12 @@ echo "Starting openshell-gateway on port ${HOST_PORT} (namespace: ${E2E_NAMESPAC
344435 --docker-tls-cert " ${PKI_DIR} /client.crt" \
345436 --docker-tls-key " ${PKI_DIR} /client.key" \
346437 --sandbox-image " ${SANDBOX_IMAGE} " \
347- --sandbox-image-pull-policy IfNotPresent \
348- > " ${GATEWAY_LOG} " 2>&1 &
438+ --sandbox-image-pull-policy IfNotPresent
439+ )
440+ if [ -n " ${GATEWAY_HOST_ALIAS_IP} " ]; then
441+ GATEWAY_ARGS+=(--host-gateway-ip " ${GATEWAY_HOST_ALIAS_IP} " )
442+ fi
443+ " ${GATEWAY_BIN} " " ${GATEWAY_ARGS[@]} " > " ${GATEWAY_LOG} " 2>&1 &
349444GATEWAY_PID=$!
350445
351446GATEWAY_NAME=" openshell-e2e-docker-${HOST_PORT} "
@@ -358,12 +453,13 @@ export OPENSHELL_PROVISION_TIMEOUT="${OPENSHELL_PROVISION_TIMEOUT:-180}"
358453echo " Waiting for gateway to become healthy..."
359454elapsed=0
360455timeout=120
456+ last_status_output=" "
361457while [ " ${elapsed} " -lt " ${timeout} " ]; do
362458 if ! kill -0 " ${GATEWAY_PID} " 2> /dev/null; then
363459 echo " ERROR: openshell-gateway exited before becoming healthy"
364460 exit 1
365461 fi
366- if " $ {CLI_BIN}" status > /dev/null 2>&1 ; then
462+ if last_status_output= " $( " $ {CLI_BIN}" status 2>&1 ) " ; then
367463 echo " Gateway healthy after ${elapsed} s."
368464 break
369465 fi
@@ -372,6 +468,13 @@ while [ "${elapsed}" -lt "${timeout}" ]; do
372468done
373469if [ " ${elapsed} " -ge " ${timeout} " ]; then
374470 echo " ERROR: gateway did not become healthy within ${timeout} s"
471+ echo " === last openshell status output ==="
472+ if [ -n " ${last_status_output} " ]; then
473+ printf ' %s\n' " ${last_status_output} "
474+ else
475+ echo " <no output>"
476+ fi
477+ echo " === end openshell status output ==="
375478 exit 1
376479fi
377480
0 commit comments