feat(hooks): install missing tools instead of warning
setup-hooks.sh now installs shellcheck, jq, and yq if absent rather than warning and continuing. Follows the same install pattern as setup-gitleaks.sh (curl + install to TOOL_INSTALL_DIR=/usr/local/bin, OS/arch detection, pinned versions). Pinned versions: shellcheck 0.10.0, jq 1.7.1, yq 4.44.3. The deployed pre-commit hook retains its runtime fallbacks as a safety net for environments where tools are removed after setup. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TP4EGbBg3XMcyF28Lx78XJ
This commit is contained in:
@@ -6,6 +6,11 @@ set -euo pipefail
|
||||
# TARGET_REPO — path to the git repo to configure (default: current directory)
|
||||
# Idempotent: safe to re-run; always replaces each managed block with the current version.
|
||||
|
||||
SHELLCHECK_VERSION="0.10.0"
|
||||
JQ_VERSION="1.7.1"
|
||||
YQ_VERSION="4.44.3"
|
||||
TOOL_INSTALL_DIR="${TOOL_INSTALL_DIR:-/usr/local/bin}"
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
TARGET="${1:-$(pwd)}"
|
||||
MARKER="# managed by setup-hooks.sh"
|
||||
@@ -16,18 +21,78 @@ if [[ ! -d "$TARGET/.git" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Tool checks (optional — warn, don't fail) ---
|
||||
# --- Tool installation ---
|
||||
|
||||
warn_if_missing() {
|
||||
_os() {
|
||||
case "$(uname -s)" in
|
||||
Linux) echo "linux" ;;
|
||||
Darwin) echo "darwin" ;;
|
||||
*) echo "Error: unsupported OS '$(uname -s)'" >&2; exit 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
_arch() {
|
||||
case "$(uname -m)" in
|
||||
x86_64) echo "x86_64" ;;
|
||||
aarch64 | arm64) echo "aarch64" ;;
|
||||
*) echo "Error: unsupported architecture '$(uname -m)'" >&2; exit 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
install_shellcheck() {
|
||||
local os arch tarball url tmp_dir
|
||||
os="$(_os)"
|
||||
arch="$(_arch)"
|
||||
tarball="shellcheck-v${SHELLCHECK_VERSION}.${os}.${arch}.tar.xz"
|
||||
url="https://github.com/koalaman/shellcheck/releases/download/v${SHELLCHECK_VERSION}/${tarball}"
|
||||
tmp_dir="$(mktemp -d)"
|
||||
trap 'rm -rf "$tmp_dir"' RETURN
|
||||
echo "Installing shellcheck v${SHELLCHECK_VERSION}..."
|
||||
curl -fsSL "$url" -o "$tmp_dir/$tarball"
|
||||
tar -xJf "$tmp_dir/$tarball" -C "$tmp_dir" --strip-components=1
|
||||
install -m 755 "$tmp_dir/shellcheck" "$TOOL_INSTALL_DIR/shellcheck"
|
||||
echo "Installed: $TOOL_INSTALL_DIR/shellcheck"
|
||||
}
|
||||
|
||||
install_jq() {
|
||||
local os arch binary url tmp_dir
|
||||
os="$(_os)"
|
||||
arch="$(_arch | sed 's/x86_64/amd64/; s/aarch64/arm64/')"
|
||||
[[ "$(_os)" == "darwin" ]] && os="macos"
|
||||
binary="jq-${os}-${arch}"
|
||||
url="https://github.com/jqlang/jq/releases/download/jq-${JQ_VERSION}/${binary}"
|
||||
tmp_dir="$(mktemp -d)"
|
||||
trap 'rm -rf "$tmp_dir"' RETURN
|
||||
echo "Installing jq v${JQ_VERSION}..."
|
||||
curl -fsSL "$url" -o "$tmp_dir/jq"
|
||||
install -m 755 "$tmp_dir/jq" "$TOOL_INSTALL_DIR/jq"
|
||||
echo "Installed: $TOOL_INSTALL_DIR/jq"
|
||||
}
|
||||
|
||||
install_yq() {
|
||||
local os arch binary url tmp_dir
|
||||
os="$(_os)"
|
||||
arch="$(_arch | sed 's/x86_64/amd64/; s/aarch64/arm64/')"
|
||||
binary="yq_${os}_${arch}"
|
||||
url="https://github.com/mikefarah/yq/releases/download/v${YQ_VERSION}/${binary}"
|
||||
tmp_dir="$(mktemp -d)"
|
||||
trap 'rm -rf "$tmp_dir"' RETURN
|
||||
echo "Installing yq v${YQ_VERSION}..."
|
||||
curl -fsSL "$url" -o "$tmp_dir/yq"
|
||||
install -m 755 "$tmp_dir/yq" "$TOOL_INSTALL_DIR/yq"
|
||||
echo "Installed: $TOOL_INSTALL_DIR/yq"
|
||||
}
|
||||
|
||||
ensure_tool() {
|
||||
local tool="$1"
|
||||
if ! command -v "$tool" &>/dev/null; then
|
||||
echo "Warning: $tool not installed — ${tool} checks in pre-commit will be skipped (install $tool to enable)" >&2
|
||||
"install_${tool}"
|
||||
fi
|
||||
}
|
||||
|
||||
warn_if_missing shellcheck
|
||||
warn_if_missing jq
|
||||
warn_if_missing yq
|
||||
ensure_tool shellcheck
|
||||
ensure_tool jq
|
||||
ensure_tool yq
|
||||
|
||||
# --- Marker-block helpers ---
|
||||
|
||||
|
||||
@@ -165,27 +165,37 @@ for hook_file in "$REPO5/.git/hooks/commit-msg" "$REPO5/.git/hooks/pre-commit" "
|
||||
fi
|
||||
done
|
||||
|
||||
# --- 7. Hooks contain graceful degradation paths for missing tools ---
|
||||
# --- 7. Setup installs tools; no "not installed" warnings when tools present ---
|
||||
echo ""
|
||||
echo "--- hooks contain graceful degradation for missing tools ---"
|
||||
echo "--- setup does not warn when tools are available ---"
|
||||
REPO6="$(make_repo)"
|
||||
trap 'rm -rf "$REPO6"' EXIT
|
||||
bash "$SCRIPT" "$REPO6" > /dev/null 2>&1
|
||||
PRE_COMMIT6="$REPO6/.git/hooks/pre-commit"
|
||||
output6="$(bash "$SCRIPT" "$REPO6" 2>&1)"
|
||||
for tool in shellcheck jq yq; do
|
||||
if grep -q "Warning:.*$tool\|$tool.*not installed\|$tool.*skipped" "$PRE_COMMIT6"; then
|
||||
pass "pre-commit hook has graceful degradation path for missing: $tool"
|
||||
if echo "$output6" | grep -qi "$tool not installed\|$tool.*not found"; then
|
||||
fail "setup warned about missing $tool — should install or already be present"
|
||||
else
|
||||
fail "pre-commit hook missing graceful degradation for: $tool"
|
||||
pass "setup emits no 'not installed' warning for: $tool (present or installed)"
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "--- setup always exits 0 (no hard dependency on optional tools) ---"
|
||||
echo "--- pre-commit hook retains runtime fallback for missing tools ---"
|
||||
PRE_COMMIT6="$REPO6/.git/hooks/pre-commit"
|
||||
for tool in shellcheck jq yq; do
|
||||
if grep -q "Warning:.*$tool\|$tool.*not installed\|$tool.*skipped" "$PRE_COMMIT6"; then
|
||||
pass "pre-commit hook has runtime fallback for missing: $tool"
|
||||
else
|
||||
fail "pre-commit hook missing runtime fallback for: $tool"
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "--- setup exits 0 when tools are present ---"
|
||||
REPO7="$(make_repo)"
|
||||
trap 'rm -rf "$REPO7"' EXIT
|
||||
if bash "$SCRIPT" "$REPO7" > /dev/null 2>&1; then
|
||||
pass "setup exits 0 when all optional tools are present"
|
||||
pass "setup exits 0 when tools are present"
|
||||
else
|
||||
fail "setup exited non-zero unexpectedly"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user