9e8f1bbeed
Dashboard / frontend (push) Failing after 0s
Dashboard / api (push) Failing after 0s
Lint PowerShell / powershell-lint (ubuntu-latest) (push) Failing after 1s
Python Lint / Lint Python with Ruff (push) Failing after 1s
ShellCheck / Lint shell scripts (push) Failing after 1s
Matrix Smoke / linux-smoke (push) Failing after 1s
Matrix Smoke / distro: cachyos (push) Failing after 15s
Matrix Smoke / distro: linux-mint-21.3 (push) Failing after 15s
Matrix Smoke / distro: debian-12 (push) Failing after 5m21s
Matrix Smoke / distro: fedora-41 (push) Failing after 4m56s
Matrix Smoke / distro: ubuntu-24.04 (push) Failing after 2m13s
Matrix Smoke / distro: rocky-9 (push) Failing after 10m39s
Matrix Smoke / distro: manjaro (push) Failing after 12m11s
Matrix Smoke / distro: opensuse-tw (push) Failing after 11m53s
Matrix Smoke / distro: archlinux (push) Failing after 20m3s
Matrix Smoke / distro: ubuntu-22.04 (push) Failing after 13m49s
Validate .env Schema / tier-1-env-validation (push) Successful in 52s
Validate .env Schema / tier-2-env-validation (push) Successful in 44s
Validate .env Schema / tier-3-env-validation (push) Successful in 52s
Validate .env Schema / tier-4-env-validation (push) Successful in 51s
Validate Extensions Catalog / Check catalog is up-to-date (push) Failing after 9m47s
Secret Scan / Scan for secrets (push) Failing after 21m4s
Validate Docker Compose / Validate Docker Compose files (push) Has been cancelled
Python Type Check / Type check with mypy (push) Has been cancelled
Validate .env Schema / tier-0-env-validation (push) Has been cancelled
Test Linux / integration-smoke (push) Has been cancelled
Lint PowerShell / powershell-lint (windows-latest) (push) Has been cancelled
Matrix Smoke / macos-smoke (push) Has been cancelled
114 lines
4.1 KiB
Bash
Executable File
114 lines
4.1 KiB
Bash
Executable File
#!/bin/bash
|
|
# ============================================================================
|
|
# ODS Installer — Python runtime guards
|
|
# ============================================================================
|
|
# Part of: installers/lib/
|
|
# Purpose: Ensure installer Python helpers use an interpreter that can import
|
|
# the modules they need. This especially protects Linux users with
|
|
# Conda/venv Python ahead of /usr/bin/python3 in PATH.
|
|
#
|
|
# Expects: SCRIPT_DIR, LOG_FILE, PKG_MANAGER, INTERACTIVE, DRY_RUN,
|
|
# pkg_install(), pkg_resolve(), ods_sudo(), ai(), ai_ok(), ai_warn(),
|
|
# error()
|
|
# Provides: ods_python_cmd_path(), ods_python_has_module(),
|
|
# ods_ensure_python_module()
|
|
# ============================================================================
|
|
|
|
[[ -f "${SCRIPT_DIR:-$(pwd)}/lib/python-cmd.sh" ]] && . "${SCRIPT_DIR:-$(pwd)}/lib/python-cmd.sh"
|
|
|
|
ods_python_cmd_path() {
|
|
local cmd="${1:-$(ods_detect_python_cmd 2>/dev/null || true)}"
|
|
[[ -z "$cmd" ]] && return 1
|
|
command -v "$cmd" 2>/dev/null || printf '%s\n' "$cmd"
|
|
}
|
|
|
|
ods_python_has_module() {
|
|
local module="$1"
|
|
local pycmd="${2:-$(ods_detect_python_cmd)}"
|
|
"$pycmd" -c "import ${module}" >/dev/null 2>&1
|
|
}
|
|
|
|
ods_python_is_env_managed() {
|
|
local py_path="${1:-$(ods_python_cmd_path 2>/dev/null || true)}"
|
|
|
|
[[ -n "${CONDA_PREFIX:-}" || -n "${VIRTUAL_ENV:-}" ]] && return 0
|
|
[[ "$py_path" == *"/conda/"* || "$py_path" == *"/miniconda"* || "$py_path" == *"/anaconda"* ]] && return 0
|
|
[[ "$py_path" == *"/.venv/"* || "$py_path" == *"/venv/"* ]] && return 0
|
|
return 1
|
|
}
|
|
|
|
ods_ensure_python_runtime() {
|
|
local pycmd
|
|
pycmd="$(ods_detect_python_cmd 2>/dev/null || true)"
|
|
if [[ -n "$pycmd" ]]; then
|
|
printf '%s' "$pycmd"
|
|
return 0
|
|
fi
|
|
|
|
if [[ "${DRY_RUN:-false}" == "true" ]]; then
|
|
ai_warn "Python is not available (dry-run: would install python3)." >&2
|
|
return 1
|
|
fi
|
|
|
|
if declare -f pkg_install >/dev/null 2>&1; then
|
|
ai "Installing python3 for installer helpers..." >&2
|
|
if declare -f pkg_update >/dev/null 2>&1; then
|
|
case "${PKG_MANAGER:-}" in
|
|
apt|apk|dnf|xbps|zypper) pkg_update >/dev/null || true ;;
|
|
esac
|
|
fi
|
|
pkg_install python3 >/dev/null 2>>"${LOG_FILE:-/dev/null}" || true
|
|
_ods_python_cmd_cached=""
|
|
fi
|
|
|
|
pycmd="$(ods_detect_python_cmd 2>/dev/null || true)"
|
|
[[ -n "$pycmd" ]] || return 1
|
|
printf '%s' "$pycmd"
|
|
}
|
|
|
|
ods_ensure_python_module() {
|
|
local module="$1"
|
|
local canonical_pkg="$2"
|
|
local pip_pkg="$3"
|
|
local display="${4:-$module}"
|
|
|
|
local pycmd
|
|
pycmd="$(ods_ensure_python_runtime)" || error "Python is required but no runnable python3/python was found."
|
|
|
|
if ods_python_has_module "$module" "$pycmd"; then
|
|
ai_ok "$display available for $pycmd"
|
|
return 0
|
|
fi
|
|
|
|
if [[ "${DRY_RUN:-false}" == "true" ]]; then
|
|
ai_warn "$display is not importable by $pycmd (dry-run: would install ${canonical_pkg})."
|
|
return 0
|
|
fi
|
|
|
|
if declare -f pkg_install >/dev/null 2>&1 && declare -f pkg_resolve >/dev/null 2>&1; then
|
|
ai "Installing $display for the installer Python runtime..."
|
|
# shellcheck disable=SC2046
|
|
pkg_install $(pkg_resolve "$canonical_pkg") 2>>"${LOG_FILE:-/dev/null}" || true
|
|
fi
|
|
|
|
if ods_python_has_module "$module" "$pycmd"; then
|
|
ai_ok "$display available for $pycmd"
|
|
return 0
|
|
fi
|
|
|
|
local py_path
|
|
py_path="$(ods_python_cmd_path "$pycmd" 2>/dev/null || printf '%s' "$pycmd")"
|
|
if ods_python_is_env_managed "$py_path"; then
|
|
ai_bad "$display is not importable by the active Python: $py_path"
|
|
ai_bad "A Conda/venv Python appears to be ahead of the system Python."
|
|
ai "Run: conda deactivate"
|
|
ai "Then re-run the installer, or install the module into that environment:"
|
|
ai " $pycmd -m pip install $pip_pkg"
|
|
else
|
|
ai_bad "$display is not importable by $pycmd."
|
|
ai "Install it manually and re-run:"
|
|
ai " $pycmd -m pip install $pip_pkg"
|
|
fi
|
|
error "$display is required by the ODS compose and service registry helpers."
|
|
}
|