From a152303a02d7c8b0c64df52c68856422b80b00ae Mon Sep 17 00:00:00 2001 From: Kris Hicks Date: Tue, 16 Jun 2026 07:13:00 -0700 Subject: [PATCH 1/2] fix(e2e): refresh latest sandbox image for docker runs This fixes an issue where you may run e.g. `mise run e2e:python`, then after Python is upgraded in mise.toml, subsequent runs of `e2e:python` fail because the Python version is out of sync. Signed-off-by: Kris Hicks --- e2e/with-docker-gateway.sh | 42 +++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/e2e/with-docker-gateway.sh b/e2e/with-docker-gateway.sh index 4c7ccd9ff..f4160174d 100755 --- a/e2e/with-docker-gateway.sh +++ b/e2e/with-docker-gateway.sh @@ -13,6 +13,13 @@ # # HTTPS endpoint-only mode is intentionally unsupported here. Use a named # gateway config when mTLS materials are needed. +# +# Sandbox image overrides: +# OPENSHELL_E2E_DOCKER_SANDBOX_IMAGE=... +# OPENSHELL_E2E_DOCKER_SANDBOX_IMAGE_PULL_POLICY=Always|IfNotPresent|Never +# +# The default community sandbox image uses :latest and is pulled with Always so +# local e2e runs do not reuse stale images that drift from the repo toolchain. set -euo pipefail @@ -342,6 +349,34 @@ ensure_docker_supervisor_image() { exit 2 } +image_uses_latest_tag() { + local image=$1 + local last_component + + # Digest references are immutable even if the tag portion says latest. + if [[ "${image}" == *@* ]]; then + return 1 + fi + + last_component="${image##*/}" + # Docker treats an omitted tag as :latest. + if [[ "${last_component}" != *:* ]]; then + return 0 + fi + + [[ "${last_component}" == *:latest ]] +} + +default_sandbox_pull_policy() { + local image=$1 + + if image_uses_latest_tag "${image}"; then + printf '%s\n' "Always" + else + printf '%s\n' "IfNotPresent" + fi +} + DAEMON_ARCH="$(normalize_arch "$(docker info --format '{{.Architecture}}' 2>/dev/null || true)")" SUPERVISOR_TARGET="$(linux_target_triple "${DAEMON_ARCH}")" HOST_OS="$(uname -s)" @@ -386,6 +421,10 @@ fi DEFAULT_SANDBOX_IMAGE="ghcr.io/nvidia/openshell-community/sandboxes/base:latest" SANDBOX_IMAGE="${OPENSHELL_E2E_DOCKER_SANDBOX_IMAGE:-${OPENSHELL_SANDBOX_IMAGE:-${DEFAULT_SANDBOX_IMAGE}}}" +SANDBOX_IMAGE_PULL_POLICY="${OPENSHELL_E2E_DOCKER_SANDBOX_IMAGE_PULL_POLICY:-${OPENSHELL_SANDBOX_IMAGE_PULL_POLICY:-}}" +if [ -z "${SANDBOX_IMAGE_PULL_POLICY}" ]; then + SANDBOX_IMAGE_PULL_POLICY="$(default_sandbox_pull_policy "${SANDBOX_IMAGE}")" +fi if ! docker image inspect "${SANDBOX_IMAGE}" >/dev/null 2>&1; then echo "Pulling ${SANDBOX_IMAGE}..." if ! docker_pull_with_retry "${SANDBOX_IMAGE}"; then @@ -420,6 +459,7 @@ else fi echo "Starting openshell-gateway on port ${HOST_PORT} (namespace: ${E2E_NAMESPACE})..." +echo "Using sandbox image: ${SANDBOX_IMAGE} (pull policy: ${SANDBOX_IMAGE_PULL_POLICY})" e2e_generate_gateway_jwt "${JWT_DIR}" # Driver-specific options moved from CLI flags into a TOML config table @@ -446,7 +486,7 @@ GATEWAY_CONFIG="${STATE_DIR}/gateway.toml" printf 'network_name = %s\n' "$(toml_string "${DOCKER_NETWORK_NAME}")" printf 'grpc_endpoint = %s\n' "$(toml_string "${GATEWAY_ENDPOINT}")" printf 'default_image = %s\n' "$(toml_string "${SANDBOX_IMAGE}")" - printf 'image_pull_policy = "IfNotPresent"\n' + printf 'image_pull_policy = %s\n' "$(toml_string "${SANDBOX_IMAGE_PULL_POLICY}")" printf 'guest_tls_ca = %s\n' "$(toml_string "${PKI_DIR}/ca.crt")" printf 'guest_tls_cert = %s\n' "$(toml_string "${PKI_DIR}/client/tls.crt")" printf 'guest_tls_key = %s\n' "$(toml_string "${PKI_DIR}/client/tls.key")" From 2b875e0dee145bbf3ef0d2b706d6e424dde84944 Mon Sep 17 00:00:00 2001 From: Evan Lezar Date: Wed, 17 Jun 2026 12:15:33 +0200 Subject: [PATCH 2/2] fix(e2e): keep Dockerfile images local Signed-off-by: Evan Lezar --- e2e/with-docker-gateway.sh | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/e2e/with-docker-gateway.sh b/e2e/with-docker-gateway.sh index f4160174d..f8e17661d 100755 --- a/e2e/with-docker-gateway.sh +++ b/e2e/with-docker-gateway.sh @@ -18,8 +18,9 @@ # OPENSHELL_E2E_DOCKER_SANDBOX_IMAGE=... # OPENSHELL_E2E_DOCKER_SANDBOX_IMAGE_PULL_POLICY=Always|IfNotPresent|Never # -# The default community sandbox image uses :latest and is pulled with Always so -# local e2e runs do not reuse stale images that drift from the repo toolchain. +# The default community sandbox image uses :latest. This wrapper refreshes it +# before starting the gateway, while the Docker driver defaults to IfNotPresent +# so local Dockerfile-built images remain usable. set -euo pipefail @@ -367,14 +368,21 @@ image_uses_latest_tag() { [[ "${last_component}" == *:latest ]] } -default_sandbox_pull_policy() { +ensure_sandbox_image_available() { local image=$1 if image_uses_latest_tag "${image}"; then - printf '%s\n' "Always" - else - printf '%s\n' "IfNotPresent" + echo "Refreshing latest sandbox image ${image}..." + docker_pull_with_retry "${image}" + return fi + + if docker image inspect "${image}" >/dev/null 2>&1; then + return + fi + + echo "Pulling ${image}..." + docker_pull_with_retry "${image}" } DAEMON_ARCH="$(normalize_arch "$(docker info --format '{{.Architecture}}' 2>/dev/null || true)")" @@ -421,16 +429,10 @@ fi DEFAULT_SANDBOX_IMAGE="ghcr.io/nvidia/openshell-community/sandboxes/base:latest" SANDBOX_IMAGE="${OPENSHELL_E2E_DOCKER_SANDBOX_IMAGE:-${OPENSHELL_SANDBOX_IMAGE:-${DEFAULT_SANDBOX_IMAGE}}}" -SANDBOX_IMAGE_PULL_POLICY="${OPENSHELL_E2E_DOCKER_SANDBOX_IMAGE_PULL_POLICY:-${OPENSHELL_SANDBOX_IMAGE_PULL_POLICY:-}}" -if [ -z "${SANDBOX_IMAGE_PULL_POLICY}" ]; then - SANDBOX_IMAGE_PULL_POLICY="$(default_sandbox_pull_policy "${SANDBOX_IMAGE}")" -fi -if ! docker image inspect "${SANDBOX_IMAGE}" >/dev/null 2>&1; then - echo "Pulling ${SANDBOX_IMAGE}..." - if ! docker_pull_with_retry "${SANDBOX_IMAGE}"; then - echo "ERROR: sandbox image '${SANDBOX_IMAGE}' is not available." >&2 - exit 2 - fi +SANDBOX_IMAGE_PULL_POLICY="${OPENSHELL_E2E_DOCKER_SANDBOX_IMAGE_PULL_POLICY:-${OPENSHELL_SANDBOX_IMAGE_PULL_POLICY:-IfNotPresent}}" +if ! ensure_sandbox_image_available "${SANDBOX_IMAGE}"; then + echo "ERROR: sandbox image '${SANDBOX_IMAGE}' is not available." >&2 + exit 2 fi PKI_DIR="${WORKDIR}/pki"