From 63b77cf86b0531f46b217e7f8e45921cd3bd63af Mon Sep 17 00:00:00 2001 From: Thomas Nordentoft Date: Sat, 8 Aug 2026 17:15:16 +0200 Subject: [PATCH 1/5] Replace custom logic with easydeploy-lib --- .gitmodules | 4 ++ README.md | 10 +++- easydeploy-lib | 1 + ensure-dependencies.sh | 93 ++++++------------------------------ scripts/deps_config.sh | 6 +++ scripts/lib.sh | 104 ++--------------------------------------- 6 files changed, 38 insertions(+), 180 deletions(-) create mode 160000 easydeploy-lib create mode 100644 scripts/deps_config.sh diff --git a/.gitmodules b/.gitmodules index 05bb5b2..3100dc1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,7 @@ [submodule "opencloud-compose"] path = opencloud-compose url = https://github.com/opencloud-eu/opencloud-compose.git +[submodule "easydeploy-lib"] + path = easydeploy-lib + url = https://github.com/nordwestt/easy-deploy-lib.git + branch = main diff --git a/README.md b/README.md index 7898047..c85011c 100644 --- a/README.md +++ b/README.md @@ -9,12 +9,18 @@ This replaces the official test installer (`curl -L https://opencloud.eu/install **Requirements:** Linux VPS, Docker Compose v2, DNS pointing at the server, ports 80/443 open. ```bash -git clone https://github.com/your-org/opencloud-easy-deploy.git +git clone --recurse-submodules https://github.com/your-org/opencloud-easy-deploy.git cd opencloud-easy-deploy -bash ensure-dependencies.sh # Docker, uv, submodule, Python deps +bash ensure-dependencies.sh # Docker, uv, submodules, Python deps bash wizard.sh # interactive: writes deploy.yaml and deploys ``` +If you already cloned without submodules: + +```bash +git submodule update --init --recursive +``` + Or manually: ```bash diff --git a/easydeploy-lib b/easydeploy-lib new file mode 160000 index 0000000..9285f8e --- /dev/null +++ b/easydeploy-lib @@ -0,0 +1 @@ +Subproject commit 9285f8efa0e3d6ce022604708d78c95c3b5bd933 diff --git a/ensure-dependencies.sh b/ensure-dependencies.sh index dbf814e..cfc2d8f 100755 --- a/ensure-dependencies.sh +++ b/ensure-dependencies.sh @@ -5,105 +5,42 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # shellcheck source=scripts/lib.sh source "${SCRIPT_DIR}/scripts/lib.sh" +# shellcheck source=scripts/deps_config.sh +source "${SCRIPT_DIR}/scripts/deps_config.sh" export PATH="${HOME}/.local/bin:${PATH}" -run_as_root() { - if [[ "${EUID}" -eq 0 ]]; then - "$@" - elif command -v sudo &>/dev/null; then - sudo "$@" - else - die "Need root privileges for: $* — re-run with sudo or as root" - fi -} - -docker_usable() { - command -v docker &>/dev/null || return 1 - docker info &>/dev/null 2>&1 -} - -compose_usable() { - docker compose version &>/dev/null 2>&1 || command -v docker-compose &>/dev/null -} - ensure_git() { if command -v git &>/dev/null; then success "git present ($(git --version | head -1))" return fi info "Installing git…" - if command -v apt-get &>/dev/null; then - run_as_root apt-get update -qq - run_as_root apt-get install -y git - elif command -v dnf &>/dev/null; then - run_as_root dnf install -y git - elif command -v pacman &>/dev/null; then - run_as_root pacman -Sy --noconfirm git + local manager + manager="$(detect_supported_package_manager)" || die "git is required but no supported package manager was found" + install_missing_dependencies "$manager" git + if command -v git &>/dev/null; then + success "git installed" else die "git is required but not installed — install git and re-run" fi - success "git installed" } -ensure_submodule() { +ensure_submodules() { if [[ ! -d "${SCRIPT_DIR}/.git" ]]; then warn "Not a git checkout — skipping submodule update" if [[ ! -f "${SCRIPT_DIR}/opencloud-compose/docker-compose.yml" ]]; then die "opencloud-compose is missing — clone the repo with submodules or copy opencloud-compose manually" fi + if [[ ! -f "${SCRIPT_DIR}/easydeploy-lib/lib/init.sh" ]]; then + die "easydeploy-lib is missing — clone the repo with submodules" + fi return fi - if [[ -f "${SCRIPT_DIR}/opencloud-compose/docker-compose.yml" ]]; then - info "Updating opencloud-compose submodule…" - else - info "Initializing opencloud-compose submodule…" - fi + info "Initializing git submodules (opencloud-compose, easydeploy-lib)…" git -C "${SCRIPT_DIR}" submodule update --init --recursive - success "opencloud-compose submodule ready" -} - -ensure_docker() { - if docker_usable; then - success "Docker present ($(docker --version | head -1))" - else - if command -v docker &>/dev/null; then - warn "Docker is installed but the daemon is not reachable — start docker and re-run" - die "Try: sudo systemctl enable --now docker" - fi - info "Installing Docker (get.docker.com)…" - curl -fsSL https://get.docker.com | run_as_root sh - if ! docker_usable; then - if [[ "${EUID}" -ne 0 ]] && ! groups | grep -q '\bdocker\b'; then - warn "Your user is not in the docker group — log out/in after:" - warn " sudo usermod -aG docker ${USER}" - warn "Or run docker commands with sudo until then." - fi - if ! docker_usable && [[ "${EUID}" -ne 0 ]]; then - warn "Verifying Docker with sudo…" - if sudo docker info &>/dev/null 2>&1; then - success "Docker installed (use sudo docker until group membership applies)" - else - die "Docker install finished but daemon is not running" - fi - else - die "Docker install finished but daemon is not running" - fi - else - success "Docker installed" - fi - fi - - if compose_usable; then - if docker compose version &>/dev/null 2>&1; then - success "Docker Compose present ($(docker compose version --short 2>/dev/null || docker compose version | head -1))" - else - success "docker-compose present" - fi - else - die "Docker Compose v2 is required — reinstall Docker or install the compose plugin" - fi + success "Git submodules ready" } ensure_uv() { @@ -132,8 +69,8 @@ main() { echo ensure_git - ensure_submodule - ensure_docker + ensure_submodules + ensure_dependencies_installed ensure_uv ensure_python_deps diff --git a/scripts/deps_config.sh b/scripts/deps_config.sh new file mode 100644 index 0000000..5717448 --- /dev/null +++ b/scripts/deps_config.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +# scripts/deps_config.sh — OpenCloud Easy Deploy dependency list (easydeploy-lib hook) + +easydeploy_required_deps() { + printf '%s\n' docker docker-compose git +} diff --git a/scripts/lib.sh b/scripts/lib.sh index 1be227b..7b18761 100644 --- a/scripts/lib.sh +++ b/scripts/lib.sh @@ -1,104 +1,8 @@ #!/usr/bin/env bash # scripts/lib.sh — shared utilities for opencloud-easy-deploy -RED='\033[0;31m' -YELLOW='\033[1;33m' -GREEN='\033[0;32m' -CYAN='\033[0;36m' -BOLD='\033[1m' -RESET='\033[0m' +_lib_sh_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +_ocd_project_root="$(cd "${_lib_sh_dir}/.." && pwd)" -info() { echo -e "${CYAN} -->${RESET} $*"; } -success() { echo -e "${GREEN} [ok]${RESET} $*"; } -warn() { echo -e "${YELLOW} [!]${RESET} $*"; } -error() { echo -e "${RED} [ERR]${RESET} $*" >&2; } -die() { error "$*"; exit 1; } - -load_deploy_env() { - local deploy_env="$1" - [[ -f "$deploy_env" ]] || return 0 - - while IFS='=' read -r key value || [[ -n "$key" ]]; do - [[ -z "$key" || "$key" == \#* ]] && continue - [[ "$key" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]] || continue - value="${value%%#*}" - value="${value%"${value##*[![:space:]]}"}" - export "${key}=${value}" - done < "$deploy_env" -} - -ask() { - local _var="$1" - local _prompt="$2" - local _default="${3:-}" - - if [[ -n "$_default" ]]; then - echo -ne "${BOLD} ${_prompt}${RESET} ${CYAN}[${_default}]${RESET}: " - else - echo -ne "${BOLD} ${_prompt}${RESET}: " - fi - - local _input - read -r _input - printf -v "$_var" '%s' "${_input:-$_default}" -} - -ask_secret() { - local _var="$1" - local _prompt="$2" - - echo -ne "${BOLD} ${_prompt}${RESET}: " - local _input - read -rs _input - echo - printf -v "$_var" '%s' "$_input" -} - -ask_yn() { - local _var="$1" - local _prompt="$2" - local _default="${3:-n}" - - local suffix="y/N" - [[ "$_default" == "y" ]] && suffix="Y/n" - - echo -ne "${BOLD} ${_prompt}${RESET} ${CYAN}[${suffix}]${RESET}: " - local _input - read -r _input - _input="${_input:-$_default}" - case "${_input,,}" in - y|yes) printf -v "$_var" '%s' "y" ;; - *) printf -v "$_var" '%s' "n" ;; - esac -} - -docker_compose_cmd() { - if docker compose version &>/dev/null; then - echo "docker compose" - return 0 - fi - if command -v docker-compose &>/dev/null; then - echo "docker-compose" - return 0 - fi - die "Docker Compose v2 is required (docker compose)" -} - -ensure_docker_network() { - local network_name="$1" - if ! docker network inspect "$network_name" &>/dev/null; then - info "Creating Docker network ${network_name}…" - docker network create "$network_name" - fi -} - -base_domain_from_host() { - local host="$1" - local parts=(${host//./ }) - local count=${#parts[@]} - if (( count >= 2 )); then - echo "${parts[count-2]}.${parts[count-1]}" - else - echo "$host" - fi -} +# shellcheck source=easydeploy-lib/lib/init.sh +source "${_ocd_project_root}/easydeploy-lib/lib/init.sh" From c00e8e26d60f322af3194fbc3e72a74fd35e0743 Mon Sep 17 00:00:00 2001 From: Thomas Nordentoft Date: Sat, 8 Aug 2026 17:18:34 +0200 Subject: [PATCH 2/5] Add workflow --- .github/workflows/test.yml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..aff8284 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,32 @@ +name: Test + +on: + push: + branches: + - main + - master + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.10", "3.12"] + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install uv + uses: astral-sh/setup-uv@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: uv sync --frozen --dev + + - name: Run tests + run: uv run pytest tests -q --tb=short From 0845da75cfb9c7b61e371d3f6a8437c62fd3a008 Mon Sep 17 00:00:00 2001 From: Thomas Nordentoft Date: Sat, 8 Aug 2026 17:32:00 +0200 Subject: [PATCH 3/5] Add export of path --- apply.sh | 2 ++ backup.sh | 2 ++ ensure-dependencies.sh | 2 -- restore.sh | 2 ++ scripts/lib.sh | 3 +++ scripts/runtime_path.sh | 3 +++ 6 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 scripts/runtime_path.sh diff --git a/apply.sh b/apply.sh index 3548c19..20fdd8d 100755 --- a/apply.sh +++ b/apply.sh @@ -3,6 +3,8 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +# shellcheck source=scripts/runtime_path.sh +source "${SCRIPT_DIR}/scripts/runtime_path.sh" ensure_dependencies="false" python_args=() diff --git a/backup.sh b/backup.sh index 5de0a0a..e9d301e 100755 --- a/backup.sh +++ b/backup.sh @@ -3,4 +3,6 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +# shellcheck source=scripts/runtime_path.sh +source "${SCRIPT_DIR}/scripts/runtime_path.sh" exec uv run python "${SCRIPT_DIR}/scripts/backup.py" run "$@" diff --git a/ensure-dependencies.sh b/ensure-dependencies.sh index cfc2d8f..e8afcdf 100755 --- a/ensure-dependencies.sh +++ b/ensure-dependencies.sh @@ -8,8 +8,6 @@ source "${SCRIPT_DIR}/scripts/lib.sh" # shellcheck source=scripts/deps_config.sh source "${SCRIPT_DIR}/scripts/deps_config.sh" -export PATH="${HOME}/.local/bin:${PATH}" - ensure_git() { if command -v git &>/dev/null; then success "git present ($(git --version | head -1))" diff --git a/restore.sh b/restore.sh index bcf6045..696b0f4 100755 --- a/restore.sh +++ b/restore.sh @@ -3,6 +3,8 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +# shellcheck source=scripts/runtime_path.sh +source "${SCRIPT_DIR}/scripts/runtime_path.sh" if [[ "${1:-}" == "--list" ]]; then shift diff --git a/scripts/lib.sh b/scripts/lib.sh index 7b18761..2d98617 100644 --- a/scripts/lib.sh +++ b/scripts/lib.sh @@ -4,5 +4,8 @@ _lib_sh_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" _ocd_project_root="$(cd "${_lib_sh_dir}/.." && pwd)" +# shellcheck source=scripts/runtime_path.sh +source "${_lib_sh_dir}/runtime_path.sh" + # shellcheck source=easydeploy-lib/lib/init.sh source "${_ocd_project_root}/easydeploy-lib/lib/init.sh" diff --git a/scripts/runtime_path.sh b/scripts/runtime_path.sh new file mode 100644 index 0000000..54e1c4b --- /dev/null +++ b/scripts/runtime_path.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +# scripts/runtime_path.sh — uv and other user-local tools (official uv installer) +export PATH="${HOME}/.local/bin:${PATH}" From 5ad2c4de516c9512ec3cc204cb2c2c042c226f67 Mon Sep 17 00:00:00 2001 From: Thomas Nordentoft Date: Sat, 8 Aug 2026 17:37:36 +0200 Subject: [PATCH 4/5] Simplify --- apply.sh | 5 ++--- backup-bundle.sh | 2 +- backup.sh | 4 +--- diagnose.sh | 4 ++-- restore-borg.sh | 2 +- restore-bundle.sh | 2 +- restore.sh | 13 ++++++------- scripts/lib.sh | 3 --- scripts/runtime_path.sh | 3 --- wizard.sh | 2 +- 10 files changed, 15 insertions(+), 25 deletions(-) delete mode 100644 scripts/runtime_path.sh diff --git a/apply.sh b/apply.sh index 20fdd8d..b7cabb3 100755 --- a/apply.sh +++ b/apply.sh @@ -3,8 +3,7 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -# shellcheck source=scripts/runtime_path.sh -source "${SCRIPT_DIR}/scripts/runtime_path.sh" +PYTHON="${SCRIPT_DIR}/.venv/bin/python" ensure_dependencies="false" python_args=() @@ -24,4 +23,4 @@ if [[ "$ensure_dependencies" == "true" ]]; then bash "${SCRIPT_DIR}/ensure-dependencies.sh" fi -uv run python "${SCRIPT_DIR}/scripts/apply.py" "${python_args[@]}" +exec "$PYTHON" "${SCRIPT_DIR}/scripts/apply.py" "${python_args[@]}" diff --git a/backup-bundle.sh b/backup-bundle.sh index eaf7631..448d7fe 100755 --- a/backup-bundle.sh +++ b/backup-bundle.sh @@ -10,4 +10,4 @@ if [[ -f "${SCRIPT_DIR}/deploy.yaml" ]] && docker inspect opencloud &>/dev/null warn "OpenCloud is running — for a consistent backup, run: bash stop.sh" fi -exec uv run python "${SCRIPT_DIR}/scripts/bundle.py" create "$@" +exec "${SCRIPT_DIR}/.venv/bin/python" "${SCRIPT_DIR}/scripts/bundle.py" create "$@" diff --git a/backup.sh b/backup.sh index e9d301e..3cfd697 100755 --- a/backup.sh +++ b/backup.sh @@ -3,6 +3,4 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -# shellcheck source=scripts/runtime_path.sh -source "${SCRIPT_DIR}/scripts/runtime_path.sh" -exec uv run python "${SCRIPT_DIR}/scripts/backup.py" run "$@" +exec "${SCRIPT_DIR}/.venv/bin/python" "${SCRIPT_DIR}/scripts/backup.py" run "$@" diff --git a/diagnose.sh b/diagnose.sh index 7e8d7ee..6d26c8f 100755 --- a/diagnose.sh +++ b/diagnose.sh @@ -17,7 +17,7 @@ OC_DOMAIN="${OC_DOMAIN:-}" EURO_DOMAIN="${EURO_OFFICE_DOMAIN:-}" if [[ -z "$OC_DOMAIN" && -f "$DEPLOY_YAML" ]]; then - OC_DOMAIN="$(uv run python - </dev/null || true + OC_DOMAIN="$("${SCRIPT_DIR}/.venv/bin/python" - </dev/null || true import yaml from pathlib import Path data = yaml.safe_load(Path("${DEPLOY_YAML}").read_text()) or {} @@ -27,7 +27,7 @@ PY fi if [[ -z "$EURO_DOMAIN" && -f "$DEPLOY_YAML" ]]; then - EURO_DOMAIN="$(uv run python - </dev/null || true + EURO_DOMAIN="$("${SCRIPT_DIR}/.venv/bin/python" - </dev/null || true import yaml from pathlib import Path data = yaml.safe_load(Path("${DEPLOY_YAML}").read_text()) or {} diff --git a/restore-borg.sh b/restore-borg.sh index e40b114..48319a0 100755 --- a/restore-borg.sh +++ b/restore-borg.sh @@ -34,7 +34,7 @@ info "Installing dependencies…" bash "${SCRIPT_DIR}/ensure-dependencies.sh" info "Restoring from Borg repository…" -uv run python "${SCRIPT_DIR}/scripts/backup.py" fresh-restore --latest "$@" +"${SCRIPT_DIR}/.venv/bin/python" "${SCRIPT_DIR}/scripts/backup.py" fresh-restore --latest "$@" info "Starting OpenCloud stack…" bash "${SCRIPT_DIR}/apply.sh" diff --git a/restore-bundle.sh b/restore-bundle.sh index 1da99a5..9126e11 100755 --- a/restore-bundle.sh +++ b/restore-bundle.sh @@ -29,7 +29,7 @@ info "Installing dependencies…" bash "${SCRIPT_DIR}/ensure-dependencies.sh" info "Restoring files from ${BUNDLE}…" -uv run python "${SCRIPT_DIR}/scripts/bundle.py" restore "$BUNDLE" --skip-apply +"${SCRIPT_DIR}/.venv/bin/python" "${SCRIPT_DIR}/scripts/bundle.py" restore "$BUNDLE" --skip-apply info "Starting OpenCloud stack…" bash "${SCRIPT_DIR}/apply.sh" diff --git a/restore.sh b/restore.sh index 696b0f4..0e7659b 100755 --- a/restore.sh +++ b/restore.sh @@ -3,17 +3,16 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -# shellcheck source=scripts/runtime_path.sh -source "${SCRIPT_DIR}/scripts/runtime_path.sh" +PYTHON="${SCRIPT_DIR}/.venv/bin/python" if [[ "${1:-}" == "--list" ]]; then shift - exec uv run python "${SCRIPT_DIR}/scripts/backup.py" list "$@" + exec "$PYTHON" "${SCRIPT_DIR}/scripts/backup.py" list "$@" fi if [[ "${1:-}" == "--latest" ]]; then shift - exec uv run python "${SCRIPT_DIR}/scripts/backup.py" restore --latest "$@" + exec "$PYTHON" "${SCRIPT_DIR}/scripts/backup.py" restore --latest "$@" fi if [[ "${1:-}" == "--archive" ]]; then @@ -21,12 +20,12 @@ if [[ "${1:-}" == "--archive" ]]; then archive="${1:-}" [[ -n "$archive" ]] || { echo "Usage: restore.sh --archive NAME [--dry-run]" >&2; exit 1; } shift - exec uv run python "${SCRIPT_DIR}/scripts/backup.py" restore --archive "$archive" "$@" + exec "$PYTHON" "${SCRIPT_DIR}/scripts/backup.py" restore --archive "$archive" "$@" fi if [[ "${1:-}" == "--dry-run" ]]; then shift - exec uv run python "${SCRIPT_DIR}/scripts/backup.py" restore --dry-run "$@" + exec "$PYTHON" "${SCRIPT_DIR}/scripts/backup.py" restore --dry-run "$@" fi cat < Date: Sat, 8 Aug 2026 17:46:50 +0200 Subject: [PATCH 5/5] Use uv run --- apply.sh | 6 ++++-- backup-bundle.sh | 3 ++- backup.sh | 5 ++++- diagnose.sh | 5 +++-- ensure-dependencies.sh | 2 ++ restore-borg.sh | 3 ++- restore-bundle.sh | 3 ++- restore.sh | 14 ++++++++------ scripts/lib.sh | 2 ++ wizard.sh | 3 ++- 10 files changed, 31 insertions(+), 15 deletions(-) diff --git a/apply.sh b/apply.sh index b7cabb3..dce41e7 100755 --- a/apply.sh +++ b/apply.sh @@ -3,7 +3,9 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PYTHON="${SCRIPT_DIR}/.venv/bin/python" +# shellcheck source=scripts/lib.sh +source "${SCRIPT_DIR}/scripts/lib.sh" +cd "${SCRIPT_DIR}" ensure_dependencies="false" python_args=() @@ -23,4 +25,4 @@ if [[ "$ensure_dependencies" == "true" ]]; then bash "${SCRIPT_DIR}/ensure-dependencies.sh" fi -exec "$PYTHON" "${SCRIPT_DIR}/scripts/apply.py" "${python_args[@]}" +exec uv run python -m scripts.apply "${python_args[@]}" diff --git a/backup-bundle.sh b/backup-bundle.sh index 448d7fe..93e382e 100755 --- a/backup-bundle.sh +++ b/backup-bundle.sh @@ -5,9 +5,10 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # shellcheck source=scripts/lib.sh source "${SCRIPT_DIR}/scripts/lib.sh" +cd "${SCRIPT_DIR}" if [[ -f "${SCRIPT_DIR}/deploy.yaml" ]] && docker inspect opencloud &>/dev/null 2>&1; then warn "OpenCloud is running — for a consistent backup, run: bash stop.sh" fi -exec "${SCRIPT_DIR}/.venv/bin/python" "${SCRIPT_DIR}/scripts/bundle.py" create "$@" +exec uv run python -m scripts.bundle create "$@" diff --git a/backup.sh b/backup.sh index 3cfd697..6a8ca5d 100755 --- a/backup.sh +++ b/backup.sh @@ -3,4 +3,7 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -exec "${SCRIPT_DIR}/.venv/bin/python" "${SCRIPT_DIR}/scripts/backup.py" run "$@" +# shellcheck source=scripts/lib.sh +source "${SCRIPT_DIR}/scripts/lib.sh" +cd "${SCRIPT_DIR}" +exec uv run python -m scripts.backup run "$@" diff --git a/diagnose.sh b/diagnose.sh index 6d26c8f..70023ec 100755 --- a/diagnose.sh +++ b/diagnose.sh @@ -5,6 +5,7 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # shellcheck source=scripts/lib.sh source "${SCRIPT_DIR}/scripts/lib.sh" +cd "${SCRIPT_DIR}" COMPOSE_ENV="${SCRIPT_DIR}/opencloud-compose/.env" DEPLOY_YAML="${SCRIPT_DIR}/deploy.yaml" @@ -17,7 +18,7 @@ OC_DOMAIN="${OC_DOMAIN:-}" EURO_DOMAIN="${EURO_OFFICE_DOMAIN:-}" if [[ -z "$OC_DOMAIN" && -f "$DEPLOY_YAML" ]]; then - OC_DOMAIN="$("${SCRIPT_DIR}/.venv/bin/python" - </dev/null || true + OC_DOMAIN="$(uv run python - </dev/null || true import yaml from pathlib import Path data = yaml.safe_load(Path("${DEPLOY_YAML}").read_text()) or {} @@ -27,7 +28,7 @@ PY fi if [[ -z "$EURO_DOMAIN" && -f "$DEPLOY_YAML" ]]; then - EURO_DOMAIN="$("${SCRIPT_DIR}/.venv/bin/python" - </dev/null || true + EURO_DOMAIN="$(uv run python - </dev/null || true import yaml from pathlib import Path data = yaml.safe_load(Path("${DEPLOY_YAML}").read_text()) or {} diff --git a/ensure-dependencies.sh b/ensure-dependencies.sh index e8afcdf..920a26b 100755 --- a/ensure-dependencies.sh +++ b/ensure-dependencies.sh @@ -42,6 +42,7 @@ ensure_submodules() { } ensure_uv() { + export PATH="${HOME}/.local/bin:${PATH}" if command -v uv &>/dev/null; then success "uv present ($(uv --version))" return @@ -56,6 +57,7 @@ ensure_uv() { } ensure_python_deps() { + export PATH="${HOME}/.local/bin:${PATH}" info "Syncing Python dependencies (uv sync --dev)…" uv sync --dev --directory "${SCRIPT_DIR}" success "Python dependencies ready" diff --git a/restore-borg.sh b/restore-borg.sh index 48319a0..7b5225d 100755 --- a/restore-borg.sh +++ b/restore-borg.sh @@ -34,7 +34,8 @@ info "Installing dependencies…" bash "${SCRIPT_DIR}/ensure-dependencies.sh" info "Restoring from Borg repository…" -"${SCRIPT_DIR}/.venv/bin/python" "${SCRIPT_DIR}/scripts/backup.py" fresh-restore --latest "$@" +cd "${SCRIPT_DIR}" +uv run python -m scripts.backup fresh-restore --latest "$@" info "Starting OpenCloud stack…" bash "${SCRIPT_DIR}/apply.sh" diff --git a/restore-bundle.sh b/restore-bundle.sh index 9126e11..fb94517 100755 --- a/restore-bundle.sh +++ b/restore-bundle.sh @@ -29,7 +29,8 @@ info "Installing dependencies…" bash "${SCRIPT_DIR}/ensure-dependencies.sh" info "Restoring files from ${BUNDLE}…" -"${SCRIPT_DIR}/.venv/bin/python" "${SCRIPT_DIR}/scripts/bundle.py" restore "$BUNDLE" --skip-apply +cd "${SCRIPT_DIR}" +uv run python -m scripts.bundle restore "$BUNDLE" --skip-apply info "Starting OpenCloud stack…" bash "${SCRIPT_DIR}/apply.sh" diff --git a/restore.sh b/restore.sh index 0e7659b..3ca20bd 100755 --- a/restore.sh +++ b/restore.sh @@ -3,16 +3,18 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PYTHON="${SCRIPT_DIR}/.venv/bin/python" +# shellcheck source=scripts/lib.sh +source "${SCRIPT_DIR}/scripts/lib.sh" +cd "${SCRIPT_DIR}" if [[ "${1:-}" == "--list" ]]; then shift - exec "$PYTHON" "${SCRIPT_DIR}/scripts/backup.py" list "$@" + exec uv run python -m scripts.backup list "$@" fi if [[ "${1:-}" == "--latest" ]]; then shift - exec "$PYTHON" "${SCRIPT_DIR}/scripts/backup.py" restore --latest "$@" + exec uv run python -m scripts.backup restore --latest "$@" fi if [[ "${1:-}" == "--archive" ]]; then @@ -20,12 +22,12 @@ if [[ "${1:-}" == "--archive" ]]; then archive="${1:-}" [[ -n "$archive" ]] || { echo "Usage: restore.sh --archive NAME [--dry-run]" >&2; exit 1; } shift - exec "$PYTHON" "${SCRIPT_DIR}/scripts/backup.py" restore --archive "$archive" "$@" + exec uv run python -m scripts.backup restore --archive "$archive" "$@" fi if [[ "${1:-}" == "--dry-run" ]]; then shift - exec "$PYTHON" "${SCRIPT_DIR}/scripts/backup.py" restore --dry-run "$@" + exec uv run python -m scripts.backup restore --dry-run "$@" fi cat <