fix(lint): restore release-gate coverage of bundled Vale assets
The gate derived release-relevant paths from the dirname of each entry's --config target. Dropping --config from .pre-commit-hooks.yaml left that loop dead, silently removing both assets/vale/ trees from coverage — a Vale rule change could land on main without demanding a release tag, leaving consumers pinned to an old rev: with stale rules. Coverage now derives from tokens[0] instead: double-dirname for the .. normalization, guarded on the tree existing and on the bundle root not resolving to "." so skill-size-check.sh cannot invent a bogus path. The --config branch is removed rather than kept as dead code. Since pre-commit rewrites only entry[0], no argument in any entry can ever name a file this repo ships, so that shape is broken by design. Known gap: deleting a hook's entire assets/ tree is not flagged, as the candidate path stops existing. Deletions within a surviving tree are. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MCQ648fLSFXPHGZdQ8gn58
This commit is contained in:
@@ -9,32 +9,45 @@ FAIL=0
|
||||
pass() { echo " PASS: $1"; PASS=$((PASS + 1)); }
|
||||
fail() { echo " FAIL: $1"; FAIL=$((FAIL + 1)); }
|
||||
|
||||
# Helper: write a minimal .pre-commit-hooks.yaml exposing one script entry and
|
||||
# one --config-bearing entry, so RELEASE_PATHS (derived from the manifest, not
|
||||
# hand-maintained) has both shapes to parse.
|
||||
# Both entry shapes the real .pre-commit-hooks.yaml ships: a bare script with no
|
||||
# bundled data, and a bare script whose sibling assets/ tree it self-locates at
|
||||
# runtime. Neither carries arguments — pre-commit only rewrites entry[0] to the
|
||||
# hook-repo clone path, so an argument path would resolve against the consuming
|
||||
# repo. RELEASE_PATHS is derived from the manifest rather than hand-maintained,
|
||||
# so it has to cope with both.
|
||||
HOOK_DIR="plugins/demo/skills/demo-audit"
|
||||
|
||||
write_manifest() {
|
||||
local dir="$1"
|
||||
mkdir -p "$dir/vale"
|
||||
cat > "$dir/.pre-commit-hooks.yaml" <<'EOF'
|
||||
cat > "$dir/.pre-commit-hooks.yaml" <<EOF
|
||||
- id: fake-size-check
|
||||
entry: scripts/skill-size-check.sh
|
||||
language: script
|
||||
- id: fake-vale-check
|
||||
entry: scripts/vale-wrap.sh --config vale/.vale.ini
|
||||
entry: $HOOK_DIR/scripts/vale-wrap.sh
|
||||
language: script
|
||||
EOF
|
||||
}
|
||||
|
||||
# Helper: a fixture repo with a manifest and its two referenced release-relevant
|
||||
# paths, committed and tagged v1.0.0.
|
||||
# Helper: writes the files both manifest entries expose — the two hook scripts
|
||||
# plus the bundled Vale config and style rule the second one self-locates.
|
||||
write_release_paths() {
|
||||
local dir="$1"
|
||||
mkdir -p "$dir/scripts" "$dir/$HOOK_DIR/scripts" "$dir/$HOOK_DIR/assets/vale/styles/Kyberforge"
|
||||
echo "v1" > "$dir/scripts/skill-size-check.sh"
|
||||
echo "v1" > "$dir/$HOOK_DIR/scripts/vale-wrap.sh"
|
||||
echo "cfg" > "$dir/$HOOK_DIR/assets/vale/.vale.ini"
|
||||
echo "rule: v1" > "$dir/$HOOK_DIR/assets/vale/styles/Kyberforge/DemoRule.yml"
|
||||
}
|
||||
|
||||
# Helper: a fixture repo with a manifest and every release-relevant path it
|
||||
# exposes, committed and tagged v1.0.0.
|
||||
make_tagged_fixture() {
|
||||
local dir
|
||||
dir="$(mktemp -d)"
|
||||
(cd "$dir" && git init -q && git config user.email t@t.t && git config user.name t)
|
||||
write_manifest "$dir"
|
||||
mkdir -p "$dir/scripts"
|
||||
echo "v1" > "$dir/scripts/skill-size-check.sh"
|
||||
echo "cfg" > "$dir/vale/.vale.ini"
|
||||
write_release_paths "$dir"
|
||||
(cd "$dir" && git add -A && git commit -q -m "initial" && git tag v1.0.0)
|
||||
echo "$dir"
|
||||
}
|
||||
@@ -65,9 +78,7 @@ echo "--- exits 1 when targeting main and no tag exists ---"
|
||||
FIXTURE2="$(mktemp -d)"; track "$FIXTURE2"
|
||||
(cd "$FIXTURE2" && git init -q && git config user.email t@t.t && git config user.name t)
|
||||
write_manifest "$FIXTURE2"
|
||||
mkdir -p "$FIXTURE2/scripts"
|
||||
echo "v1" > "$FIXTURE2/scripts/skill-size-check.sh"
|
||||
echo "cfg" > "$FIXTURE2/vale/.vale.ini"
|
||||
write_release_paths "$FIXTURE2"
|
||||
(cd "$FIXTURE2" && git add -A && git commit -q -m "initial")
|
||||
if run_check "$FIXTURE2" "refs/heads/main" > /dev/null; then
|
||||
fail "exited 0 when targeting main with no tag — expected exit 1"
|
||||
@@ -116,10 +127,10 @@ fi
|
||||
echo ""
|
||||
echo "--- exits 1 when a release-relevant path was deleted since the tag, not just modified ---"
|
||||
FIXTURE6="$(make_tagged_fixture)"; track "$FIXTURE6"
|
||||
rm -rf "$FIXTURE6/vale"
|
||||
(cd "$FIXTURE6" && git add -A && git commit -q -m "delete the vale config dir")
|
||||
rm -f "$FIXTURE6/$HOOK_DIR/assets/vale/.vale.ini"
|
||||
(cd "$FIXTURE6" && git add -A && git commit -q -m "delete the bundled vale config")
|
||||
OUT6=$(run_check "$FIXTURE6" "refs/heads/main" || true)
|
||||
if echo "$OUT6" | grep -q "vale/.vale.ini"; then
|
||||
if echo "$OUT6" | grep -q "assets/vale/.vale.ini"; then
|
||||
pass "flags a deleted release-relevant path instead of silently dropping it from the diff"
|
||||
else
|
||||
fail "did not flag deletion of a release-relevant path since the tag"
|
||||
@@ -166,6 +177,40 @@ else
|
||||
fail "flagged a file that no .pre-commit-hooks.yaml entry actually exposes"
|
||||
fi
|
||||
|
||||
# --- 10. A change confined to a hook's bundled styles/ tree is release-relevant ---
|
||||
# The manifest entry names only the wrapper script; the Vale rules it enforces
|
||||
# live in the sibling assets/ tree it self-locates at runtime. If that tree is
|
||||
# not covered, editing a rule and landing it on main demands no new tag, and a
|
||||
# consumer pinned to the old rev keeps the stale rules forever.
|
||||
echo ""
|
||||
echo "--- exits 1 when only a bundled Vale style rule changed since the tag ---"
|
||||
FIXTURE10="$(make_tagged_fixture)"; track "$FIXTURE10"
|
||||
echo "rule: v2" > "$FIXTURE10/$HOOK_DIR/assets/vale/styles/Kyberforge/DemoRule.yml"
|
||||
(cd "$FIXTURE10" && git add -A && git commit -q -m "tighten a vale rule")
|
||||
OUT10=$(run_check "$FIXTURE10" "refs/heads/main" || true)
|
||||
if echo "$OUT10" | grep -q "assets/vale/styles/Kyberforge/DemoRule.yml"; then
|
||||
pass "flags a change confined to a hook's bundled assets/vale/styles/ tree"
|
||||
else
|
||||
fail "a bundled Vale style rule changed since the tag without demanding a release"
|
||||
fi
|
||||
|
||||
# --- 11. The assets/ derivation must not invent a path for a bundle-less hook ---
|
||||
# scripts/skill-size-check.sh has no sibling assets/ tree, so its derived
|
||||
# candidate normalises to a bare top-level assets/ — a directory this repo does
|
||||
# not ship. Adding it unconditionally would make any unrelated repo-root
|
||||
# assets/ file falsely demand a release.
|
||||
echo ""
|
||||
echo "--- exits 0 when a top-level assets/ file changed but no hook bundles one ---"
|
||||
FIXTURE11="$(make_tagged_fixture)"; track "$FIXTURE11"
|
||||
mkdir -p "$FIXTURE11/assets"
|
||||
echo "unrelated" > "$FIXTURE11/assets/logo.txt"
|
||||
(cd "$FIXTURE11" && git add -A && git commit -q -m "add an unrelated top-level assets file")
|
||||
if run_check "$FIXTURE11" "refs/heads/main" > /dev/null; then
|
||||
pass "exits 0 for a top-level assets/ file that no manifest entry bundles"
|
||||
else
|
||||
fail "invented a bogus assets/ path for a hook script with no bundled tree"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Results: $PASS passed, $FAIL failed"
|
||||
[[ $FAIL -eq 0 ]]
|
||||
|
||||
Reference in New Issue
Block a user