diff options
| author | Craig Jennings <c@cjennings.net> | 2026-07-23 20:48:44 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-07-23 20:48:44 -0500 |
| commit | c238afbd4150ef53737f16e7dd84a565d2838ecc (patch) | |
| tree | 588a25dc318cb854c57d8146639d400674baed18 /scripts/tests/install-lang-completeness.bats | |
| parent | 10ea44b6de3be1872f7f0bd4501ccf3878105bc4 (diff) | |
| download | rulesets-c238afbd4150ef53737f16e7dd84a565d2838ecc.tar.gz rulesets-c238afbd4150ef53737f16e7dd84a565d2838ecc.zip | |
feat(languages): ship the missing python and typescript hooks
The python and typescript bundles carried rules and a coverage script but no pre-commit hook, so any project installing one got no credential scan on commit. Both now ship all four components the README documents: the shared secret scan, a validate-on-edit hook, settings wiring, and a seed CLAUDE.md. Verified against a real repo: a commit carrying an AWS key is refused.
install-lang now warns when a bundle is missing a documented component. That's the half that keeps this from recurring. Whoever adds the sixth bundle will forget something too, and today the installer prints success either way.
Two things fell out of the build. node --check is unusable on TypeScript: it ignores --experimental-strip-types, so it rejects valid TS and accepts broken TS. The hook uses tsc filtered to syntactic diagnostics instead. And completing the bundles means every pair now collides on settings.json and pre-commit, so no two compose without FORCE=1. The earlier "bundles already compose" reading rested on these two being incomplete. Filed for a real decision; clock-panel is the project that wants it.
Also stamps :LAST_REVIEWED: at task creation, with a lint checker to catch misses. Writing a task is reviewing it, so leaving the stamp off pushed every fresh task to the top of the next review batch to be re-derived by someone with less context than its author had. Tonight's sweep sent the staleness count from 13 to 22 while the list got more accurate.
Diffstat (limited to 'scripts/tests/install-lang-completeness.bats')
| -rw-r--r-- | scripts/tests/install-lang-completeness.bats | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/scripts/tests/install-lang-completeness.bats b/scripts/tests/install-lang-completeness.bats new file mode 100644 index 0000000..42832dc --- /dev/null +++ b/scripts/tests/install-lang-completeness.bats @@ -0,0 +1,93 @@ +#!/usr/bin/env bats +# +# Tests for install-lang.sh's bundle-completeness warning. +# +# Background: the python and typescript bundles shipped for nearly two months +# with no githooks/pre-commit, so any project installing them got no +# credential scan on commit. install-lang guarded each component copy with a +# plain `[ -d ... ]`, so a missing component was indistinguishable from a +# complete install — it printed nothing and exited 0. +# +# The fix is not "never miss a component" (a person will), it's "say so when +# you do". These tests pin that: a complete bundle installs quietly, an +# incomplete one names exactly what's absent, and neither case fails the +# install — a warning must not become a new way to block work. + +REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../.." && pwd)" +INSTALL="$REPO_ROOT/scripts/install-lang.sh" + +setup() { + TEST_DIR="$(mktemp -d -t install-lang-bats.XXXXXX)" + PROJECT="$TEST_DIR/proj" + mkdir -p "$PROJECT" + git init -q "$PROJECT" +} + +teardown() { + rm -rf "$TEST_DIR" +} + +# ---- Normal: a complete bundle is quiet ------------------------------ + +@test "install-lang: a complete bundle warns about nothing" { + run env LANG_ARG=bash bash "$INSTALL" bash "$PROJECT" + [ "$status" -eq 0 ] + [[ "$output" != *"incomplete"* ]] +} + +@test "install-lang: python is now a complete bundle" { + run bash "$INSTALL" python "$PROJECT" + [ "$status" -eq 0 ] + [[ "$output" != *"incomplete"* ]] + [ -f "$PROJECT/githooks/pre-commit" ] + [ -f "$PROJECT/.claude/settings.json" ] + [ -f "$PROJECT/.claude/hooks/validate-python.sh" ] +} + +@test "install-lang: typescript is now a complete bundle" { + run bash "$INSTALL" typescript "$PROJECT" + [ "$status" -eq 0 ] + [[ "$output" != *"incomplete"* ]] + [ -f "$PROJECT/githooks/pre-commit" ] + [ -f "$PROJECT/.claude/settings.json" ] + [ -f "$PROJECT/.claude/hooks/validate-typescript.sh" ] +} + +@test "install-lang: the installed pre-commit is executable" { + run bash "$INSTALL" python "$PROJECT" + [ "$status" -eq 0 ] + [ -x "$PROJECT/githooks/pre-commit" ] +} + +# ---- Error: an incomplete bundle announces itself -------------------- + +@test "install-lang: a bundle missing githooks/ warns and names it" { + fake="$REPO_ROOT/languages/zz-test-partial" + mkdir -p "$fake/claude/rules" + printf '# rule\n' > "$fake/claude/rules/zz.md" + run bash "$INSTALL" zz-test-partial "$PROJECT" + rm -rf "$fake" + [ "$status" -eq 0 ] + [[ "$output" == *"incomplete"* ]] + [[ "$output" == *"githooks/pre-commit"* ]] +} + +@test "install-lang: the warning names every missing component, not just the first" { + fake="$REPO_ROOT/languages/zz-test-partial" + mkdir -p "$fake/claude/rules" + printf '# rule\n' > "$fake/claude/rules/zz.md" + run bash "$INSTALL" zz-test-partial "$PROJECT" + rm -rf "$fake" + [[ "$output" == *"githooks/pre-commit"* ]] + [[ "$output" == *"settings.json"* ]] +} + +@test "install-lang: an incomplete bundle still installs (warn, never block)" { + fake="$REPO_ROOT/languages/zz-test-partial" + mkdir -p "$fake/claude/rules" + printf '# rule\n' > "$fake/claude/rules/zz.md" + run bash "$INSTALL" zz-test-partial "$PROJECT" + rm -rf "$fake" + [ "$status" -eq 0 ] + [ -f "$PROJECT/.claude/rules/zz.md" ] +} |
