Files
dotfiles/lib/fetch.sh
T
noconnorandClaude Opus 4.8 ebdc213444 bin/: swap seed tools for devops CLIs; add ansible/ module
Replace the placeholder ripgrep/fd/bat/fzf set with devops tooling, keeping
jq: kubectl, helm, k9s, kubectx/kubens, stern, yq, OpenTofu, and terragrunt
— all self-contained, statically linked release binaries in ~/.local/bin,
so they persist across Kasm redeploys with no reinstall.

Switch idempotency from parsing each tool's --version (kubectl/helm/k9s have
no uniform flag) to a version stamp under ~/.local/bin/.versions, and add
fetch_arch_deb() for the amd64/arm64 naming most devops tools use.

Ansible is Python, not a single binary, so it gets its own module: a venv at
~/.local/opt/ansible with its CLIs symlinked into ~/.local/bin. The guard
verifies ansible actually runs (a redeploy can wipe the system python the
venv links to) and rebuilds if not.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 10:34:01 -04:00

85 lines
2.6 KiB
Bash

#!/usr/bin/env sh
# lib/fetch.sh — helpers for installing userland binaries into ~/.local/bin.
#
# Everything lands under $HOME, so installed tools survive Kasm redeploys
# (which wipe the root filesystem but keep $HOME) with no reinstall needed.
# No sudo, no system packages. Prefer statically linked release binaries so
# they keep working even after the root fs — and its shared libraries — is
# reset.
#
# Source this (callers already run `set -eu`), then use fetch_arch /
# fetch_arch_deb, have_version + mark_version, install_tarball_bin, and
# install_raw_bin.
BIN_DIR="${BIN_DIR:-$HOME/.local/bin}"
VERSION_DIR="$BIN_DIR/.versions"
fsay() { printf '%s\n' "$*" >&2; }
# Normalize `uname -m` to the tokens rust-style release names use.
fetch_arch() {
case "$(uname -m)" in
x86_64|amd64) printf 'x86_64\n' ;;
aarch64|arm64) printf 'aarch64\n' ;;
*) fsay "fetch: unsupported arch $(uname -m)"; return 1 ;;
esac
}
# Same, but in the Go/Debian token style most devops tools use.
fetch_arch_deb() {
case "$(uname -m)" in
x86_64|amd64) printf 'amd64\n' ;;
aarch64|arm64) printf 'arm64\n' ;;
*) fsay "fetch: unsupported arch $(uname -m)"; return 1 ;;
esac
}
# Download <url> to <dest-file> using whatever downloader is available.
_fetch_dl() {
if command -v curl >/dev/null 2>&1; then
curl -fsSL "$1" -o "$2"
elif command -v wget >/dev/null 2>&1; then
wget -qO "$2" "$1"
else
fsay "fetch: need curl or wget"; return 1
fi
}
# have_version <name> <version> — true if <name> is installed and was
# stamped at <version>, so bootstrap can skip a re-download. Versions are
# recorded in ~/.local/bin/.versions rather than parsed from each tool's
# `--version` output, which varies wildly (kubectl/helm/k9s have no uniform
# flag).
have_version() {
[ -x "$BIN_DIR/$1" ] && [ -f "$VERSION_DIR/$1" ] &&
[ "$(cat "$VERSION_DIR/$1")" = "$2" ]
}
# mark_version <name> <version> — record the installed version.
mark_version() {
mkdir -p "$VERSION_DIR"
printf '%s\n' "$2" >"$VERSION_DIR/$1"
}
# install_tarball_bin <url> <path-within-archive> <dest-name> — download a
# .tar.gz, extract, and install one binary from it into ~/.local/bin.
install_tarball_bin() {
mkdir -p "$BIN_DIR"
_tmp="$(mktemp -d)"
_fetch_dl "$1" "$_tmp/archive.tar.gz"
tar -xzf "$_tmp/archive.tar.gz" -C "$_tmp"
install -m 0755 "$_tmp/$2" "$BIN_DIR/$3"
rm -rf "$_tmp"
fsay "installed $BIN_DIR/$3"
}
# install_raw_bin <url> <dest-name> — download a single raw binary.
install_raw_bin() {
mkdir -p "$BIN_DIR"
_tmp="$(mktemp)"
_fetch_dl "$1" "$_tmp"
install -m 0755 "$_tmp" "$BIN_DIR/$2"
rm -f "$_tmp"
fsay "installed $BIN_DIR/$2"
}