From d9ccf71901cc35da72f8337fd70320c33edcc979 Mon Sep 17 00:00:00 2001 From: Codex Date: Sun, 9 Aug 2026 18:29:21 +0200 Subject: [PATCH] Fix Docker provider search dependencies --- CHANGELOG.md | 5 +++++ Dockerfile | 4 ++-- README.md | 1 + VERSION | 2 +- package-lock.json | 52 ++++++++++++++++++----------------------------- package.json | 2 +- test_app.py | 10 +++++++++ 7 files changed, 40 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2951d45..d4e11f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 0.52.6 - 2026-08-09 + +- Fixed Docker search failures by pinning Cheerio to the Node 18-compatible `1.0.0` release. +- Made Docker installs deterministic by copying `package-lock.json` and using `npm ci`. + ## 0.52.5 - 2026-08-09 - Changed Watchlist title links to open the anime on the provider it was added from instead of the retired metadata source. diff --git a/Dockerfile b/Dockerfile index 4526167..1490e70 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,8 +22,8 @@ RUN apt-get update \ RUN mkdir -p /app -COPY package.json /app/ -RUN cd /app && npm install --omit=dev +COPY package.json package-lock.json /app/ +RUN cd /app && npm ci --omit=dev COPY app.py app_support.py config_page.py http_handler.py provider_bridge.py provider_downloader.py queue_jobs.py queue_page.py search_page.py template_helpers.py title_matching.py watchlist_identity.py watchlist_page.py web_templates.py VERSION CHANGELOG.md favicon.png /app/ COPY providers /app/providers diff --git a/README.md b/README.md index 426fa48..77a32b2 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ Kaizoku is a local web app for searching, tracking, and downloading anime from A - Node.js and npm for the provider bridge. - `ffmpeg` available in `PATH`. - `openssl` available in `PATH` for AES-128 encrypted HLS segments. +- Docker builds install the locked Node dependencies with `npm ci`; rebuild the image after dependency updates. Install Node dependencies once: diff --git a/VERSION b/VERSION index e56c472..f4b8938 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.52.5 +0.52.6 diff --git a/package-lock.json b/package-lock.json index 3484b84..bfe8e6e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.1.0", "dependencies": { "axios": "^1.7.9", - "cheerio": "^1.0.0" + "cheerio": "1.0.0" } }, "node_modules/agent-base": { @@ -62,25 +62,25 @@ } }, "node_modules/cheerio": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.2.0.tgz", - "integrity": "sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0.tgz", + "integrity": "sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==", "license": "MIT", "dependencies": { "cheerio-select": "^2.1.0", "dom-serializer": "^2.0.0", "domhandler": "^5.0.3", - "domutils": "^3.2.2", - "encoding-sniffer": "^0.2.1", - "htmlparser2": "^10.1.0", - "parse5": "^7.3.0", - "parse5-htmlparser2-tree-adapter": "^7.1.0", + "domutils": "^3.1.0", + "encoding-sniffer": "^0.2.0", + "htmlparser2": "^9.1.0", + "parse5": "^7.1.2", + "parse5-htmlparser2-tree-adapter": "^7.0.0", "parse5-parser-stream": "^7.1.2", - "undici": "^7.19.0", + "undici": "^6.19.5", "whatwg-mimetype": "^4.0.0" }, "engines": { - "node": ">=20.18.1" + "node": ">=18.17" }, "funding": { "url": "https://github.com/cheeriojs/cheerio?sponsor=1" @@ -442,9 +442,9 @@ } }, "node_modules/htmlparser2": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz", - "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz", + "integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==", "funding": [ "https://github.com/fb55/htmlparser2?sponsor=1", { @@ -456,20 +456,8 @@ "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", - "domutils": "^3.2.2", - "entities": "^7.0.1" - } - }, - "node_modules/htmlparser2/node_modules/entities": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", - "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "domutils": "^3.1.0", + "entities": "^4.5.0" } }, "node_modules/https-proxy-agent": { @@ -610,12 +598,12 @@ "license": "MIT" }, "node_modules/undici": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.0.tgz", - "integrity": "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==", + "version": "6.28.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.28.0.tgz", + "integrity": "sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA==", "license": "MIT", "engines": { - "node": ">=20.18.1" + "node": ">=18.17" } }, "node_modules/whatwg-encoding": { diff --git a/package.json b/package.json index 504b4c1..724fd0a 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,6 @@ "description": "Local provider bridge for Kaizoku anime metadata and stream resolution.", "dependencies": { "axios": "^1.7.9", - "cheerio": "^1.0.0" + "cheerio": "1.0.0" } } diff --git a/test_app.py b/test_app.py index 1e579a8..bea9ebe 100644 --- a/test_app.py +++ b/test_app.py @@ -4050,6 +4050,16 @@ class TemplateHelperTests(unittest.TestCase): self.assertNotIn("What you can do here", APP.QUEUE_HTML) self.assertNotIn("How it works", APP.WATCHLIST_HTML) + def test_docker_uses_locked_node_dependencies(self): + package = json.loads((ROOT / "package.json").read_text(encoding="utf-8")) + lock = json.loads((ROOT / "package-lock.json").read_text(encoding="utf-8")) + dockerfile = (ROOT / "Dockerfile").read_text(encoding="utf-8") + + self.assertEqual(package["dependencies"]["cheerio"], "1.0.0") + self.assertEqual(lock["packages"]["node_modules/cheerio"]["version"], "1.0.0") + self.assertIn("COPY package.json package-lock.json /app/", dockerfile) + self.assertIn("npm ci --omit=dev", dockerfile) + def test_queue_page_formats_jellyfin_handoff_jobs(self): self.assertIn('job.job_type === "jellyfin_handoff"', APP.QUEUE_HTML) self.assertIn('const progress = `${job.completed || 0}/${job.total || 0} entries`;', APP.QUEUE_HTML)