diff --git a/entrypoint.sh b/entrypoint.sh index bfd4d792..a11fbc96 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -235,7 +235,11 @@ test_write() { return 1 fi - if ! run_as_target_user sh -c 'echo 0123456789_TEST > "$1"' _ "$test_file"; then + # This is a probe: a failure here is expected (e.g. a fresh root-owned bind + # mount) and is recovered by the caller via change_ownership + re-probe. Hide + # the shell's "Permission denied"/"Read-only file system" stderr so a handled + # probe miss doesn't masquerade as a real boot failure in the logs. + if ! run_as_target_user sh -c 'echo 0123456789_TEST 2>/dev/null > "$1"' _ "$test_file"; then echo "Failed to write test file in $folder as $USERNAME" return 1 fi @@ -448,6 +452,12 @@ else if [ $config_ok -ne 0 ]; then fail_unwritable_config_dir "$CONFIG_PATH" fi + + # The ingest/destination library (default /books) is user data and may be a + # bind mount owned by another uid; downloads fail with "Destination not + # writable" if the runtime user can't write there. Fix the top-level dir only + # (root mode) so we don't recursively chown a potentially huge library. + make_writable "${INGEST_DIR:-/books}" root fi # Always run Gunicorn (even when DEBUG=true) to ensure Socket.IO WebSocket diff --git a/tests/e2e/platform/suite/conftest.py b/tests/e2e/platform/suite/conftest.py index e672fe3a..864100cc 100644 --- a/tests/e2e/platform/suite/conftest.py +++ b/tests/e2e/platform/suite/conftest.py @@ -17,10 +17,16 @@ from __future__ import annotations import os import time from dataclasses import dataclass, field +from pathlib import Path import pytest import requests +# This conftest's pytest_collection_modifyitems hook receives the *whole* +# session's items (not just ones under this dir), so scope our marking to the +# suite to avoid tagging the entire repo's tests as platform/e2e. +_SUITE_DIR = Path(__file__).resolve().parent + BASE_URL = os.environ.get("E2E_BASE_URL", "http://localhost:8084") ACTIVE_PROFILE = os.environ.get("E2E_PROFILE", "baseline") DEFAULT_TIMEOUT = 15 @@ -124,7 +130,10 @@ def pytest_collection_modifyitems(config: pytest.Config, items: list[pytest.Item everywhere (this is the matrix: invariants x profiles). """ for item in items: + if not item.path.is_relative_to(_SUITE_DIR): + continue item.add_marker(pytest.mark.platform) + item.add_marker(pytest.mark.e2e) marker = item.get_closest_marker("profiles") if marker and ACTIVE_PROFILE not in marker.args: item.add_marker(