fix(lint): make the Vale prefilter work for external consumers
pre-commit prefixes only entry[0] with the hook-repo clone path (cmd = (prefix.path(cmd[0]), *cmd[1:])), so the --config argument in .pre-commit-hooks.yaml resolved against the *consuming* repo's root and hard-failed every external run with E100. Two of the three hooks ADR-0014 promises were unusable. vale-wrap.sh now self-locates its config from BASH_SOURCE when no --config is supplied; an explicit --config still wins in all three argv forms and stays cwd-relative. Both manifests drop the argument and are kept byte-identical: the local repo: local config resolved --config correctly only because the consuming repo *was* this repo, and that divergence is why three review rounds missed the defect. Also in the wrapper: - replace GNU-only `realpath -m` with a portable abspath helper; -m is load-bearing (dest does not exist yet), so BSD realpath aborted the script under set -e on macOS - walk directory arguments instead of passing them through unflattened, which reported a clean 0-error run for files that fail when named explicitly - read/write with errors='surrogateescape' so one non-UTF-8 .md under a directory argument cannot abort the hook New test-vale-hooks-consumer.sh builds the hook repo from the working tree and points a file:// consumer at it, covering the manifest as a hook repo for the first time. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MCQ648fLSFXPHGZdQ8gn58
This commit is contained in:
127
tests/test-vale-hooks-consumer.sh
Executable file
127
tests/test-vale-hooks-consumer.sh
Executable file
@@ -0,0 +1,127 @@
|
||||
#!/usr/bin/env bash
|
||||
# Integration test for .pre-commit-hooks.yaml as an EXTERNAL hook repo — the
|
||||
# contract ADR-0014 exists to provide, and the one thing running pre-commit
|
||||
# inside this repo can never exercise: `repo: local` makes pre-commit's clone
|
||||
# prefix equal to the consuming repo's root, so a hook entry that only works
|
||||
# because those two coincide passes here and hard-fails everywhere else.
|
||||
# (It did: every argument after entry[0] resolves against the CONSUMING repo,
|
||||
# so a `--config plugins/.../.vale.ini` argument gave external consumers
|
||||
# `E100 [--config] Runtime error ... does not exist`, exit 2, on both Vale hooks.)
|
||||
#
|
||||
# The hook repo is built from the WORKING TREE, not from HEAD, so an uncommitted
|
||||
# change to the manifest or the wrapper is what gets tested.
|
||||
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)); }
|
||||
|
||||
for bin in pre-commit vale git; do
|
||||
if ! command -v "$bin" &>/dev/null; then
|
||||
echo "SKIP: $bin is not installed — cannot stand up a consumer repo"
|
||||
exit 77
|
||||
fi
|
||||
done
|
||||
|
||||
WORK="$(mktemp -d)"
|
||||
trap 'rm -rf "$WORK"' EXIT
|
||||
|
||||
HOOK_REPO="$WORK/hookrepo"
|
||||
CONSUMER="$WORK/consumer"
|
||||
export PRE_COMMIT_HOME="$WORK/pc-home"
|
||||
|
||||
mkdir -p "$HOOK_REPO/plugins/kyberforge/skills" "$HOOK_REPO/scripts"
|
||||
cp "$REPO_ROOT/.pre-commit-hooks.yaml" "$HOOK_REPO/"
|
||||
cp "$REPO_ROOT/scripts/skill-size-check.sh" "$HOOK_REPO/scripts/"
|
||||
for skill in skill-audit agent-audit; do
|
||||
mkdir -p "$HOOK_REPO/plugins/kyberforge/skills/$skill"
|
||||
cp -R "$REPO_ROOT/plugins/kyberforge/skills/$skill/scripts" \
|
||||
"$REPO_ROOT/plugins/kyberforge/skills/$skill/assets" \
|
||||
"$HOOK_REPO/plugins/kyberforge/skills/$skill/"
|
||||
done
|
||||
git -C "$HOOK_REPO" init -q
|
||||
git -C "$HOOK_REPO" add -A
|
||||
git -C "$HOOK_REPO" -c user.email=test@example.invalid -c user.name=test commit -qm "hook repo"
|
||||
HOOK_REV="$(git -C "$HOOK_REPO" rev-parse HEAD)"
|
||||
|
||||
# The two Vale hooks scope by filename, so the consumer needs one file of each
|
||||
# shape: a hook with nothing to match reports `Skipped` and proves nothing.
|
||||
mkdir -p "$CONSUMER/skills/demo" "$CONSUMER/agents"
|
||||
git -C "$CONSUMER" init -q
|
||||
cat > "$CONSUMER/.pre-commit-config.yaml" <<EOF
|
||||
repos:
|
||||
- repo: file://$HOOK_REPO
|
||||
rev: $HOOK_REV
|
||||
hooks:
|
||||
- id: kyberforge-vale-audit-skill
|
||||
- id: kyberforge-vale-audit-agent
|
||||
EOF
|
||||
|
||||
write_fixtures() {
|
||||
local body="$1"
|
||||
cat > "$CONSUMER/skills/demo/SKILL.md" <<EOF
|
||||
---
|
||||
name: demo
|
||||
description: >
|
||||
Use when the caller wants a demonstration skill $body across two
|
||||
physical lines of one folded block scalar.
|
||||
---
|
||||
|
||||
Body.
|
||||
EOF
|
||||
cat > "$CONSUMER/agents/demo.md" <<EOF
|
||||
---
|
||||
name: demo
|
||||
description: >
|
||||
Use when the caller wants a demonstration agent $body across two
|
||||
physical lines of one folded block scalar.
|
||||
---
|
||||
|
||||
Body.
|
||||
EOF
|
||||
git -C "$CONSUMER" add -A
|
||||
}
|
||||
|
||||
run_hooks() {
|
||||
(cd "$CONSUMER" && pre-commit run --all-files 2>&1) || true
|
||||
}
|
||||
|
||||
# --- 1. Both hooks resolve their config and actually gate on a bad file ---
|
||||
echo ""
|
||||
echo "--- both Vale hooks run and fail a bad file in an external consumer repo ---"
|
||||
write_fixtures "that helps with and utilize things"
|
||||
OUT_BAD="$(run_hooks)"
|
||||
if echo "$OUT_BAD" | grep -q "does not exist"; then
|
||||
fail "hooks hard-errored on a path resolved against the consumer repo (E100) — the bug this test guards against"
|
||||
echo "$OUT_BAD" | sed 's/^/ /'
|
||||
elif echo "$OUT_BAD" | grep -q "Skipped"; then
|
||||
fail "a hook matched no files, so it proved nothing"
|
||||
echo "$OUT_BAD" | sed 's/^/ /'
|
||||
elif [[ "$(echo "$OUT_BAD" | grep -c "VagueWording")" -ge 2 ]]; then
|
||||
pass "both hooks flatten and flag the folded description in a consumer repo"
|
||||
else
|
||||
fail "hooks did not flag both fixtures"
|
||||
echo "$OUT_BAD" | sed 's/^/ /'
|
||||
fi
|
||||
|
||||
# --- 2. Clean files pass — the hooks gate, they don't just always fail ---
|
||||
echo ""
|
||||
echo "--- both Vale hooks pass clean files in an external consumer repo ---"
|
||||
write_fixtures "of the packaged hook contract"
|
||||
set +e
|
||||
(cd "$CONSUMER" && pre-commit run --all-files > "$WORK/clean.log" 2>&1)
|
||||
RC_CLEAN=$?
|
||||
set -e
|
||||
if [[ $RC_CLEAN -eq 0 ]]; then
|
||||
pass "both hooks exit 0 on clean files"
|
||||
else
|
||||
fail "hooks failed on clean files (rc=$RC_CLEAN)"
|
||||
sed 's/^/ /' "$WORK/clean.log"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Results: $PASS passed, $FAIL failed"
|
||||
[[ $FAIL -eq 0 ]]
|
||||
Reference in New Issue
Block a user