From 459bde0f380fc325a00e675bbc1597d6ab4d88cb Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 11 Aug 2026 13:27:35 +0000 Subject: [PATCH] Make tab completion + backup pruning setup unconditional in setup.sh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both were only ever wired up from inside install_base(), so a box that went straight to a direct single-service install (sudo ./setup.sh beszel-agent, or any other service) without first explicitly running `sudo ./setup.sh base` never got either — the direct-install branch exits before the guided flow's own `run_service base` call is ever reached. Confirmed live: tab completion doesn't work on a fresh box that installed beszel-agent first. Moved the call site to setup.sh itself, right after the --list/--status early exits (which stay read-only and don't require root) and before every other branch (configure, --remove, direct install, guided flow) — all of which are downstream of that point regardless of which one actually runs. Both helpers are idempotent and already no-prompt by design, so calling them unconditionally on every invocation is safe; skipped under --dry-run (with an equivalent [DRY-RUN] message) so a preview run doesn't write real files. install_base()'s own calls to both are now fully redundant (base.sh has no standalone-bootstrap block, so install_base() is only ever reached downstream of setup.sh's new call site) and removed, along with the two DRY-RUN preview lines that described them there. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01H4k6J1qXXyYxhGEgnJaMvn --- services/base.sh | 27 ++++++++++++++++----------- setup.sh | 21 +++++++++++++++++++++ 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/services/base.sh b/services/base.sh index f776807..1d14d62 100644 --- a/services/base.sh +++ b/services/base.sh @@ -22,8 +22,6 @@ install_base() { echo "[DRY-RUN] Would offer Caddy reverse proxy install (full repo only)" echo "[DRY-RUN] Would offer CrowdSec intrusion prevention install (full repo only)" echo "[DRY-RUN] Would offer to add SSH Host aliases to ~/.ssh/config" - echo "[DRY-RUN] Would add setup.sh tab completion to ~/.bashrc (if not already there)" - echo "[DRY-RUN] Would set up daily pruning of old *.backup.* config files (systemd timer, if not already there)" return 0 fi @@ -85,11 +83,17 @@ install_base() { # ── SSH Host aliases ───────────────────────────────────────────────────── _base_setup_ssh_aliases - # ── setup.sh tab completion ───────────────────────────────────────────── - _base_setup_tab_completion - - # ── Old config-backup pruning ──────────────────────────────────────────── - _base_setup_backup_pruning + # setup.sh tab completion and old-config-backup pruning are no longer + # called from here — setup.sh itself now runs both unconditionally on + # every invocation (see the block right after --list/--status in + # setup.sh), since install_base() only ever runs downstream of that + # point anyway (base.sh has no standalone-bootstrap block — see the + # header comment — so it's only ever reached via setup.sh's own + # dispatcher). Calling them here too would just be a redundant, harmless + # no-op given both are idempotent, but the single call site in setup.sh + # is the one that actually matters: it's what fixed a box that ran e.g. + # `sudo ./setup.sh beszel-agent` directly and never explicitly ran + # `base` first, which used to mean tab completion never got set up. } # Wires tools/setup-completion.bash into ACTUAL_USER's shell automatically — @@ -104,10 +108,11 @@ _base_setup_tab_completion() { [ -f "$bashrc" ] || return 0 grep -qF "$comp_script" "$bashrc" 2>/dev/null && return 0 - # No DRY_RUN check here — install_base()'s own top-level one (above) - # already returns before this helper is ever called in that mode, - # unlike install_glow()'s check further down, which is independently - # invokable (sudo ./setup.sh glow --dry-run) and genuinely reachable. + # No DRY_RUN check here — setup.sh's own top-level call site (see the + # block right after --list/--status) already skips calling this at all + # when --dry-run is set, unlike install_glow()'s check further down, + # which is independently invokable (sudo ./setup.sh glow --dry-run) and + # genuinely reachable. { echo "" echo "# ubuntu-post-install: setup.sh tab completion" diff --git a/setup.sh b/setup.sh index e5d19e1..fca3b90 100755 --- a/setup.sh +++ b/setup.sh @@ -267,6 +267,27 @@ if [ "$DO_LIST" = true ]; then list_services; exit 0; fi # ── --status ───────────────────────────────────────────────────────────────── if [ "$DO_STATUS" = true ]; then print_status; exit 0; fi +# ── Tab completion + backup pruning: always on, regardless of which branch ── +# below actually runs (configure, --remove, direct install, or the guided +# flow). Both used to only be wired up from inside install_base() — meaning +# a box that never explicitly ran `sudo ./setup.sh base` first (e.g. went +# straight to `sudo ./setup.sh beszel-agent`, the direct-install path, which +# exits before the guided flow's own `run_service base` call ever runs) +# never got either. Both are idempotent and no-prompt by design (see their +# own comments in services/base.sh), so running them unconditionally here on +# every invocation is safe. Skipped under --dry-run (would otherwise write +# real files during what's supposed to be a preview) and never reached by +# --list/--status above, which stay read-only and deliberately don't require +# root. +if [ "$DRY_RUN" = true ]; then + echo "[DRY-RUN] Would add setup.sh tab completion to ~/.bashrc (if not already there)" + echo "[DRY-RUN] Would set up daily pruning of old *.backup.* config files (systemd timer, if not already there)" +else + require_root + declare -F _base_setup_tab_completion >/dev/null 2>&1 && _base_setup_tab_completion + declare -F _base_setup_backup_pruning >/dev/null 2>&1 && _base_setup_backup_pruning +fi + # ── configure: show/update site-wide defaults ──────────────────────────────── if [ "${REQUESTED[*]:-}" = "configure" ]; then require_root