From 76222399495e695be07da88d6960d812dd50b749 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Padez?= Date: Wed, 12 Aug 2026 17:28:46 +0000 Subject: [PATCH] split the upstream binaries out of the package section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit lazydocker, lazygit, starship and fastfetch were buried inside "System Update & Essentials", after the package install and with no announcement — so a run appeared to be installing system packages and then started pulling tarballs and printing a five-shell starship tutorial. They are a different thing: upstream binaries on their own release cadence, not anything the distribution ships. Now their own step, announced in the same shape as the package section. Each is checked before it is fetched. The original re-ran every installer on every run, which is why a machine that already had starship got it reinstalled along with its "add this to your ~/.zshrc" instructions — advice this script does not want followed, since it writes the shell config itself. Its output is now dropped; errors still surface. Two real bugs fixed on the way: lazygit's asset name was hardcoded to x86_64, so on arm64 the download 404s and tar fails partway through the run. It now maps ARCH, and spells the architectures the way lazygit does rather than the way we do. The version was extracted with `tr -d 'v'`, which deletes every v in the string rather than the leading one. `${version#v}` instead. fastfetch stays a package but stops assuming the PPA is needed: Ubuntu picked it up in 24.10, so the repository is now checked first and the PPA added only where the archive has nothing. Verified on this host — noble genuinely has no candidate, so the PPA is still the only source here. Verified both branches of tools_install by stubbing the presence check. Co-Authored-By: Claude Opus 5 (1M context) --- scripts/setup/machine-setup/lib/tools.sh | 129 +++++++++++++++++++ scripts/setup/machine-setup/machine-setup.sh | 44 +++---- 2 files changed, 148 insertions(+), 25 deletions(-) create mode 100644 scripts/setup/machine-setup/lib/tools.sh diff --git a/scripts/setup/machine-setup/lib/tools.sh b/scripts/setup/machine-setup/lib/tools.sh new file mode 100644 index 00000000..f13874d6 --- /dev/null +++ b/scripts/setup/machine-setup/lib/tools.sh @@ -0,0 +1,129 @@ +#!/bin/bash +# ============================================================================= +# machine-setup — command-line tools that do not come from the distribution +# ============================================================================= +# +# Definitions only, like the other lib/ files. +# +# These four were buried inside "System Update & Essentials", after the package +# install and with no announcement, so a run appeared to be installing system +# packages and then started downloading tarballs and printing a shell tutorial. +# They are their own concern: upstream binaries, fetched from upstream, on their +# own release cadence. +# +# Each one is checked before it is fetched. The original re-ran every installer +# on every run — which is how a machine that already had starship got it +# reinstalled, along with its "add this to your ~/.zshrc" instructions, which we +# do not want because this script writes the shell config itself. + +[[ -n "${MACHINE_SETUP_TOOLS_LOADED:-}" ]] && return 0 +MACHINE_SETUP_TOOLS_LOADED=1 + +# The set installed on every machine, in the order they are fetched. +tools_default() { echo lazydocker lazygit starship fastfetch; } + +# The command that proves a tool is already here. Same as the tool name for all +# four today, but kept as a mapping because that is not a rule — a package and +# the binary it provides disagree often enough (fd-find/fdfind) to be worth the +# indirection. +tool_command() { + case "$1" in + lazydocker) echo lazydocker ;; + lazygit) echo lazygit ;; + starship) echo starship ;; + fastfetch) echo fastfetch ;; + *) echo "$1" ;; + esac +} + +tool_is_installed() { command -v "$(tool_command "$1")" &>/dev/null; } + +# ----------------------------------------------------------------------------- +# The installers +# ----------------------------------------------------------------------------- + +tool_install_lazydocker() { + curl -fsSL https://raw.githubusercontent.com/jesseduffield/lazydocker/master/scripts/install_update_linux.sh | + DIR=/usr/local/bin bash +} + +# The one that was actually broken on arm64: the asset name was hardcoded to +# x86_64, so an arm machine downloaded a 404 and tar failed halfway through the +# run. lazygit spells the architectures x86_64 and arm64, which is neither of the +# two spellings ARCH uses, hence the mapping. +tool_install_lazygit() { + local version asset url + case "$ARCH" in + amd64) asset="x86_64" ;; + arm64) asset="arm64" ;; + esac + + version="$(curl -fsSL https://api.github.com/repos/jesseduffield/lazygit/releases/latest | jq -r '.tag_name')" + # Strip only the leading v. The original used `tr -d 'v'`, which deletes every + # v in the string and would mangle any tag that had one anywhere else. + version="${version#v}" + [[ -n "$version" ]] || { + warn "could not read the latest lazygit version — skipping" + return 0 + } + + url="https://github.com/jesseduffield/lazygit/releases/download/v${version}/lazygit_${version}_Linux_${asset}.tar.gz" + curl -fsSLo /tmp/lazygit.tar.gz "$url" + tar -C /usr/local/bin -xzf /tmp/lazygit.tar.gz lazygit + rm -f /tmp/lazygit.tar.gz +} + +# Quiet on purpose. The installer ends by printing how to add starship to bash, +# zsh, ion, tcsh and xonsh — five shells' worth of instructions for a step that +# already writes the zsh config itself. Errors still come through. +tool_install_starship() { + curl -fsSL https://starship.rs/install.sh | sh -s -- -y -b /usr/local/bin >/dev/null +} + +# A distribution package everywhere, but not always one the distribution ships: +# Ubuntu only picked fastfetch up in 24.10, so on noble and older the PPA is the +# only source. Checked rather than assumed, so the PPA stops being added the +# moment the archive has it. +tool_install_fastfetch() { + if [[ "$PM" == "apt" ]] && ! apt-cache policy fastfetch 2>/dev/null | grep -q 'Candidate: [0-9]'; then + info " fastfetch is not in this release's archive — adding the upstream PPA" + add-apt-repository -y ppa:zhangsongcui3371/fastfetch >/dev/null 2>&1 || + { + warn "could not add the fastfetch PPA — skipping" + return 0 + } + pkg_refresh >/dev/null 2>&1 + fi + pkg_install_now fastfetch +} + +# ----------------------------------------------------------------------------- +# Acting +# ----------------------------------------------------------------------------- + +# Announce the section, then fetch only what is absent — same contract and same +# output shape as pkg_install, so the two read alike in a transcript. +tools_install() { + local label="$1" + shift + + local tool + local -a missing=() present=() + for tool in "$@"; do + if tool_is_installed "$tool"; then present+=("$tool"); else missing+=("$tool"); fi + done + + info "$label — installs what is missing, keeps what you already have" + ((${#present[@]})) && echo " already here: ${present[*]}" + + if ((${#missing[@]} == 0)); then + echo " to install: nothing, all present" + return 0 + fi + + echo " to install: ${missing[*]}" + for tool in "${missing[@]}"; do + info " installing ${tool}..." + "tool_install_${tool}" + done +} diff --git a/scripts/setup/machine-setup/machine-setup.sh b/scripts/setup/machine-setup/machine-setup.sh index da456ccd..d2c0ea06 100755 --- a/scripts/setup/machine-setup/machine-setup.sh +++ b/scripts/setup/machine-setup/machine-setup.sh @@ -20,6 +20,8 @@ PROGRESS_FILE="$SCRIPT_DIR/.setup-progress" source "$SCRIPT_DIR/lib/base.sh" # shellcheck source=lib/packages.sh source "$SCRIPT_DIR/lib/packages.sh" +# shellcheck source=lib/tools.sh +source "$SCRIPT_DIR/lib/tools.sh" # Trap errors with context. Installed here rather than in lib/base.sh, because # that file is definitions only and a trap is a side effect on whoever sources it. @@ -89,34 +91,26 @@ if ! skip; then # shellcheck disable=SC2046 # word splitting is how the list is passed pkg_install "Core packages" $(pkgs_core) - ok "System updated and essentials installed" + ok "System updated and core packages in place" + SUMMARY+=("System packages updated, core packages installed") + step_ok +fi - # lazydocker - info "Installing lazydocker..." - curl -fsSL https://raw.githubusercontent.com/jesseduffield/lazydocker/master/scripts/install_update_linux.sh | DIR=/usr/local/bin bash - ok "lazydocker installed" +# ============================================================================= +# 2b. Command-line tools +# ============================================================================= +# +# Separate from the packages above because they are a different thing: upstream +# binaries on their own release cadence, not anything the distribution ships. +# Lumping them in made a run look like it was installing system packages and +# then start downloading tarballs unannounced. - # lazygit - info "Installing lazygit..." - LAZYGIT_VERSION=$(curl -fsSL "https://api.github.com/repos/jesseduffield/lazygit/releases/latest" | jq -r '.tag_name' | tr -d 'v') - curl -fsSLo /tmp/lazygit.tar.gz "https://github.com/jesseduffield/lazygit/releases/download/v${LAZYGIT_VERSION}/lazygit_${LAZYGIT_VERSION}_Linux_x86_64.tar.gz" - tar -C /usr/local/bin -xzf /tmp/lazygit.tar.gz lazygit - rm -f /tmp/lazygit.tar.gz - ok "lazygit installed" +step "Command-line tools" +if ! skip; then + # shellcheck disable=SC2046 # word splitting is how the list is passed + tools_install "Command-line tools" $(tools_default) - # starship - info "Installing starship..." - curl -fsSL https://starship.rs/install.sh | sh -s -- -y - ok "starship installed" - - # fastfetch - info "Installing fastfetch..." - add-apt-repository -y ppa:zhangsongcui3371/fastfetch > /dev/null 2>&1 || true - apt-get update -y > /dev/null 2>&1 - apt-get install -y fastfetch - ok "fastfetch installed" - - SUMMARY+=("System packages updated and essentials installed") + SUMMARY+=("Command-line tools: $(tools_default)") step_ok fi