-
-
Notifications
You must be signed in to change notification settings - Fork 39
installer: Docker Compose v2 not installable on Debian bookworm ARM64 - store apps will silently fail #2991
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| ### Fixed | ||
|
|
||
| - Installer: Docker Compose v2 now uses Docker's official apt repository when Debian bookworm ARM64 lacks distro Compose packages, and installer and UI health checks report Compose failures loudly. |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -54,6 +54,9 @@ TAOS_BUS_PORT="${TAOS_BUS_PORT:-7900}" | |||||||||||||||||||
| SERVICE_MODE="${TAOS_SERVICE:-auto}" | ||||||||||||||||||||
| COW_POOL_MODE="${TAOS_COW_POOL:-auto}" | ||||||||||||||||||||
|
|
||||||||||||||||||||
| DOCKER_COMPOSE_STATUS="unknown" | ||||||||||||||||||||
| DOCKER_COMPOSE_DETAIL="" | ||||||||||||||||||||
|
|
||||||||||||||||||||
| os_name="$(uname -s)" | ||||||||||||||||||||
| arch="$(uname -m)" | ||||||||||||||||||||
|
|
||||||||||||||||||||
|
|
@@ -1038,6 +1041,53 @@ _apt_install_compose() { | |||||||||||||||||||
| fi | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| _install_compose_v2() { | ||||||||||||||||||||
| if command -v apt-get >/dev/null 2>&1; then | ||||||||||||||||||||
| _apt_install_compose | ||||||||||||||||||||
| local _apt_compose_rc=$? | ||||||||||||||||||||
| if (( _apt_compose_rc == 0 )); then | ||||||||||||||||||||
| DOCKER_COMPOSE_STATUS="installed" | ||||||||||||||||||||
| DOCKER_COMPOSE_DETAIL="distro apt package" | ||||||||||||||||||||
| return 0 | ||||||||||||||||||||
| fi | ||||||||||||||||||||
| if (( _apt_compose_rc == 2 )); then | ||||||||||||||||||||
| log "compose plugin not in distro apt -- trying Docker's official apt repo" | ||||||||||||||||||||
| if _apt_install_docker_official_repo; then | ||||||||||||||||||||
| DOCKER_COMPOSE_STATUS="installed" | ||||||||||||||||||||
| DOCKER_COMPOSE_DETAIL="Docker official apt repo" | ||||||||||||||||||||
| return 0 | ||||||||||||||||||||
| fi | ||||||||||||||||||||
| else | ||||||||||||||||||||
| warn "apt install of the Docker Compose v2 plugin failed -- Store Docker apps will be unavailable" | ||||||||||||||||||||
| fi | ||||||||||||||||||||
| elif command -v dnf >/dev/null 2>&1; then | ||||||||||||||||||||
| if sudo dnf install -y -q docker-compose; then | ||||||||||||||||||||
| DOCKER_COMPOSE_STATUS="installed" | ||||||||||||||||||||
| DOCKER_COMPOSE_DETAIL="dnf package" | ||||||||||||||||||||
| return 0 | ||||||||||||||||||||
| fi | ||||||||||||||||||||
| elif command -v pacman >/dev/null 2>&1; then | ||||||||||||||||||||
| if sudo pacman -Sy --noconfirm --needed docker-compose; then | ||||||||||||||||||||
| DOCKER_COMPOSE_STATUS="installed" | ||||||||||||||||||||
| DOCKER_COMPOSE_DETAIL="pacman package" | ||||||||||||||||||||
| return 0 | ||||||||||||||||||||
| fi | ||||||||||||||||||||
| elif command -v apk >/dev/null 2>&1; then | ||||||||||||||||||||
| if sudo apk add --no-cache docker-cli-compose; then | ||||||||||||||||||||
| DOCKER_COMPOSE_STATUS="installed" | ||||||||||||||||||||
| DOCKER_COMPOSE_DETAIL="apk package" | ||||||||||||||||||||
| return 0 | ||||||||||||||||||||
| fi | ||||||||||||||||||||
| else | ||||||||||||||||||||
| warn "unrecognised package manager -- cannot install Docker Compose v2" | ||||||||||||||||||||
| fi | ||||||||||||||||||||
|
|
||||||||||||||||||||
| DOCKER_COMPOSE_STATUS="unavailable" | ||||||||||||||||||||
| DOCKER_COMPOSE_DETAIL="compose installation failed" | ||||||||||||||||||||
| warn "Docker Compose v2 is unavailable -- Store Docker apps will fail" | ||||||||||||||||||||
| return 1 | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| # Undo one apt file touched by the Docker official-repo fallback below. | ||||||||||||||||||||
| # $1 = path, $2 = backup path ("" when the file did NOT pre-exist), | ||||||||||||||||||||
| # $3 = 1 when THIS invocation created the file. | ||||||||||||||||||||
|
|
@@ -1262,13 +1312,17 @@ _apt_install_docker_official_repo() { | |||||||||||||||||||
|
|
||||||||||||||||||||
| ensure_docker_for_apps() { | ||||||||||||||||||||
| if [[ "${TAOS_SKIP_DOCKER:-0}" == "1" ]]; then | ||||||||||||||||||||
| log "TAOS_SKIP_DOCKER=1 — skipping Docker (Store Docker apps will be unavailable)" | ||||||||||||||||||||
| DOCKER_COMPOSE_STATUS="skipped" | ||||||||||||||||||||
| DOCKER_COMPOSE_DETAIL="TAOS_SKIP_DOCKER=1" | ||||||||||||||||||||
| log "TAOS_SKIP_DOCKER=1 -- skipping Docker (Store Docker apps will be unavailable)" | ||||||||||||||||||||
| return 0 | ||||||||||||||||||||
| fi | ||||||||||||||||||||
| # macOS: the Docker Engine can't run natively (it needs a Linux VM), so the | ||||||||||||||||||||
| # server doesn't install it here — agents use the Apple Containerization | ||||||||||||||||||||
| # framework, and Docker apps need a user-provided Docker (Desktop/colima). | ||||||||||||||||||||
| if [[ "$(uname -s)" == "Darwin" ]]; then | ||||||||||||||||||||
| DOCKER_COMPOSE_STATUS="unavailable" | ||||||||||||||||||||
| DOCKER_COMPOSE_DETAIL="Docker Desktop or colima required" | ||||||||||||||||||||
|
Comment on lines
+1324
to
+1325
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Detect Compose before reporting it as unavailable on macOS. If Docker Desktop or Colima is already installed, Proposed fix if [[ "$(uname -s)" == "Darwin" ]]; then
- DOCKER_COMPOSE_STATUS="unavailable"
- DOCKER_COMPOSE_DETAIL="Docker Desktop or colima required"
+ if docker compose version >/dev/null 2>&1; then
+ DOCKER_COMPOSE_STATUS="installed"
+ DOCKER_COMPOSE_DETAIL="docker compose version succeeded"
+ else
+ DOCKER_COMPOSE_STATUS="unavailable"
+ DOCKER_COMPOSE_DETAIL="Docker Desktop or colima required"
+ fi📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||
| command -v docker >/dev/null 2>&1 \ | ||||||||||||||||||||
| && log "macOS: using existing Docker ($(docker --version 2>/dev/null | head -1))" \ | ||||||||||||||||||||
| || log "macOS: provide Docker (Desktop or colima) for Store Docker apps; agents use Apple Containerization" | ||||||||||||||||||||
|
|
@@ -1292,65 +1346,42 @@ ensure_docker_for_apps() { | |||||||||||||||||||
| if (( had_docker )); then | ||||||||||||||||||||
| log "docker present: $(docker --version 2>/dev/null | head -1)" | ||||||||||||||||||||
| else | ||||||||||||||||||||
| # Install the engine AND the Compose v2 plugin — taOS deploys Store | ||||||||||||||||||||
| # Docker apps via `docker compose`, and most distro 'docker' packages | ||||||||||||||||||||
| # (e.g. Ubuntu's docker.io) don't bundle compose, which otherwise fails | ||||||||||||||||||||
| # with "unknown command: docker compose". | ||||||||||||||||||||
| log "installing Docker Engine + Compose plugin (for Store Docker apps)" | ||||||||||||||||||||
| log "installing Docker Engine (for Store Docker apps)" | ||||||||||||||||||||
| if command -v apt-get >/dev/null 2>&1; then | ||||||||||||||||||||
| # Install the engine and the compose plugin in SEPARATE apt | ||||||||||||||||||||
| # transactions: bundling them meant a missing compose package name | ||||||||||||||||||||
| # (see _apt_install_compose below) failed the whole transaction and | ||||||||||||||||||||
| # left the box without Docker at all (#1541). | ||||||||||||||||||||
| sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq docker.io \ | ||||||||||||||||||||
| || warn "apt install docker.io failed — Store Docker apps will be unavailable" | ||||||||||||||||||||
| # _apt_install_compose distinguishes missing-package (rc=2) | ||||||||||||||||||||
| # from install-failure (rc=1). Only the missing-package case | ||||||||||||||||||||
| # means the distro archive has no compose plugin to offer -- | ||||||||||||||||||||
| # Debian trixie / Armbian trixie (taOS#2). Anything else is a | ||||||||||||||||||||
| # real apt error and must NOT silently swap to Docker's repo. | ||||||||||||||||||||
| _apt_install_compose | ||||||||||||||||||||
| _apt_compose_rc=$? | ||||||||||||||||||||
| if (( _apt_compose_rc == 2 )); then | ||||||||||||||||||||
| log "compose plugin not in distro apt — trying Docker's official apt repo" | ||||||||||||||||||||
| if ! _apt_install_docker_official_repo; then | ||||||||||||||||||||
| warn "Docker Engine + Compose plugin are unavailable on this host (Store Docker apps will be unavailable)" | ||||||||||||||||||||
| fi | ||||||||||||||||||||
| elif (( _apt_compose_rc != 0 )); then | ||||||||||||||||||||
| warn "compose plugin install failed -- Store Docker apps will be unavailable" | ||||||||||||||||||||
| fi | ||||||||||||||||||||
| || warn "apt install docker.io failed -- Store Docker apps will be unavailable" | ||||||||||||||||||||
| elif command -v dnf >/dev/null 2>&1; then | ||||||||||||||||||||
| sudo dnf install -y -q moby-engine docker-compose \ | ||||||||||||||||||||
| || warn "dnf install moby-engine/docker-compose failed — Store Docker apps will be unavailable" | ||||||||||||||||||||
| sudo dnf install -y -q moby-engine \ | ||||||||||||||||||||
| || warn "dnf install moby-engine failed -- Store Docker apps will be unavailable" | ||||||||||||||||||||
| elif command -v pacman >/dev/null 2>&1; then | ||||||||||||||||||||
| sudo pacman -Sy --noconfirm --needed docker docker-compose \ | ||||||||||||||||||||
| || warn "pacman install docker/docker-compose failed — Store Docker apps will be unavailable" | ||||||||||||||||||||
| sudo pacman -Sy --noconfirm --needed docker \ | ||||||||||||||||||||
| || warn "pacman install docker failed -- Store Docker apps will be unavailable" | ||||||||||||||||||||
| elif command -v apk >/dev/null 2>&1; then | ||||||||||||||||||||
| sudo apk add --no-cache docker docker-cli-compose \ | ||||||||||||||||||||
| || warn "apk add docker/docker-cli-compose failed — Store Docker apps will be unavailable" | ||||||||||||||||||||
| sudo apk add --no-cache docker \ | ||||||||||||||||||||
| || warn "apk add docker failed -- Store Docker apps will be unavailable" | ||||||||||||||||||||
| else | ||||||||||||||||||||
| warn "unrecognised package manager — install Docker + the compose plugin manually for Store Docker apps" | ||||||||||||||||||||
| warn "unrecognised package manager -- install Docker manually for Store Docker apps" | ||||||||||||||||||||
| DOCKER_COMPOSE_STATUS="unavailable" | ||||||||||||||||||||
| DOCKER_COMPOSE_DETAIL="Docker engine unavailable" | ||||||||||||||||||||
| return 0 | ||||||||||||||||||||
| fi | ||||||||||||||||||||
| fi | ||||||||||||||||||||
|
|
||||||||||||||||||||
| # Ensure the Compose v2 plugin (taOS deploys apps via `docker compose`). | ||||||||||||||||||||
| # This also covers the case where Docker was ALREADY installed but without | ||||||||||||||||||||
| # the plugin — the fresh-install branch above bundles it, but a pre-existing | ||||||||||||||||||||
| # Docker (the `had_docker` path) may lack it, so install it here too. | ||||||||||||||||||||
| if ! docker compose version >/dev/null 2>&1; then | ||||||||||||||||||||
| if docker compose version >/dev/null 2>&1; then | ||||||||||||||||||||
| DOCKER_COMPOSE_STATUS="installed" | ||||||||||||||||||||
| DOCKER_COMPOSE_DETAIL="docker compose version succeeded" | ||||||||||||||||||||
| else | ||||||||||||||||||||
| log "installing the Docker Compose v2 plugin" | ||||||||||||||||||||
| if command -v apt-get >/dev/null 2>&1; then | ||||||||||||||||||||
| _apt_install_compose || true | ||||||||||||||||||||
| elif command -v dnf >/dev/null 2>&1; then | ||||||||||||||||||||
| sudo dnf install -y -q docker-compose || true | ||||||||||||||||||||
| elif command -v pacman >/dev/null 2>&1; then | ||||||||||||||||||||
| sudo pacman -Sy --noconfirm --needed docker-compose || true | ||||||||||||||||||||
| elif command -v apk >/dev/null 2>&1; then | ||||||||||||||||||||
| sudo apk add --no-cache docker-cli-compose || true | ||||||||||||||||||||
| _install_compose_v2 || true | ||||||||||||||||||||
| if ! docker compose version >/dev/null 2>&1; then | ||||||||||||||||||||
| DOCKER_COMPOSE_STATUS="unavailable" | ||||||||||||||||||||
| DOCKER_COMPOSE_DETAIL="docker compose version failed" | ||||||||||||||||||||
| warn "the 'docker compose' plugin isn't available -- Store Docker apps need it (install docker-compose-v2 / docker-compose-plugin manually)" | ||||||||||||||||||||
| else | ||||||||||||||||||||
| DOCKER_COMPOSE_STATUS="installed" | ||||||||||||||||||||
| DOCKER_COMPOSE_DETAIL="docker compose version succeeded" | ||||||||||||||||||||
| fi | ||||||||||||||||||||
| docker compose version >/dev/null 2>&1 \ | ||||||||||||||||||||
| || warn "the 'docker compose' plugin isn't available — Store Docker apps need it (install docker-compose-v2 / docker-compose-plugin manually)" | ||||||||||||||||||||
| fi | ||||||||||||||||||||
|
|
||||||||||||||||||||
| command -v docker >/dev/null 2>&1 || { warn "docker not on PATH after install — skipping daemon/group setup"; return 0; } | ||||||||||||||||||||
|
|
@@ -2795,6 +2826,16 @@ if [[ "$TAOS_BROWSER_PROXY_PORT" != "0" ]]; then | |||||||||||||||||||
| fi | ||||||||||||||||||||
| log " Install dir : $INSTALL_DIR" | ||||||||||||||||||||
| log " Storage pool: ${COW_EFFECTIVE_MODE:-n/a} (detected fs: ${COW_FS_TYPE:-unknown})" | ||||||||||||||||||||
| if [[ "$DOCKER_COMPOSE_STATUS" == "installed" ]]; then | ||||||||||||||||||||
| log " Docker Compose v2: available" | ||||||||||||||||||||
| elif [[ "$DOCKER_COMPOSE_STATUS" == "skipped" ]]; then | ||||||||||||||||||||
| log " Docker Compose v2: skipped (TAOS_SKIP_DOCKER=1)" | ||||||||||||||||||||
| else | ||||||||||||||||||||
| warn "=== DOCKER COMPOSE V2 SUMMARY ===" | ||||||||||||||||||||
| warn " Docker Compose v2: UNAVAILABLE -- Store Docker apps will fail" | ||||||||||||||||||||
| warn " Reason: ${DOCKER_COMPOSE_DETAIL:-compose status unknown}" | ||||||||||||||||||||
| warn " Install docker-compose-plugin or docker-compose-v2 manually, then rerun the installer." | ||||||||||||||||||||
| fi | ||||||||||||||||||||
| # Surface what the controller actually detected so a tester can confirm at | ||||||||||||||||||||
| # a glance (taOS #2 -- installer used to silently skip, so testers had no | ||||||||||||||||||||
| # way to tell whether the NPU was recognised). HW_PROFILE_ID/HW_NPU_TYPE | ||||||||||||||||||||
|
|
||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -147,7 +147,7 @@ echo "test: trixie fallback installs docker-ce + plugin from Docker's repo" | |
| grep -q "docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin" "$SCRIPT" | ||
|
|
||
| echo "test: trixie fallback is gated on the missing-package rc==2, not on a generic failure" | ||
| grep -A 6 "_apt_install_compose" "$SCRIPT" \ | ||
| grep -A 15 "_install_compose_v2" "$SCRIPT" \ | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WARNING: Test at line 159 searches for The change from Reply with |
||
| | grep -q "_apt_compose_rc == 2" | ||
|
|
||
| echo "test: trixie fallback does NOT trigger on a generic install failure" | ||
|
|
@@ -224,6 +224,11 @@ grep -A4 'Docker apt key fingerprint mismatch' "$SCRIPT" \ | |
| echo "test: ensure_docker_for_apps call site tolerates fallback failure (no set -e abort)" | ||
| ensure_docker_call_line=$(grep -n "ensure_docker_for_apps || warn" "$SCRIPT" | head -1 | cut -d: -f1) | ||
| (( ensure_docker_call_line > 0 )) | ||
|
|
||
| echo "test: Compose v2 failure is tracked for the installer summary" | ||
| grep -q 'DOCKER_COMPOSE_STATUS="unavailable"' "$SCRIPT" | ||
| grep -q 'Docker Compose v2: UNAVAILABLE' "$SCRIPT" | ||
|
|
||
| # ── Controller readiness wait (taOS#2) ───────────────────────────────── | ||
|
|
||
| echo "test: controller wait uses a 240 s ready timeout" | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -118,6 +118,89 @@ def _extract_func(name: str) -> str: | |
| """ | ||
|
|
||
|
|
||
| def _run_preexisting_docker_compose_path(tmp_path): | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. SUGGESTION: Test not hermetic w.r.t.
Reply with |
||
| script = "\n".join([ | ||
| "set -euo pipefail", | ||
| "log() { printf '[log] %s\\n' \"$*\" >&2; }", | ||
| "warn() { printf '[warn] %s\\n' \"$*\" >&2; }", | ||
| "sudo() {", | ||
| " while [[ $# -gt 0 ]]; do", | ||
| " case \"$1\" in", | ||
| " [A-Z_]*=*) shift; continue ;;", | ||
| " esac", | ||
| " break", | ||
| " done", | ||
| " \"$@\"", | ||
| "}", | ||
| "uname() { echo Linux; }", | ||
| "apt-cache() { return 1; }", | ||
| "apt-get() { return 0; }", | ||
| "systemctl() { return 0; }", | ||
| "compose_available=0", | ||
| "OFFICIAL_REPO_CALLED=0", | ||
| "docker() {", | ||
| " case \"${1:-}\" in", | ||
| " --version) echo 'Docker version 27.0.0' ;;", | ||
| " info) return 0 ;;", | ||
| " compose)", | ||
| " if [[ \"${2:-}\" == version && \"$compose_available\" == 1 ]]; then", | ||
| " echo 'Docker Compose version v2.30.0'", | ||
| " return 0", | ||
| " fi", | ||
| " echo \"docker: 'compose' is not a docker command\" >&2", | ||
| " return 1", | ||
| " ;;", | ||
| " esac", | ||
| "}", | ||
| "_docker_running() { sudo docker info; }", | ||
| _extract_func("_apt_install_compose"), | ||
| _extract_func("_install_compose_v2"), | ||
| _extract_func("ensure_docker_for_apps"), | ||
| "_apt_install_docker_official_repo() {", | ||
| " OFFICIAL_REPO_CALLED=1", | ||
| " compose_available=1", | ||
| "}", | ||
| "ensure_rc=0", | ||
| "ensure_docker_for_apps || ensure_rc=$?", | ||
| "compose_rc=0", | ||
| "docker compose version >/dev/null 2>&1 || compose_rc=$?", | ||
| "printf 'ensure_rc=%s official_repo_called=%s compose_rc=%s\\n' \\", | ||
| " \"$ensure_rc\" \"$OFFICIAL_REPO_CALLED\" \"$compose_rc\"", | ||
| ]) | ||
| proc = subprocess.run( | ||
| ["bash", "-c", script], | ||
| capture_output=True, | ||
| text=True, | ||
| env={**os.environ, "USER": "root", "SUDO_USER": "root", "arch": "aarch64"}, | ||
| timeout=30, | ||
| ) | ||
| assert "ensure_rc=" in proc.stdout, ( | ||
| f"ensure_docker_for_apps never completed.\nstdout={proc.stdout}\nstderr={proc.stderr}" | ||
| ) | ||
| values = dict( | ||
| item.split("=", 1) | ||
| for item in proc.stdout.strip().split() | ||
| if "=" in item | ||
| ) | ||
| return proc, {key: int(value) for key, value in values.items()} | ||
|
|
||
|
|
||
| @pytest.mark.skipif(os.name != "posix", reason="bash-only test") | ||
| def test_bookworm_arm64_preexisting_docker_gets_compose_from_official_repo(tmp_path): | ||
| proc, values = _run_preexisting_docker_compose_path(tmp_path) | ||
|
|
||
| assert proc.returncode == 0, f"wrapper failed: {proc.stderr}" | ||
| assert values["ensure_rc"] == 0, f"installer Docker setup failed: {proc.stderr}" | ||
| assert values["official_repo_called"] == 1, ( | ||
| "a pre-existing Docker install with no distro Compose package must use " | ||
| f"Docker's official repo fallback; stdout={proc.stdout!r} stderr={proc.stderr!r}" | ||
| ) | ||
| assert values["compose_rc"] == 0, ( | ||
| "bookworm ARM64-shaped path left 'docker compose' unavailable; " | ||
| f"stdout={proc.stdout!r} stderr={proc.stderr!r}" | ||
| ) | ||
|
|
||
|
|
||
| def _run_fallback( | ||
| tmp_path, | ||
| *, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -291,6 +291,24 @@ async def _check_docker() -> dict: | |
| return {"status": "error", "detail": str(e)} | ||
|
|
||
|
|
||
| async def _check_docker_compose() -> dict: | ||
| """Check the Docker Compose v2 plugin used by Store apps.""" | ||
| try: | ||
| proc = await asyncio.create_subprocess_exec( | ||
| "docker", "compose", "version", | ||
| stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, | ||
| ) | ||
| stdout, stderr = await asyncio.wait_for(proc.communicate(), timeout=5) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win 🔎 Supported by static analysis🏁 Script executed: #!/bin/bash
set -euo pipefail
# Resolve the repository-declared Python target before using its interpreter.
fd -a -t f 'pyproject.toml' '.python-version' 'tox.ini' 'setup.cfg' | while IFS= read -r file; do
echo "== $file =="
rg -n 'requires-python|python_requires|python_version|target-version' "$file" || true
done
# With that declared interpreter, verify that timing out communicate() leaves
# the child alive until the caller explicitly terminates it.
python - <<'PY'
import asyncio
async def probe():
proc = await asyncio.create_subprocess_exec("sleep", "30")
try:
await asyncio.wait_for(proc.communicate(), timeout=0.01)
except asyncio.TimeoutError:
print(f"returncode_after_timeout={proc.returncode!r}")
proc.kill()
await proc.communicate()
asyncio.run(probe())
PYRepository: jaylfc/taOS Length of output: 362 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== candidate files =='
fd -a -t f 'dashboard.py|pyproject.toml|.python-version|tox.ini|setup.cfg' . || true
printf '%s\n' '== dashboard.py outline =='
ast-grep outline tinyagentos/routes/dashboard.py
printf '%s\n' '== relevant source =='
sed -n '260,325p' tinyagentos/routes/dashboard.py
printf '%s\n' '== subprocess and timeout bindings =='
rg -n -C 3 'create_subprocess|communicate|wait_for|TimeoutError|docker compose' tinyagentos/routes/dashboard.pyRepository: jaylfc/taOS Length of output: 6523 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== declared Python target =='
rg -n -C 2 'requires-python|python_requires|python_version|target-version' pyproject.toml || true
printf '%s\n' '== timeout behavior probe =='
python3 - <<'PY'
import asyncio
async def probe():
proc = await asyncio.create_subprocess_exec(
"sleep", "30",
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
)
try:
await asyncio.wait_for(proc.communicate(), timeout=0.01)
except asyncio.TimeoutError:
print(f"returncode_after_timeout={proc.returncode!r}")
proc.kill()
await proc.communicate()
asyncio.run(probe())
PYRepository: jaylfc/taOS Length of output: 530 Terminate the Compose process after a timeout. When 🤖 Prompt for AI Agents |
||
| if proc.returncode == 0: | ||
| return {"status": "ok", "detail": f"Docker Compose {stdout.decode().strip()}"} | ||
| detail = stderr.decode().strip()[:200] | ||
| return {"status": "error", "detail": detail or "Docker Compose v2 is unavailable"} | ||
| except FileNotFoundError: | ||
| return {"status": "unavailable", "detail": "Docker Compose v2 not installed"} | ||
| except Exception as e: | ||
| return {"status": "error", "detail": str(e)} | ||
|
|
||
|
|
||
| @router.get("/api/health-check") | ||
| async def api_health_check(request: Request): | ||
| """Run all health checks and return results.""" | ||
|
|
@@ -307,7 +325,10 @@ async def api_health_check(request: Request): | |
| # 3. Docker | ||
| checks.append(await _timed_check("Docker", _check_docker())) | ||
|
|
||
| # 4. Each backend | ||
| # 4. Docker Compose v2 | ||
| checks.append(await _timed_check("Docker Compose v2", _check_docker_compose())) | ||
|
|
||
| # 5. Each backend | ||
| for backend in config.backends: | ||
| name = f"Backend: {backend.get('name', backend.get('url', 'unknown'))}" | ||
|
|
||
|
|
@@ -317,7 +338,7 @@ async def _check_backend(b=backend): | |
|
|
||
| checks.append(await _timed_check(name, _check_backend())) | ||
|
|
||
| # 5. QMD | ||
| # 6. QMD | ||
| async def _check_qmd(): | ||
| qmd = request.app.state.qmd_client | ||
| result = await qmd.health() | ||
|
|
@@ -333,7 +354,7 @@ async def _check_qmd(): | |
| # already covered by the "QMD Server" check above. See | ||
| # docs/design/framework-agnostic-runtime.md. | ||
|
|
||
| # 6. Disk space | ||
| # 7. Disk space | ||
| disk = shutil.disk_usage("/") | ||
| disk_pct = (disk.used / disk.total) * 100 | ||
| disk_status = "ok" if disk_pct < 85 else ("warning" if disk_pct < 95 else "error") | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WARNING: Missing warning when Docker official repo fallback fails after missing-package rc==2
When
_apt_install_composereturns 2 (package not in distro) and_apt_install_docker_official_repoalso fails, the code falls through silently to the final "unavailable" block without warning that the official repo fallback was attempted and failed.Reply with
@kilocode-bot fix itto have Kilo Code address this issue.