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
113 lines
4.7 KiB
Bash
113 lines
4.7 KiB
Bash
#!/usr/bin/env bash
|
|
# Regression checks for Linux cloud mode. Cloud/external LLM installs must not
|
|
# require a local llama-server container or local-mode dependency overlays.
|
|
|
|
set -euo pipefail
|
|
|
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
cd "$ROOT_DIR"
|
|
|
|
pass() { printf '[PASS] %s\n' "$1"; }
|
|
fail() { printf '[FAIL] %s\n' "$1" >&2; exit 1; }
|
|
|
|
contains() {
|
|
local haystack="$1" needle="$2" label="$3"
|
|
[[ "$haystack" == *"$needle"* ]] && pass "$label" || fail "$label"
|
|
}
|
|
|
|
rejects() {
|
|
local haystack="$1" needle="$2" label="$3"
|
|
[[ "$haystack" != *"$needle"* ]] && pass "$label" || fail "$label"
|
|
}
|
|
|
|
PY="${ODS_PYTHON_CMD:-}"
|
|
if [[ -z "$PY" ]]; then
|
|
if command -v python3 >/dev/null 2>&1; then
|
|
PY=python3
|
|
elif command -v python >/dev/null 2>&1; then
|
|
PY=python
|
|
else
|
|
fail "python is required"
|
|
fi
|
|
fi
|
|
|
|
flags="$(ODS_PYTHON_CMD="$PY" ./scripts/resolve-compose-stack.sh \
|
|
--script-dir "$ROOT_DIR" \
|
|
--tier CLOUD \
|
|
--gpu-backend cpu \
|
|
--gpu-count 0 \
|
|
--ods-mode cloud)"
|
|
flags="${flags//\\//}"
|
|
|
|
contains "$flags" "docker-compose.base.yml" "cloud mode keeps base stack"
|
|
contains "$flags" "docker-compose.cloud.yml" "cloud mode layers cloud overlay"
|
|
contains "$flags" "extensions/services/litellm/compose.yaml" "cloud mode includes LiteLLM gateway"
|
|
rejects "$flags" "docker-compose.cpu.yml" "cloud mode does not include CPU llama-server overlay"
|
|
rejects "$flags" "compose.local.yaml" "cloud mode does not include local dependency overlays"
|
|
|
|
lemonade_flags="$(LEMONADE_EXTERNAL=true AMD_INFERENCE_RUNTIME=lemonade AMD_INFERENCE_MANAGED=false ODS_PYTHON_CMD="$PY" ./scripts/resolve-compose-stack.sh \
|
|
--script-dir "$ROOT_DIR" \
|
|
--tier CLOUD \
|
|
--gpu-backend cpu \
|
|
--gpu-count 0 \
|
|
--ods-mode lemonade)"
|
|
lemonade_flags="${lemonade_flags//\\//}"
|
|
|
|
contains "$lemonade_flags" "docker-compose.base.yml" "external Lemonade keeps base stack"
|
|
contains "$lemonade_flags" "docker-compose.cloud.yml" "external Lemonade profiles managed llama-server out"
|
|
contains "$lemonade_flags" "docker-compose.lemonade-external.yml" "external Lemonade layers dedicated overlay"
|
|
rejects "$lemonade_flags" "docker-compose.cpu.yml" "external Lemonade does not include CPU llama-server overlay"
|
|
|
|
if grep -q 'profiles:' docker-compose.cloud.yml && grep -q 'local-inference' docker-compose.cloud.yml; then
|
|
pass "cloud overlay profiles local llama-server out of default startup"
|
|
else
|
|
fail "cloud overlay must profile local llama-server out of default startup"
|
|
fi
|
|
|
|
if grep -Fq -- '--ods-mode "${ODS_MODE:-local}"' installers/lib/compose-select.sh \
|
|
&& grep -Fq -- '--ods-mode "${ODS_MODE:-local}"' installers/phases/03-features.sh \
|
|
&& grep -Fq -- '--ods-mode "${ODS_MODE:-local}"' installers/phases/11-services.sh \
|
|
&& grep -Fq -- '--ods-mode "${ODS_MODE:-local}"' ods-cli; then
|
|
pass "installer and CLI pass ods mode to compose resolver"
|
|
else
|
|
fail "all installer/CLI resolver calls must pass --ods-mode"
|
|
fi
|
|
|
|
if grep -q 'ODS_MODE:-local.*cloud' installers/phases/12-health.sh \
|
|
&& grep -Fq 'LiteLLM' installers/phases/12-health.sh \
|
|
&& grep -Fq 'skipping local llama-server pre-warm' installers/phases/12-health.sh; then
|
|
pass "cloud health path skips local llama-server"
|
|
else
|
|
fail "cloud health path must skip local llama-server"
|
|
fi
|
|
|
|
if grep -Fq 'image: ${HERMES_AGENT_IMAGE:-nousresearch/hermes-agent:v2026.5.16}' extensions/services/hermes/compose.yaml \
|
|
&& grep -Fq '${HERMES_AGENT_IMAGE:-nousresearch/hermes-agent:v2026.5.16}|HERMES' installers/phases/08-images.sh \
|
|
&& grep -Fq 'HERMES_AGENT_IMAGE_FALLBACK' installers/phases/08-images.sh \
|
|
&& ! grep -R -q 'nousresearch/hermes-agent:sha-' extensions/services/hermes installers/phases config/dependency-lock.json; then
|
|
pass "Hermes image default is resolvable and overrideable for cloud installs"
|
|
else
|
|
fail "Hermes image default must not rely on removed sha-* Docker tags"
|
|
fi
|
|
|
|
"$PY" - "$ROOT_DIR" <<'PY'
|
|
from pathlib import Path
|
|
import sys
|
|
|
|
root = Path(sys.argv[1])
|
|
text = (root / "installers/phases/11-services.sh").read_text(encoding="utf-8")
|
|
model_config = text.index('mkdir -p "$INSTALL_DIR/config/llama-server"')
|
|
hermes_block = text.index('if [[ "${ENABLE_HERMES:-false}" == "true" ]]; then')
|
|
soul_block = text.index('_soul_output="$INSTALL_DIR/data/persona/SOUL.md"')
|
|
if model_config < hermes_block < soul_block:
|
|
# Make sure the local-model block was closed before Hermes/SOUL rendering begins.
|
|
between = text[model_config:hermes_block]
|
|
if '\n fi\n' in between:
|
|
print("[PASS] SOUL.md render is outside local-model-only block")
|
|
sys.exit(0)
|
|
print("[FAIL] SOUL.md render must run for cloud installs too", file=sys.stderr)
|
|
sys.exit(1)
|
|
PY
|
|
|
|
echo "[PASS] linux cloud mode contracts"
|