From 5f3729568ec54a303fb20d907f70dcf3006c6c8f Mon Sep 17 00:00:00 2001 From: MacRimi Date: Mon, 12 Oct 2026 01:15:39 +0200 Subject: [PATCH] fix(post-install): updating optimizations of both flows prints only its steps --- .../test_install_functions_sourced_twice.py | 39 +++++++++++++++++++ scripts/global/utils-install-functions.sh | 21 ++++++---- 2 files changed, 53 insertions(+), 7 deletions(-) create mode 100644 .github/scripts/tests/test_install_functions_sourced_twice.py diff --git a/.github/scripts/tests/test_install_functions_sourced_twice.py b/.github/scripts/tests/test_install_functions_sourced_twice.py new file mode 100644 index 00000000..46259459 --- /dev/null +++ b/.github/scripts/tests/test_install_functions_sourced_twice.py @@ -0,0 +1,39 @@ +"""The shared install functions are sourced by both post-install flows. An +update that runs functions of the two sources the file twice in one shell, +which has to be as quiet as the first time.""" + +from pathlib import Path +import shutil +import subprocess +import unittest + +ROOT = Path(__file__).resolve().parents[3] +SHARED = ROOT / "scripts/global/utils-install-functions.sh" + + +@unittest.skipUnless(shutil.which("bash"), "bash is needed") +class SourcedTwiceTests(unittest.TestCase): + def source(self, times): + script = "; ".join([f'source "{SHARED}"'] * times) + '; echo "${PMX_NIC_LINK_DIR}|${#PMX_DKMS_COMPONENTS[@]}"' + return subprocess.run(["bash", "-c", script], capture_output=True, text=True, check=False) + + def test_a_second_source_prints_nothing(self): + once, twice = self.source(1), self.source(2) + self.assertEqual(twice.stderr, once.stderr) + self.assertNotIn("readonly variable", twice.stderr) + self.assertEqual(twice.returncode, 0) + + def test_the_values_are_the_same_and_stay_read_only(self): + self.assertEqual(self.source(2).stdout.strip(), "/etc/systemd/network|2") + attempt = subprocess.run(["bash", "-c", f'source "{SHARED}"; PMX_NIC_LINK_DIR=/tmp'], + capture_output=True, text=True, check=False) + self.assertIn("readonly variable", attempt.stderr) + + def test_no_other_shared_file_declares_a_read_only_variable_unguarded(self): + for path in sorted((ROOT / "scripts/global").glob("*.sh")) + [ROOT / "scripts/utils.sh"]: + for line in path.read_text(errors="replace").splitlines(): + self.assertFalse(line.startswith(("readonly ", "declare -r ")), f"{path.name}: {line[:60]}") + + +if __name__ == "__main__": + unittest.main() diff --git a/scripts/global/utils-install-functions.sh b/scripts/global/utils-install-functions.sh index a1c702fa..c4a79559 100644 --- a/scripts/global/utils-install-functions.sh +++ b/scripts/global/utils-install-functions.sh @@ -102,8 +102,12 @@ install_single_package() { # file, so user-authored .link files in /etc/systemd/network/ are # never touched. -readonly PMX_NIC_LINK_DIR="/etc/systemd/network" -readonly PMX_NIC_LINK_MARKER="# Managed by ProxMenux — do not edit" +# Declared once: this file is sourced by both post-install flows, and an +# update that runs functions of the two sources it twice in the same shell. +declare -p PMX_NIC_LINK_DIR >/dev/null 2>&1 \ + || readonly PMX_NIC_LINK_DIR="/etc/systemd/network" +declare -p PMX_NIC_LINK_MARKER >/dev/null 2>&1 \ + || readonly PMX_NIC_LINK_MARKER="# Managed by ProxMenux — do not edit" # Print the MAC address recorded in a .link file, uppercased, or empty # if the file has no MACAddress= line. @@ -254,13 +258,16 @@ pmx_uninstall_persistent_network() { # ProxMenux components against that kernel — so drivers keep # working after the reboot without operator intervention. -readonly PMX_COMPONENTS_STATUS="/usr/local/share/proxmenux/components_status.json" +declare -p PMX_COMPONENTS_STATUS >/dev/null 2>&1 \ + || readonly PMX_COMPONENTS_STATUS="/usr/local/share/proxmenux/components_status.json" # component_key : dkms_module_name (empty module = not DKMS) -readonly -a PMX_DKMS_COMPONENTS=( - "nvidia_driver:nvidia" - "coral_driver:gasket" -) +if ! declare -p PMX_DKMS_COMPONENTS >/dev/null 2>&1; then + readonly -a PMX_DKMS_COMPONENTS=( + "nvidia_driver:nvidia" + "coral_driver:gasket" + ) +fi # Print the newest installed pve/proxmox kernel version, or empty. _pmx_newest_installed_kernel() {