From 348d97488ab675fd5fb0eeec2d097d1445c84c40 Mon Sep 17 00:00:00 2001 From: Dymas Date: Sun, 19 Jul 2026 14:40:03 +0200 Subject: [PATCH] Fix fallback dependency detection --- CHANGELOG.md | 5 +++++ Dockerfile | 1 + README.md | 4 ++-- VERSION | 2 +- app_support.py | 4 ++++ http_handler.py | 15 +++++++++++++-- test_app.py | 20 ++++++++++++++++++++ 7 files changed, 46 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44ec96d..8bb321a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 0.49.2 - 2026-07-19 + +- Fixed the Config page dependency check so Docker-installed fallback tools are detected from `/usr/local/bin` and `/usr/bin`, matching the runtime command lookup. +- Set the Docker image `PATH` explicitly to include system binary directories before the app starts. + ## 0.49.1 - 2026-07-19 - Fixed Docker fallback tool discovery by exposing `anipy-cli` and `animdl` from fixed system paths and checking common system install locations at runtime. diff --git a/Dockerfile b/Dockerfile index 1ff213d..e13d9dc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,6 +11,7 @@ ENV DEBIAN_FRONTEND=noninteractive \ ANI_CLI_BRANCH=${ANI_CLI_BRANCH} \ ANI_CLI_WEB_REPO=${ANI_CLI_WEB} \ ANI_CLI_WEB_BRANCH=${ANI_CLI_WEB_BRANCH} \ + PATH=/usr/local/bin:/usr/bin:/bin \ ANI_CLI_BIN=ani-cli \ ANIPY_CLI_BIN=/usr/local/bin/anipy-cli \ ANIMDL_BIN=/usr/local/bin/animdl \ diff --git a/README.md b/README.md index 3b57ecf..fb8e4f0 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Local web UI for a system-wide `ani-cli` install. -Current version: `0.49.1` +Current version: `0.49.2` ## What it does @@ -96,7 +96,7 @@ Docker notes: - `UPDATE_ON_START=true` runs `ani-cli --update` before startup - `ANI_CLI_WEB_BRANCH` lets the image clone a specific `ani-cli-web` branch at build time - `botan` is installed inside the container for providers or scripts that need Botan cryptography tooling -- `anipy-cli` and `animdl` are installed systemwide inside the container at `/usr/local/bin` and linked from `/usr/bin`, so fallback retries are available without extra container setup +- `anipy-cli` and `animdl` are installed systemwide inside the container at `/usr/local/bin`, linked from `/usr/bin`, and included in the runtime `PATH`, so fallback retries are available without extra container setup ## Key behavior diff --git a/VERSION b/VERSION index 36328c4..20f6573 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.49.1 +0.49.2 diff --git a/app_support.py b/app_support.py index 9d7ce5b..4692664 100644 --- a/app_support.py +++ b/app_support.py @@ -1009,6 +1009,10 @@ def cli_executable_exists(command): return bool(shutil.which(text) or (Path(text).exists() and os.access(text, os.X_OK))) +def cli_executable_exists_any(*commands): + return any(cli_executable_exists(command) for command in commands) + + def printable_command(command): return " ".join(sh_quote(part) for part in command) diff --git a/http_handler.py b/http_handler.py index 02416d4..be3404b 100644 --- a/http_handler.py +++ b/http_handler.py @@ -35,6 +35,7 @@ from app_support import ( debug_enabled, debug_log, load_project_text_file, + cli_executable_exists_any, cli_executable_exists, normalize_config, path_is_within_roots, @@ -94,8 +95,18 @@ def dependency_status(): checks = ["curl", "sed", "grep", "openssl", "fzf", "aria2c", "ffmpeg", "yt-dlp"] result = {name: bool(shutil.which(name)) for name in checks} result["ani-cli"] = cli_executable_exists(ANI_CLI) - result["anipy-cli"] = cli_executable_exists(ANIPY_CLI) - result["animdl"] = cli_executable_exists(ANIMDL) + result["anipy-cli"] = cli_executable_exists_any( + ANIPY_CLI, + "anipy-cli", + "/usr/local/bin/anipy-cli", + "/usr/bin/anipy-cli", + ) + result["animdl"] = cli_executable_exists_any( + ANIMDL, + "animdl", + "/usr/local/bin/animdl", + "/usr/bin/animdl", + ) return result diff --git a/test_app.py b/test_app.py index 64be319..a9a2deb 100644 --- a/test_app.py +++ b/test_app.py @@ -3119,6 +3119,26 @@ class HandlerRouteTests(unittest.TestCase): self.assertIn("anipy-cli", handler.json_payload) self.assertIn("animdl", handler.json_payload) + def test_dependency_status_checks_docker_fallback_tool_paths(self): + with mock.patch.object(http_handler, "cli_executable_exists", return_value=True), mock.patch.object( + http_handler, "cli_executable_exists_any", return_value=True + ) as exists_any: + status = http_handler.dependency_status() + + self.assertTrue(status["animdl"]) + exists_any.assert_any_call( + http_handler.ANIMDL, + "animdl", + "/usr/local/bin/animdl", + "/usr/bin/animdl", + ) + exists_any.assert_any_call( + http_handler.ANIPY_CLI, + "anipy-cli", + "/usr/local/bin/anipy-cli", + "/usr/bin/anipy-cli", + ) + def test_clear_failed_route_removes_failed_jobs(self): with APP.DOWNLOAD_QUEUE._connect() as conn: conn.execute("DELETE FROM jobs")