github new-usemame/Calibre-Web-NextGen v4.0.64
v4.0.64 — test-isolation refactor: no more lockfile-pollution flakes in CI (#208)

latest releases: v4.1.0, v4.0.172, v4.0.171...
one month ago

What's fixed (CI / developer experience): The three scheduled scripts (scripts/ingest_processor.py, scripts/kindle_epub_fixer.py, scripts/convert_library.py) historically acquired their single-instance lockfile at module-import time and called sys.exit(2) on collision. Under pytest-xdist (workers share /tmp across processes), importlib.import_module(...) from one worker would crash a sibling worker that had already taken the same lock — the entire class of "PR landed red Fast Tests because of cross-xdist-worker lockfile pollution" that PR #204 patched narrowly the day before.

What changed: Each script now has a _acquire_lock_or_exit() helper called from main(), so importing the module is a pure load with no filesystem side effects. convert_library.py is also hardened for CI / non-container environments (missing /config directory, missing abc user) so test runners can subprocess-import it without root and without the LinuxServer image's user table.

Runtime impact for end users: Zero. The scripts still acquire the lock when run (via cron / s6-overlay inside the container) — that behavior moves from import-time to main()-time, which is a no-op functionally because they were always run as __main__.

Why this matters operationally: Future PRs ship through CI without lockfile-flake-driven retries. The --admin override that some recent PRs needed to push through red Fast Tests for the documented "kindle-lockfile pollution" reason is no longer necessary.

Regression coverage: New tests/unit/test_script_import_side_effects.py (20 tests) pins the contract via three layers:

  1. Subprocess imports of each script return rc=0 and create no /tmp lockfile, both with no prior lockfile and with a stale sibling-script lockfile present.
  2. AST source-pin tests assert no module-level sys.exit() on lock collision and no module-level atexit.register() — a future refactor that re-introduces import-time side effects fails the test.
  3. AST wire-up test asserts each script's main() actually calls _acquire_lock_or_exit() — so a refactor that silently removes the call (losing single-instance protection in production while the import-side-effect tests still pass) is caught.

Drop-in image: ghcr.io/new-usemame/calibre-web-nextgen:latest — same docker-compose.yml, swap the image line, restart. Tracker if anything's still broken: https://github.com/new-usemame/Calibre-Web-NextGen/issues.

Files in the squash: scripts/convert_library.py, scripts/ingest_processor.py, scripts/kindle_epub_fixer.py, tests/unit/test_script_import_side_effects.py — +319 / -58 LOC.

Don't miss a new Calibre-Web-NextGen release

NewReleases is sending notifications on new releases.