From db2b5f17f08451c6dc161b28265a55fa97f7bd64 Mon Sep 17 00:00:00 2001 From: Rongsong Shen Date: Wed, 22 Jul 2026 13:07:23 +0000 Subject: [PATCH] fix(admin-config-tool): pin xceadmin's python3 to meson's own resolution Both meson-build.sh (venv creation) and meson-install.sh (wrapper shebang) resolved python3 independently at run time (bare `python3 -m venv` / `command -v python3`) -- correct as long as invoked inside nix develop/build, but nothing prevented a stray non-nix system python3 earlier on PATH from shadowing it. meson.build now resolves python3 once via import('python'). find_installation('python3') -- same mechanism as find_program('go')/ capnp/packcc elsewhere in this build, printed at `meson setup` time as "Program python3 found: YES (/nix/store/...)" -- and threads that exact resolved path into both scripts as an explicit argument instead of a fresh lookup. Verified: meson setup prints the pinned python3, xceadmin target rebuilds clean (165/165 passed), and the built venv's own python3 resolves through to that exact nix store path. --- src/xceadmin/meson-build.sh | 8 +++++--- src/xceadmin/meson-install.sh | 15 +++++++++------ src/xceadmin/meson.build | 15 ++++++++++++++- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/xceadmin/meson-build.sh b/src/xceadmin/meson-build.sh index e4a865f6..62f485cb 100755 --- a/src/xceadmin/meson-build.sh +++ b/src/xceadmin/meson-build.sh @@ -19,7 +19,9 @@ set -euo pipefail SOURCE_DIR="$1" # .../src/xceadmin (meson.current_source_dir()) BUILD_DIR="$2" # .../xceadmin (meson.current_build_dir()) REPO_ROOT="$3" # real repo root (contains ha/, src/) -STAMP_FILE="$4" +PYTHON="$4" # meson's resolved python3 (import('python').find_installation()), + # NOT a bare `python3` PATH lookup -- see meson.build's comment +STAMP_FILE="$5" SRC_DIR="$REPO_ROOT/src" @@ -50,9 +52,9 @@ cp "$SRC_DIR/schema/controller.capnp" "$SCHEMA_DST/controller.capnp" cp "$SRC_DIR/schema/c.capnp" "$SCHEMA_DST/c.capnp" cp "$SRC_DIR/configs/schema/"*.schema.json "$SCHEMA_DST/json/" -echo "=== xceadmin (meson): pinned install into build-dir venv ===" +echo "=== xceadmin (meson): pinned install into build-dir venv (python: $PYTHON) ===" rm -rf "$VENV_DIR" -python3 -m venv --system-site-packages "$VENV_DIR" +"$PYTHON" -m venv --system-site-packages "$VENV_DIR" "$VENV_DIR/bin/pip" install "$WORK_DIR" --quiet echo "=== xceadmin (meson): running tests ===" diff --git a/src/xceadmin/meson-install.sh b/src/xceadmin/meson-install.sh index 48348abb..b88c7bd6 100755 --- a/src/xceadmin/meson-install.sh +++ b/src/xceadmin/meson-install.sh @@ -9,15 +9,18 @@ # # Instead: copy just the xceadmin/xcecommon package dirs (pure files, no # shebang) into $out, and hand-write a wrapper whose shebang and PYTHONPATH -# are resolved against *this* install script's own environment (python3 -# and the nix-provided pycapnp/pyyaml/jsonschema/click site-packages come -# from nativeBuildInputs, same as every other phase of this derivation) -- -# every path baked in below is a real /nix/store path, so nix's reference -# scanner picks each one up as a proper runtime dependency of $out. +# are resolved against *this* install script's own environment (python3 -- +# passed in as $1, meson's own resolved interpreter (import('python'). +# find_installation()) from meson.build, not a fresh `command -v python3` +# lookup here -- and the nix-provided pycapnp/pyyaml/jsonschema/click +# site-packages come from nativeBuildInputs, same as every other phase of +# this derivation) -- every path baked in below is a real /nix/store path, +# so nix's reference scanner picks each one up as a proper runtime +# dependency of $out. set -euo pipefail +PYTHON="$1" DESTDIR_PREFIX="$MESON_INSTALL_DESTDIR_PREFIX" -PYTHON="$(command -v python3)" VENV_SITE_GLOB=("$MESON_BUILD_ROOT"/xceadmin/.venv/lib/python3.*/site-packages) VENV_SITE="${VENV_SITE_GLOB[0]}" diff --git a/src/xceadmin/meson.build b/src/xceadmin/meson.build index e6d26b07..c4f3bc60 100644 --- a/src/xceadmin/meson.build +++ b/src/xceadmin/meson.build @@ -12,6 +12,18 @@ # standalone, but no longer xce-build.sh's OWN xceadmin implementation # -- see tools/xce-build.sh, which now just calls this same target). +# Resolved once via meson's own dependency machinery (same pattern as +# find_program('go')/capnp/packcc elsewhere in this build, printed as +# "Program python3 found: YES (/nix/store/...)" at `meson setup` time) and +# threaded explicitly into both scripts below -- NOT left to each script's +# own `python3 -m venv`/`command -v python3` PATH lookup at run time. A bare +# PATH lookup would happen to match nix's python3 when invoked correctly +# (inside `nix develop` / a nix build sandbox), but nothing would catch a +# stray non-nix system python3 shadowing it earlier on PATH -- pinning the +# exact interpreter meson already found makes that impossible, not just +# unlikely. +python3_prog = import('python').find_installation('python3') + xceadmin_stamp = custom_target('xceadmin', output: 'xceadmin-build.stamp', # No meaningful per-file `input:` list: meson-build.sh copies the whole @@ -26,6 +38,7 @@ xceadmin_stamp = custom_target('xceadmin', meson.current_source_dir(), meson.current_build_dir(), meson.current_source_dir() / '..' / '..', # repo root (contains ha/, src/) + python3_prog.full_path(), '@OUTPUT@', ], build_by_default: true, @@ -37,4 +50,4 @@ xceadmin_stamp = custom_target('xceadmin', # (ninja install always depends on build_by_default targets first) so the # build-dir venv it copies from already exists. See meson-install.sh for # why this isn't a plain `cp` of that venv. -meson.add_install_script('meson-install.sh') +meson.add_install_script('meson-install.sh', python3_prog.full_path())