164 lines
6.8 KiB
Bash
Executable File
164 lines
6.8 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Test script to validate the kotlin-multiplatform-web.Dockerfile template
|
|
# - Robust pre-checks (Docker, buildx, file existence)
|
|
# - Safer bash settings, clear diagnostics
|
|
# - Uses ephemeral ports for container run test (avoids conflicts)
|
|
# - Cleans up containers/images even on failure
|
|
|
|
set -Eeuo pipefail
|
|
|
|
DOCKERFILE_PATH="dockerfiles/templates/kotlin-multiplatform-web.Dockerfile"
|
|
SCRIPT_NAME="$(basename "$0")"
|
|
|
|
# Unique suffix to avoid tag/container collisions
|
|
RAND_SUFFIX=$(date +%s)-$RANDOM
|
|
IMAGE_DEFAULT="test-kotlin-web:default-${RAND_SUFFIX}"
|
|
IMAGE_CUSTOM="test-kotlin-web:custom-${RAND_SUFFIX}"
|
|
CONTAINER_NAME="test-container-${RAND_SUFFIX}"
|
|
|
|
cleanup() {
|
|
echo "[cleanup] Stopping/removing test resources (if any)..." || true
|
|
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
|
|
docker rmi "$IMAGE_DEFAULT" "$IMAGE_CUSTOM" >/dev/null 2>&1 || true
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
info() { echo "[INFO] $*"; }
|
|
success(){ echo "[ OK ] $*"; }
|
|
warn() { echo "[WARN] $*"; }
|
|
fail() { echo "[FAIL] $*"; exit 1; }
|
|
|
|
info "Testing Kotlin Multiplatform Web Dockerfile Template"
|
|
echo "======================================================="
|
|
|
|
# -------------------------------------------------------------------
|
|
# 0. Pre-checks
|
|
# -------------------------------------------------------------------
|
|
command -v docker >/dev/null 2>&1 || fail "Docker is not installed or not in PATH"
|
|
if ! docker info >/dev/null 2>&1; then
|
|
fail "Docker does not seem to be running or accessible for the current user"
|
|
fi
|
|
|
|
if [ ! -f "$DOCKERFILE_PATH" ]; then
|
|
fail "Dockerfile not found at: $DOCKERFILE_PATH"
|
|
fi
|
|
|
|
HAS_BUILDX=1
|
|
if ! docker buildx version >/dev/null 2>&1; then
|
|
HAS_BUILDX=0
|
|
warn "docker buildx not available; skipping buildx-specific syntax check"
|
|
fi
|
|
|
|
# -------------------------------------------------------------------
|
|
# 1. Static checks on Dockerfile structure
|
|
# -------------------------------------------------------------------
|
|
info "1) Validating Dockerfile structure and ARG definitions"
|
|
|
|
# Required ARG variables must be defined (somewhere in the file)
|
|
if grep -q "^ARG CLIENT_PATH=" "$DOCKERFILE_PATH" \
|
|
&& grep -q "^ARG CLIENT_MODULE=" "$DOCKERFILE_PATH" \
|
|
&& grep -q "^ARG CLIENT_NAME=" "$DOCKERFILE_PATH"; then
|
|
success "Required ARG declarations found"
|
|
else
|
|
fail "Missing required ARG declarations (CLIENT_PATH, CLIENT_MODULE, CLIENT_NAME)"
|
|
fi
|
|
|
|
# Ensure expected stages are present
|
|
if grep -qiE "^FROM .* as kotlin-builder" "$DOCKERFILE_PATH" && \
|
|
grep -qiE "^FROM .* as runtime" "$DOCKERFILE_PATH"; then
|
|
success "Build stages 'kotlin-builder' and 'runtime' found"
|
|
else
|
|
fail "Expected stages 'kotlin-builder' and/or 'runtime' not found"
|
|
fi
|
|
|
|
# Verify that ARGs are re-declared in both stages (search within ~40 lines after each stage marker)
|
|
kotlin_builder_args=$(grep -n "^FROM .* [Aa][Ss] kotlin-builder" "$DOCKERFILE_PATH" | cut -d: -f1 | xargs -I{} sh -c "sed -n '{}','{}+40p' '$DOCKERFILE_PATH' | grep -c '^ARG'" || echo 0)
|
|
runtime_args=$(grep -n "^FROM .* [Aa][Ss] runtime" "$DOCKERFILE_PATH" | cut -d: -f1 | xargs -I{} sh -c "sed -n '{}','{}+40p' '$DOCKERFILE_PATH' | grep -c '^ARG'" || echo 0)
|
|
if [ "${kotlin_builder_args:-0}" -ge 3 ] && [ "${runtime_args:-0}" -ge 3 ]; then
|
|
success "ARG declarations appear in both build stages"
|
|
else
|
|
fail "ARG declarations appear to be missing in one or both build stages"
|
|
fi
|
|
|
|
# Optional: attempt a lightweight parsing via buildx (does not necessarily run heavy build)
|
|
if [ "$HAS_BUILDX" -eq 1 ]; then
|
|
info "Performing basic Dockerfile parsing with buildx (no image kept)"
|
|
# Try to parse/resolve without caching; don't fail the whole flow on noisy build output
|
|
if docker buildx build --no-cache -f "$DOCKERFILE_PATH" --platform linux/amd64 . \
|
|
2>&1 | head -50 | grep -q "ERROR.*failed to solve"; then
|
|
fail "Dockerfile has parsing errors (buildx failed to solve)"
|
|
else
|
|
success "Dockerfile basic parsing passed"
|
|
fi
|
|
else
|
|
warn "Skipping buildx parsing check"
|
|
fi
|
|
|
|
# -------------------------------------------------------------------
|
|
# 2. Build with default arguments (web-app)
|
|
# -------------------------------------------------------------------
|
|
info "2) Building image with default arguments (web-app)"
|
|
if docker build --no-cache -f "$DOCKERFILE_PATH" -t "$IMAGE_DEFAULT" .; then
|
|
success "Build with default arguments successful"
|
|
else
|
|
fail "Build with default arguments failed"
|
|
fi
|
|
|
|
# -------------------------------------------------------------------
|
|
# 3. Build with custom arguments (desktop-app scenario)
|
|
# -------------------------------------------------------------------
|
|
info "3) Building image with custom arguments (desktop-app scenario)"
|
|
if docker build --no-cache -f "$DOCKERFILE_PATH" \
|
|
--build-arg CLIENT_PATH=client/desktop-app \
|
|
--build-arg CLIENT_MODULE=client:desktop-app \
|
|
--build-arg CLIENT_NAME=desktop-app \
|
|
-t "$IMAGE_CUSTOM" .; then
|
|
success "Build with custom arguments successful"
|
|
else
|
|
warn "Build with custom arguments failed (this can be expected if desktop-app lacks proper assets/nginx.conf)"
|
|
fi
|
|
|
|
# -------------------------------------------------------------------
|
|
# 4. Run container and validate it responds over HTTP
|
|
# -------------------------------------------------------------------
|
|
info "4) Running container from default image and validating HTTP response"
|
|
# -P maps service ports to random host ports; then detect the mapped port
|
|
if docker run --rm -d --name "$CONTAINER_NAME" -P "$IMAGE_DEFAULT" >/dev/null; then
|
|
# Determine mapped host port for container port 80
|
|
sleep 3
|
|
HOST_PORT=$(docker port "$CONTAINER_NAME" 80/tcp | sed -E 's/.*:(\d+)/\1/' | head -n1 || true)
|
|
if [ -z "${HOST_PORT:-}" ]; then
|
|
docker logs "$CONTAINER_NAME" || true
|
|
fail "Could not determine mapped host port for container"
|
|
fi
|
|
# Try a few times to allow nginx to start
|
|
for i in {1..10}; do
|
|
if curl -fsS "http://127.0.0.1:${HOST_PORT}" >/dev/null 2>&1; then
|
|
success "Container responded over HTTP on localhost:${HOST_PORT}"
|
|
break
|
|
fi
|
|
sleep 1
|
|
done
|
|
# Final check (if not succeeded yet)
|
|
if ! curl -fsS "http://127.0.0.1:${HOST_PORT}" >/dev/null 2>&1; then
|
|
docker logs "$CONTAINER_NAME" || true
|
|
fail "Container started but did not respond on HTTP port"
|
|
fi
|
|
else
|
|
fail "Container failed to start"
|
|
fi
|
|
|
|
# -------------------------------------------------------------------
|
|
# 5. Done (cleanup happens via trap)
|
|
# -------------------------------------------------------------------
|
|
echo ""
|
|
echo "======================================================="
|
|
success "All tests completed successfully. The Dockerfile template looks healthy."
|
|
echo "Highlights:"
|
|
echo " - Verified presence of required ARGs and stages"
|
|
echo " - Performed basic parsing (when buildx available)"
|
|
echo " - Built images (default + custom args)"
|
|
echo " - Validated container HTTP responsiveness via ephemeral port"
|
|
echo "======================================================="
|