Files
holocron/tests/test-git-hooks-install.sh
Defame1297 a61a8d04a5 chore: add post-push hook to auto-refresh kyberforge plugin cache
Installing kyberforge via the holocron marketplace caches the plugin at a
specific version. After every push, the marketplace clone and plugin cache
need to be refreshed manually — otherwise new skills added since the last
install are invisible until the user runs `claude plugin update` manually.

Adds a post-push git hook that pulls the holocron marketplace clone and
updates the kyberforge cache automatically after every push, eliminating
the manual refresh step.

## Implementation Notes
- `scripts/git-hooks/post-push` is the canonical source; `install.sh` now
  copies all files in `scripts/git-hooks/` into `.git/hooks/` on fresh
  checkouts, making the pattern extensible for future hooks.
- Hook exits 0 on all failures (warns to stderr) — a stale cache refresh
  never blocks a completed push.
- 11 bats tests cover both the hook and the install.sh copy block, using
  mocked binaries and a temp-tree fixture to avoid touching real state.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P87CiC58Ru2PPWYTeXtjHT
2026-06-27 22:55:56 +00:00

120 lines
3.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# Tests for the git hook install block in scripts/install.sh.
# Runs install.sh from a temp repo to avoid touching the real .git/hooks/.
set -euo pipefail
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
PASS=0
FAIL=0
pass() { echo " PASS: $1"; PASS=$((PASS + 1)); }
fail() { echo " FAIL: $1"; FAIL=$((FAIL + 1)); }
# ---------------------------------------------------------------------------
# Temp repo setup
#
# install.sh derives REPO_ROOT from the script's own location, so copying it
# into a temp tree makes REPO_ROOT point there, not at the real checkout.
# ---------------------------------------------------------------------------
TEMP_REPO="$(mktemp -d)"
TEMP_HOME="$(mktemp -d)"
trap 'rm -rf "$TEMP_REPO" "$TEMP_HOME"' EXIT
mkdir -p "$TEMP_REPO/scripts"
mkdir -p "$TEMP_REPO/.git/hooks"
# Minimal deploy-manifest.sh — empty deploy lists so install.sh reaches the
# hook-copy block without attempting to copy files that don't exist in the
# temp tree.
cat > "$TEMP_REPO/scripts/deploy-manifest.sh" << 'EOF'
# shellcheck disable=SC2034
DEPLOY_FILES=()
DEPLOY_EXECUTABLES=()
DEPLOY_DIRS=()
DEPLOY_SKILLS_SRC=".agents/skills"
EOF
# Copy the real install.sh and git-hooks into the temp repo
cp "$REPO_ROOT/scripts/install.sh" "$TEMP_REPO/scripts/install.sh"
cp -r "$REPO_ROOT/scripts/git-hooks" "$TEMP_REPO/scripts/git-hooks"
HOOKS_SRC="$TEMP_REPO/scripts/git-hooks"
run_install() {
HOME="$TEMP_HOME" bash "$TEMP_REPO/scripts/install.sh" > /dev/null 2>&1
}
# ---------------------------------------------------------------------------
echo "--- hook install: files copied to .git/hooks/ ---"
# ---------------------------------------------------------------------------
run_install
for hook_file in "$HOOKS_SRC"/*; do
[[ -f "$hook_file" ]] || continue
hook_name="$(basename "$hook_file")"
if [[ -f "$TEMP_REPO/.git/hooks/$hook_name" ]]; then
pass "$hook_name installed to .git/hooks/"
else
fail "$hook_name missing from .git/hooks/"
fi
done
# ---------------------------------------------------------------------------
echo ""
echo "--- hook install: installed hooks are executable ---"
# ---------------------------------------------------------------------------
for hook_file in "$HOOKS_SRC"/*; do
[[ -f "$hook_file" ]] || continue
hook_name="$(basename "$hook_file")"
if [[ -x "$TEMP_REPO/.git/hooks/$hook_name" ]]; then
pass "$hook_name is executable"
else
fail "$hook_name is not executable"
fi
done
# ---------------------------------------------------------------------------
echo ""
echo "--- hook install: directories in git-hooks/ are not installed ---"
# ---------------------------------------------------------------------------
# Add a subdirectory to scripts/git-hooks/ — the install block must skip it
mkdir -p "$HOOKS_SRC/not-a-hook"
run_install
if [[ ! -e "$TEMP_REPO/.git/hooks/not-a-hook" ]]; then
pass "directories in scripts/git-hooks/ are not copied to .git/hooks/"
else
fail "a directory from scripts/git-hooks/ was incorrectly installed"
fi
rmdir "$HOOKS_SRC/not-a-hook"
# ---------------------------------------------------------------------------
echo ""
echo "--- hook install: idempotent ---"
# ---------------------------------------------------------------------------
run_install
for hook_file in "$HOOKS_SRC"/*; do
[[ -f "$hook_file" ]] || continue
hook_name="$(basename "$hook_file")"
if diff -q "$hook_file" "$TEMP_REPO/.git/hooks/$hook_name" > /dev/null 2>&1; then
pass "idempotent: $hook_name content unchanged after second install"
else
fail "idempotent: $hook_name content corrupted after second install"
fi
if [[ -x "$TEMP_REPO/.git/hooks/$hook_name" ]]; then
pass "idempotent: $hook_name still executable after second install"
else
fail "idempotent: $hook_name lost executable bit after second install"
fi
done
# ---------------------------------------------------------------------------
echo ""
echo "Results: $PASS passed, $FAIL failed"
[[ $FAIL -eq 0 ]]