9e8f1bbeed
Dashboard / frontend (push) Failing after 0s
Dashboard / api (push) Failing after 0s
Lint PowerShell / powershell-lint (ubuntu-latest) (push) Failing after 1s
Python Lint / Lint Python with Ruff (push) Failing after 1s
ShellCheck / Lint shell scripts (push) Failing after 1s
Matrix Smoke / linux-smoke (push) Failing after 1s
Matrix Smoke / distro: cachyos (push) Failing after 15s
Matrix Smoke / distro: linux-mint-21.3 (push) Failing after 15s
Matrix Smoke / distro: debian-12 (push) Failing after 5m21s
Matrix Smoke / distro: fedora-41 (push) Failing after 4m56s
Matrix Smoke / distro: ubuntu-24.04 (push) Failing after 2m13s
Matrix Smoke / distro: rocky-9 (push) Failing after 10m39s
Matrix Smoke / distro: manjaro (push) Failing after 12m11s
Matrix Smoke / distro: opensuse-tw (push) Failing after 11m53s
Matrix Smoke / distro: archlinux (push) Failing after 20m3s
Matrix Smoke / distro: ubuntu-22.04 (push) Failing after 13m49s
Validate .env Schema / tier-1-env-validation (push) Successful in 52s
Validate .env Schema / tier-2-env-validation (push) Successful in 44s
Validate .env Schema / tier-3-env-validation (push) Successful in 52s
Validate .env Schema / tier-4-env-validation (push) Successful in 51s
Validate Extensions Catalog / Check catalog is up-to-date (push) Failing after 9m47s
Secret Scan / Scan for secrets (push) Failing after 21m4s
Validate Docker Compose / Validate Docker Compose files (push) Has been cancelled
Python Type Check / Type check with mypy (push) Has been cancelled
Validate .env Schema / tier-0-env-validation (push) Has been cancelled
Test Linux / integration-smoke (push) Has been cancelled
Lint PowerShell / powershell-lint (windows-latest) (push) Has been cancelled
Matrix Smoke / macos-smoke (push) Has been cancelled
171 lines
5.2 KiB
Bash
Executable File
171 lines
5.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Regression: Docker full-model hot-swap failures must restore the last
|
|
# known-good model config and recreate llama-server from that config.
|
|
|
|
set -euo pipefail
|
|
|
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
TARGET="$ROOT_DIR/scripts/bootstrap-upgrade.sh"
|
|
|
|
fail() {
|
|
echo "[FAIL] $*" >&2
|
|
if [[ -n "${tmp:-}" ]]; then
|
|
[[ -f "$tmp/bootstrap.log" ]] && sed 's/^/[bootstrap] /' "$tmp/bootstrap.log" >&2
|
|
[[ -f "${install_dir:-}/.env" ]] && sed 's/^/[env] /' "$install_dir/.env" >&2
|
|
[[ -f "${install_dir:-}/config/llama-server/models.ini" ]] && sed 's/^/[models.ini] /' "$install_dir/config/llama-server/models.ini" >&2
|
|
[[ -f "${docker_calls:-}" ]] && sed 's/^/[docker] /' "$docker_calls" >&2
|
|
fi
|
|
exit 1
|
|
}
|
|
|
|
pass() {
|
|
echo "[PASS] $*"
|
|
}
|
|
|
|
tmp="$(mktemp -d)"
|
|
trap 'rm -rf "$tmp"' EXIT
|
|
|
|
fakebin="$tmp/bin"
|
|
install_dir="$tmp/install"
|
|
docker_calls="$tmp/docker-calls.log"
|
|
mkdir -p "$fakebin" "$install_dir/data/models" "$install_dir/config/llama-server"
|
|
|
|
cat > "$fakebin/curl" <<'EOF'
|
|
#!/usr/bin/env bash
|
|
case " $* " in
|
|
*" -sI "*)
|
|
printf 'HTTP/2 200\r\ncontent-length: 10\r\n\r\n'
|
|
exit 0
|
|
;;
|
|
esac
|
|
printf 'health:%s\n' "$*" >> "${ODS_FAKE_CURL_LOG:?}"
|
|
if [[ " $* " == *"11434/health"* ]] && grep -q '^GGUF_FILE=Bootstrap.gguf$' .env 2>/dev/null; then
|
|
printf '{"status":"ok"}\n'
|
|
exit 0
|
|
fi
|
|
exit 7
|
|
EOF
|
|
chmod +x "$fakebin/curl"
|
|
|
|
cat > "$fakebin/sleep" <<'EOF'
|
|
#!/usr/bin/env bash
|
|
exit 0
|
|
EOF
|
|
chmod +x "$fakebin/sleep"
|
|
|
|
cat > "$fakebin/uname" <<'EOF'
|
|
#!/usr/bin/env bash
|
|
printf 'Linux\n'
|
|
EOF
|
|
chmod +x "$fakebin/uname"
|
|
|
|
cat > "$fakebin/docker" <<'EOF'
|
|
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
env_value() {
|
|
local key="$1"
|
|
[[ -f .env ]] || return 0
|
|
grep -E "^${key}=" .env 2>/dev/null | head -1 | cut -d= -f2-
|
|
}
|
|
|
|
case "${1:-}" in
|
|
info)
|
|
exit 0
|
|
;;
|
|
compose)
|
|
if [[ "${2:-}" == "version" ]]; then
|
|
exit 0
|
|
fi
|
|
if [[ " $* " == *" up -d --force-recreate --no-deps llama-server "* ]]; then
|
|
printf 'compose-up:%s\n' "$(env_value GGUF_FILE)" >> "${ODS_FAKE_DOCKER_LOG:?}"
|
|
exit 0
|
|
fi
|
|
exit 0
|
|
;;
|
|
ps)
|
|
if [[ " $* " == *"name=ods-llama-server"* ]]; then
|
|
printf 'ods-llama-server\n'
|
|
fi
|
|
exit 0
|
|
;;
|
|
inspect)
|
|
if [[ "${2:-}" == "ods-llama-server" ]]; then
|
|
if [[ " $* " == *".State.Status"* ]]; then
|
|
printf 'restarting true 1\n'
|
|
exit 0
|
|
fi
|
|
printf '/app/llama-server --model /models/%s --ctx-size %s\n' \
|
|
"$(env_value GGUF_FILE)" "$(env_value CTX_SIZE)"
|
|
fi
|
|
exit 0
|
|
;;
|
|
esac
|
|
|
|
exit 0
|
|
EOF
|
|
chmod +x "$fakebin/docker"
|
|
|
|
cat > "$install_dir/.env" <<'EOF'
|
|
GGUF_FILE=Bootstrap.gguf
|
|
LLM_MODEL=bootstrap-model
|
|
MAX_CONTEXT=8192
|
|
CTX_SIZE=8192
|
|
GPU_BACKEND=nvidia
|
|
OLLAMA_PORT=11434
|
|
EOF
|
|
|
|
cat > "$install_dir/config/llama-server/models.ini" <<'EOF'
|
|
[bootstrap-model]
|
|
filename = Bootstrap.gguf
|
|
load-on-startup = true
|
|
n-ctx = 8192
|
|
EOF
|
|
|
|
cat > "$install_dir/.compose-flags" <<'EOF'
|
|
-f docker-compose.base.yml -f docker-compose.nvidia.yml
|
|
EOF
|
|
|
|
printf 'bootstrap\n' > "$install_dir/data/models/Bootstrap.gguf"
|
|
printf 'full-model\n' > "$install_dir/data/models/Full.gguf"
|
|
|
|
curl_calls="$tmp/curl-calls.log"
|
|
|
|
set +e
|
|
PATH="$fakebin:$PATH" ODS_FAKE_DOCKER_LOG="$docker_calls" ODS_FAKE_CURL_LOG="$curl_calls" bash "$TARGET" \
|
|
"$install_dir" \
|
|
"Full.gguf" \
|
|
"https://example.invalid/Full.gguf" \
|
|
"" \
|
|
"full-model" \
|
|
"32768" \
|
|
"Bootstrap.gguf" \
|
|
> "$tmp/bootstrap.log" 2>&1
|
|
rc=$?
|
|
set -e
|
|
|
|
[[ $rc -ne 0 ]] || fail "bootstrap-upgrade must fail when Docker llama-server never becomes healthy"
|
|
grep -q '^GGUF_FILE=Bootstrap.gguf$' "$install_dir/.env" \
|
|
|| fail "Docker hot-swap failure must restore previous GGUF_FILE"
|
|
grep -q '^LLM_MODEL=bootstrap-model$' "$install_dir/.env" \
|
|
|| fail "Docker hot-swap failure must restore previous LLM_MODEL"
|
|
grep -q '^CTX_SIZE=8192$' "$install_dir/.env" \
|
|
|| fail "Docker hot-swap failure must restore previous CTX_SIZE"
|
|
grep -q 'filename = Bootstrap.gguf' "$install_dir/config/llama-server/models.ini" \
|
|
|| fail "Docker hot-swap failure must restore previous models.ini"
|
|
grep -q 'compose-up:Full.gguf' "$docker_calls" \
|
|
|| fail "test did not exercise the full-model compose recreate"
|
|
grep -q 'compose-up:Bootstrap.gguf' "$docker_calls" \
|
|
|| fail "rollback must recreate llama-server from the restored bootstrap config"
|
|
grep -q 'Restoring previous active model config after Docker llama-server swap failure' "$tmp/bootstrap.log" \
|
|
|| fail "bootstrap-upgrade should log the Docker rollback"
|
|
grep -q 'llama-server container exited or is restarting while loading the full model' "$tmp/bootstrap.log" \
|
|
|| fail "bootstrap-upgrade should detect a failed llama-server container before waiting for the full health timeout"
|
|
health_attempts=$(grep -c '^health:' "$curl_calls" 2>/dev/null || true)
|
|
[[ "$health_attempts" -lt 60 ]] \
|
|
|| fail "failed Docker hot-swap should not wait for all health attempts after the container is restarting"
|
|
grep -q '"status": "failed"' "$install_dir/data/bootstrap-status.json" \
|
|
|| fail "failed Docker hot-swap must mark bootstrap-status failed"
|
|
|
|
pass "Docker hot-swap failure restores previous active model config"
|