CI_CD_Doctor / pre_validation.sh
samrat-rm's picture
Upload folder using huggingface_hub
d7c4dd5 verified
#!/usr/bin/env bash
#
# validate-submission.sh — OpenEnv Submission Validator
#
# Checks that the Docker image builds, the server boots and responds to /reset,
# and `openenv validate` passes. Works locally (no HF Space required) or against
# a deployed HF Space.
#
# Prerequisites:
# - Docker: https://docs.docker.com/get-docker/
# - openenv-core: pip install openenv-core
# - curl (usually pre-installed)
#
# Run (local mode — builds image and runs container on localhost):
# ./validate-submission.sh
# ./validate-submission.sh --local [repo_dir]
#
# Run (remote mode — pings an already-deployed HF Space):
# ./validate-submission.sh <ping_url> [repo_dir]
#
# Examples:
# ./validate-submission.sh
# ./validate-submission.sh --local ./my-repo
# ./validate-submission.sh https://my-team.hf.space
#
set -uo pipefail
DOCKER_BUILD_TIMEOUT=600
if [ -t 1 ]; then
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BOLD='\033[1m'
NC='\033[0m'
else
RED='' GREEN='' YELLOW='' BOLD='' NC=''
fi
run_with_timeout() {
local secs="$1"; shift
if command -v timeout &>/dev/null; then
timeout "$secs" "$@"
elif command -v gtimeout &>/dev/null; then
gtimeout "$secs" "$@"
else
"$@" &
local pid=$!
( sleep "$secs" && kill "$pid" 2>/dev/null ) &
local watcher=$!
wait "$pid" 2>/dev/null
local rc=$?
kill "$watcher" 2>/dev/null
wait "$watcher" 2>/dev/null
return $rc
fi
}
portable_mktemp() {
local prefix="${1:-validate}"
mktemp "${TMPDIR:-/tmp}/${prefix}-XXXXXX" 2>/dev/null || mktemp
}
CLEANUP_FILES=()
LOCAL_CONTAINER=""
cleanup() {
rm -f "${CLEANUP_FILES[@]+"${CLEANUP_FILES[@]}"}"
if [ -n "$LOCAL_CONTAINER" ]; then
docker rm -f "$LOCAL_CONTAINER" >/dev/null 2>&1 || true
fi
}
trap cleanup EXIT
LOCAL_MODE=false
if [ $# -eq 0 ] || [ "${1:-}" = "--local" ]; then
LOCAL_MODE=true
REPO_DIR="${2:-.}"
PING_URL=""
else
PING_URL="${1:-}"
REPO_DIR="${2:-.}"
fi
if ! REPO_DIR="$(cd "$REPO_DIR" 2>/dev/null && pwd)"; then
printf "Error: directory '%s' not found\n" "${2:-.}"
exit 1
fi
PING_URL="${PING_URL%/}"
export PING_URL
PASS=0
log() { printf "[%s] %b\n" "$(date -u +%H:%M:%S)" "$*"; }
pass() { log "${GREEN}PASSED${NC} -- $1"; PASS=$((PASS + 1)); }
fail() { log "${RED}FAILED${NC} -- $1"; }
hint() { printf " ${YELLOW}Hint:${NC} %b\n" "$1"; }
stop_at() {
printf "\n"
printf "${RED}${BOLD}Validation stopped at %s.${NC} Fix the above before continuing.\n" "$1"
exit 1
}
printf "\n"
printf "${BOLD}========================================${NC}\n"
printf "${BOLD} OpenEnv Submission Validator${NC}\n"
printf "${BOLD}========================================${NC}\n"
log "Repo: $REPO_DIR"
if [ "$LOCAL_MODE" = true ]; then
log "Mode: LOCAL (build + run container on localhost:8000)"
else
log "Mode: REMOTE"
log "Ping URL: $PING_URL"
fi
printf "\n"
log "${BOLD}Step 1/3: Running docker build${NC} ..."
if ! command -v docker &>/dev/null; then
fail "docker command not found"
hint "Install Docker: https://docs.docker.com/get-docker/"
stop_at "Step 1"
fi
if [ -f "$REPO_DIR/Dockerfile" ]; then
DOCKER_CONTEXT="$REPO_DIR"
elif [ -f "$REPO_DIR/server/Dockerfile" ]; then
DOCKER_CONTEXT="$REPO_DIR/server"
else
fail "No Dockerfile found in repo root or server/ directory"
stop_at "Step 1"
fi
log " Found Dockerfile in $DOCKER_CONTEXT"
LOCAL_IMAGE_TAG="cicd-doctor-validate:local"
BUILD_OK=false
BUILD_OUTPUT=$(run_with_timeout "$DOCKER_BUILD_TIMEOUT" docker build -t "$LOCAL_IMAGE_TAG" "$DOCKER_CONTEXT" 2>&1) && BUILD_OK=true
if [ "$BUILD_OK" = true ]; then
pass "Docker build succeeded"
else
fail "Docker build failed (timeout=${DOCKER_BUILD_TIMEOUT}s)"
printf "%s\n" "$BUILD_OUTPUT" | tail -20
stop_at "Step 1"
fi
if [ "$LOCAL_MODE" = true ]; then
log "${BOLD}Step 2/3: Starting local container${NC} and pinging /reset ..."
LOCAL_PORT=8000
LOCAL_CONTAINER="cicd-doctor-validate-$$"
PING_URL="http://localhost:${LOCAL_PORT}"
if ! docker run -d --rm --name "$LOCAL_CONTAINER" -p "${LOCAL_PORT}:8000" "$LOCAL_IMAGE_TAG" >/dev/null 2>&1; then
fail "Failed to start container on port ${LOCAL_PORT}"
hint "Is port ${LOCAL_PORT} already in use? Try: lsof -i :${LOCAL_PORT}"
stop_at "Step 2"
fi
log " Container ${LOCAL_CONTAINER} started; waiting for server to come up ..."
CURL_OUTPUT=$(portable_mktemp "validate-curl")
CLEANUP_FILES+=("$CURL_OUTPUT")
HTTP_CODE="000"
for i in $(seq 1 30); do
HTTP_CODE=$(curl -s -o "$CURL_OUTPUT" -w "%{http_code}" -X POST \
-H "Content-Type: application/json" -d '{}' \
"$PING_URL/reset" --max-time 5 2>/dev/null || printf "000")
if [ "$HTTP_CODE" = "200" ]; then
break
fi
sleep 1
done
if [ "$HTTP_CODE" = "200" ]; then
pass "Local container responds to /reset on $PING_URL"
else
fail "Local container did not respond to /reset (last HTTP $HTTP_CODE)"
log " --- container logs (tail) ---"
docker logs "$LOCAL_CONTAINER" 2>&1 | tail -30
stop_at "Step 2"
fi
else
log "${BOLD}Step 2/3: Pinging HF Space${NC} ($PING_URL/reset) ..."
CURL_OUTPUT=$(portable_mktemp "validate-curl")
CLEANUP_FILES+=("$CURL_OUTPUT")
HTTP_CODE=$(curl -s -o "$CURL_OUTPUT" -w "%{http_code}" -X POST \
-H "Content-Type: application/json" -d '{}' \
"$PING_URL/reset" --max-time 30 2>"$CURL_OUTPUT" || printf "000")
if [ "$HTTP_CODE" = "200" ]; then
pass "HF Space is live and responds to /reset"
elif [ "$HTTP_CODE" = "000" ]; then
fail "HF Space not reachable (connection failed or timed out)"
hint "Check your network connection and that the Space is running."
hint "Try: curl -s -o /dev/null -w '%%{http_code}' -X POST $PING_URL/reset"
stop_at "Step 2"
else
fail "HF Space /reset returned HTTP $HTTP_CODE (expected 200)"
hint "Make sure your Space is running and the URL is correct."
hint "Try opening $PING_URL in your browser first."
stop_at "Step 2"
fi
fi
log "${BOLD}Step 3/3: Running openenv validate${NC} ..."
if ! command -v openenv &>/dev/null; then
fail "openenv command not found"
hint "Install it: pip install openenv-core"
stop_at "Step 3"
fi
VALIDATE_OK=false
VALIDATE_OUTPUT=$(cd "$REPO_DIR" && openenv validate 2>&1) && VALIDATE_OK=true
if [ "$VALIDATE_OK" = true ]; then
pass "openenv validate passed"
[ -n "$VALIDATE_OUTPUT" ] && log " $VALIDATE_OUTPUT"
else
fail "openenv validate failed"
printf "%s\n" "$VALIDATE_OUTPUT"
stop_at "Step 3"
fi
printf "\n"
printf "${BOLD}========================================${NC}\n"
printf "${GREEN}${BOLD} All 3/3 checks passed!${NC}\n"
printf "${GREEN}${BOLD} Your submission is ready to submit.${NC}\n"
printf "${BOLD}========================================${NC}\n"
printf "\n"
exit 0