From 7b61619a7a21b3034dfbaf91a08c20a3bf6fdbac Mon Sep 17 00:00:00 2001 From: Krzysztof kuhy Rudnicki Date: Sun, 23 Aug 2026 06:56:26 +0200 Subject: [PATCH] Reconcile the venv on launch, so a pin bump cannot sit unnoticed run.sh created .venv on first run and then only ever launched the app. When the crdt-sync pin moved to v0.9.0 nothing ran pip, so the venv sat at 0.6.0 for months and surfaced as an ImportError on LogCodec at startup. The venv is isolated (ENABLE_USER_SITE=False), so it could not fall back to the healthy 0.9.0 in user site-packages that the systemd units use. Reconcile against requirements.txt and refuse to launch if that fails, rather than starting on dependencies we already know are wrong. Gated on a sha256 stamp of requirements.txt: pip re-resolves the two git pins over the network (~5.5s) on every call, and this is a screen locker that has to start when the network is down. The stamp is only written on success, so a failed install retries on the next launch instead of being remembered as done. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01PCUN9mdfJzJXqEZatHnUCD --- run.sh | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/run.sh b/run.sh index 8e8aee2..3480b6a 100755 --- a/run.sh +++ b/run.sh @@ -1,10 +1,40 @@ #!/usr/bin/env bash -set -e +set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" VENV="$SCRIPT_DIR/.venv" -[[ ! -d "$VENV" ]] && python3 -m venv "$VENV" # tkinter is from Python stdlib; install python-tk system package if missing: # Arch: sudo pacman -S python-tk # Debian: sudo apt-get install python3-tk cd "$SCRIPT_DIR" -"$VENV/bin/python" -m screen_locker.screen_lock "$@" + +if [[ ! -d "$VENV" ]]; then + python3 -m venv "$VENV" +fi + +# Reconcile the venv against requirements.txt whenever that file changes. +# Without this the venv is created once and never updated, so a dependency pin +# bump stays invisible until it surfaces as an ImportError at startup -- +# crdt-sync sat at 0.6.0 for months after the pin moved to 0.9.0. +# +# Gated on a hash stamp so the common case costs nothing: pip re-resolves the +# git-pinned deps over the network (~5s) on every call, and this is a screen +# locker that must still start when the network is down. +STAMP="$VENV/.requirements.sha256" +WANT="$(sha256sum requirements.txt | cut -d" " -f1)" +HAVE="$(cat "$STAMP" 2>/dev/null || true)" + +if [[ "$WANT" != "$HAVE" ]]; then + echo "Dependencies changed; reconciling venv against requirements.txt..." >&2 + if "$VENV/bin/pip" install -q -r requirements.txt; then + printf '%s\n' "$WANT" > "$STAMP" + else + # Do not stamp on failure, so the next launch retries. Abort rather + # than run on dependencies we know are wrong. + echo "ERROR: failed to install dependencies from requirements.txt" >&2 + echo " Refusing to launch with unreconciled dependencies." >&2 + echo " Retry manually: $VENV/bin/pip install -r requirements.txt" >&2 + exit 1 + fi +fi + +exec "$VENV/bin/python" -m screen_locker.screen_lock "$@"