fix(tests): make runner worktree exclusions relative to the search root
Both runners excluded */.claude/worktrees/* by absolute path, which filtered out every test when the repo itself is a Claude worktree. Search from inside the root so only nested worktrees are skipped. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -45,11 +45,17 @@ fi
|
|||||||
# land at .claude/skills/<name>/tests/ and be discovered and run a second time,
|
# land at .claude/skills/<name>/tests/ and be discovered and run a second time,
|
||||||
# which is ADR-0024 consequence 2 arriving here. Keeping the exclusion now is
|
# which is ADR-0024 consequence 2 arriving here. Keeping the exclusion now is
|
||||||
# what stops that landing as a mystery double-run on the merge that enables it.
|
# what stops that landing as a mystery double-run on the merge that enables it.
|
||||||
|
#
|
||||||
|
# The walk runs from inside REPO_ROOT so the exclusions match paths RELATIVE to
|
||||||
|
# it, the same universe the `git ls-files` grep below sees. Matched against
|
||||||
|
# absolute paths, `*/.claude/worktrees/*` excluded every file whenever the
|
||||||
|
# checkout itself was a Claude worktree (<repo>/.claude/worktrees/<name>/), and
|
||||||
|
# the run failed with "N of N tracked .bats file(s) were not discovered".
|
||||||
TEST_FILES=()
|
TEST_FILES=()
|
||||||
while IFS= read -r f; do
|
while IFS= read -r f; do
|
||||||
TEST_FILES+=("$f")
|
TEST_FILES+=("$REPO_ROOT/${f#./}")
|
||||||
done < <(
|
done < <(
|
||||||
find "$REPO_ROOT" -name "*.bats" \
|
cd "$REPO_ROOT" && find . -name "*.bats" \
|
||||||
-not -path "*/tests/bats/*" \
|
-not -path "*/tests/bats/*" \
|
||||||
-not -path "*/test_helper/*" \
|
-not -path "*/test_helper/*" \
|
||||||
-not -path "*/.claude/worktrees/*" \
|
-not -path "*/.claude/worktrees/*" \
|
||||||
|
|||||||
@@ -151,11 +151,17 @@ run_bats
|
|||||||
# such file exists today -- the skill suites are all .bats, where run-bats.sh
|
# such file exists today -- the skill suites are all .bats, where run-bats.sh
|
||||||
# already hit this -- so the exclusion is symmetry with its sibling, kept here
|
# already hit this -- so the exclusion is symmetry with its sibling, kept here
|
||||||
# so the first shell suite added under a skill does not reintroduce it.
|
# so the first shell suite added under a skill does not reintroduce it.
|
||||||
|
#
|
||||||
|
# The walk runs from inside SEARCH_ROOT so the exclusions match paths RELATIVE to
|
||||||
|
# it. Matched against absolute paths, `*/.claude/worktrees/*` excluded every
|
||||||
|
# suite whenever the checkout itself was a Claude worktree
|
||||||
|
# (<repo>/.claude/worktrees/<name>/); relative, it still skips worktrees nested
|
||||||
|
# below the root. The `./` prefix is swapped back for SEARCH_ROOT afterwards.
|
||||||
SCRIPTS=()
|
SCRIPTS=()
|
||||||
while IFS= read -r script; do
|
while IFS= read -r script; do
|
||||||
SCRIPTS+=("$script")
|
SCRIPTS+=("$SEARCH_ROOT/${script#./}")
|
||||||
done < <(
|
done < <(
|
||||||
find "$SEARCH_ROOT" -name "test-*.sh" \
|
cd "$SEARCH_ROOT" && find . -name "test-*.sh" \
|
||||||
-not -path "*/.git/*" \
|
-not -path "*/.git/*" \
|
||||||
-not -path "*/.claude/worktrees/*" \
|
-not -path "*/.claude/worktrees/*" \
|
||||||
-not -path "*/apm_modules/*" \
|
-not -path "*/apm_modules/*" \
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ trap cleanup EXIT
|
|||||||
# invokes it as `$(make_fake_repo)`, and an append made in here would land in the
|
# invokes it as `$(make_fake_repo)`, and an append made in here would land in the
|
||||||
# command substitution's subshell and be lost. Registration is the caller's job.
|
# command substitution's subshell and be lost. Registration is the caller's job.
|
||||||
make_fake_repo() {
|
make_fake_repo() {
|
||||||
local dir
|
local dir="${1:-}"
|
||||||
dir="$(mktemp -d)"
|
[[ -n "$dir" ]] || dir="$(mktemp -d)"
|
||||||
mkdir -p "$dir/tests" "$dir/scripts/lib"
|
mkdir -p "$dir/tests" "$dir/scripts/lib"
|
||||||
cp "$REPO_ROOT/scripts/lib/batch-run.sh" "$dir/scripts/lib/batch-run.sh"
|
cp "$REPO_ROOT/scripts/lib/batch-run.sh" "$dir/scripts/lib/batch-run.sh"
|
||||||
cp "$RUN_BATS" "$dir/tests/run-bats.sh"
|
cp "$RUN_BATS" "$dir/tests/run-bats.sh"
|
||||||
@@ -410,6 +410,40 @@ else
|
|||||||
fail "the run failed but not with the zero-files message: $FAKE_OUT"
|
fail "the run failed but not with the zero-files message: $FAKE_OUT"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# --- 10. A repo root that itself sits under .claude/worktrees/ still runs. The
|
||||||
|
# worktree exclusion used to match the absolute path, so a Claude worktree --
|
||||||
|
# which lives at <repo>/.claude/worktrees/<name>/ -- excluded every file of its
|
||||||
|
# own and failed with "N of N tracked .bats file(s) were not discovered". The
|
||||||
|
# exclusion is now relative to the root, so a worktree nested BELOW the root is
|
||||||
|
# still skipped.
|
||||||
|
echo ""
|
||||||
|
echo "--- a root under .claude/worktrees/ discovers its own files and still skips nested worktrees ---"
|
||||||
|
WT_PARENT="$(mktemp -d)"
|
||||||
|
FIXTURES+=("$WT_PARENT")
|
||||||
|
DIR10="$WT_PARENT/repo/.claude/worktrees/agent-x"
|
||||||
|
make_fake_repo "$DIR10" >/dev/null
|
||||||
|
git -C "$DIR10" init -q
|
||||||
|
seed_bats_files "$DIR10"
|
||||||
|
mkdir -p "$DIR10/.claude/worktrees/nested/tests"
|
||||||
|
printf '@test "n" { false; }\n' > "$DIR10/.claude/worktrees/nested/tests/n.bats"
|
||||||
|
install_stub_bats "$DIR10" <<'EOF'
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
echo "1..1"
|
||||||
|
echo "ok 1 first"
|
||||||
|
exit 0
|
||||||
|
EOF
|
||||||
|
git -C "$DIR10" add tests/a.bats tests/b.bats
|
||||||
|
run_fake "$DIR10"
|
||||||
|
if [[ $FAKE_RC -ne 0 ]]; then
|
||||||
|
fail "a root under .claude/worktrees/ failed — its own files were excluded: $FAKE_OUT"
|
||||||
|
elif ! grep -q "^=== tests/a.bats ===$" <<< "$FAKE_OUT"; then
|
||||||
|
fail "a root under .claude/worktrees/ did not run its own tests/a.bats: $FAKE_OUT"
|
||||||
|
elif grep -q "nested/tests/n.bats" <<< "$FAKE_OUT"; then
|
||||||
|
fail "a worktree nested below the root was discovered and run: $FAKE_OUT"
|
||||||
|
else
|
||||||
|
pass "a root under .claude/worktrees/ runs its own files and skips nested worktrees"
|
||||||
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "Results: $PASS passed, $FAIL failed"
|
echo "Results: $PASS passed, $FAIL failed"
|
||||||
[[ $FAIL -eq 0 ]]
|
[[ $FAIL -eq 0 ]]
|
||||||
|
|||||||
@@ -45,8 +45,8 @@ trap cleanup EXIT
|
|||||||
# substitution's subshell and be lost. Registration is the caller's job. Same
|
# substitution's subshell and be lost. Registration is the caller's job. Same
|
||||||
# convention as tests/test-run-bats.sh.
|
# convention as tests/test-run-bats.sh.
|
||||||
make_fake_repo() {
|
make_fake_repo() {
|
||||||
local dir
|
local dir="${1:-}"
|
||||||
dir="$(mktemp -d)"
|
[[ -n "$dir" ]] || dir="$(mktemp -d)"
|
||||||
mkdir -p "$dir/tests" "$dir/scripts/lib" "$dir/cases"
|
mkdir -p "$dir/tests" "$dir/scripts/lib" "$dir/cases"
|
||||||
cp "$REPO_ROOT/scripts/lib/batch-run.sh" "$dir/scripts/lib/batch-run.sh"
|
cp "$REPO_ROOT/scripts/lib/batch-run.sh" "$dir/scripts/lib/batch-run.sh"
|
||||||
cp "$RUN_TESTS" "$dir/tests/run-tests.sh"
|
cp "$RUN_TESTS" "$dir/tests/run-tests.sh"
|
||||||
@@ -670,6 +670,39 @@ else
|
|||||||
pass "--strict and RUN_TESTS_STRICT=1 both dispatch children with RUN_TESTS_STRICT absent"
|
pass "--strict and RUN_TESTS_STRICT=1 both dispatch children with RUN_TESTS_STRICT absent"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# --- A search root that itself sits under .claude/worktrees/ still runs. The
|
||||||
|
# worktree exclusion used to match the absolute path, so every suite in a Claude
|
||||||
|
# worktree (<repo>/.claude/worktrees/<name>/) was filtered out. It is now
|
||||||
|
# relative to the search root, so a worktree nested BELOW the root is still
|
||||||
|
# skipped.
|
||||||
|
echo ""
|
||||||
|
echo "--- a root under .claude/worktrees/ discovers its own suites and still skips nested worktrees ---"
|
||||||
|
WT_PARENT="$(mktemp -d)"
|
||||||
|
FIXTURES+=("$WT_PARENT")
|
||||||
|
WT_DIR="$WT_PARENT/repo/.claude/worktrees/agent-x"
|
||||||
|
make_fake_repo "$WT_DIR" >/dev/null
|
||||||
|
install_healthy_bats_runner "$WT_DIR"
|
||||||
|
add_case "$WT_DIR" test-own.sh <<'EOF'
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
echo "own suite ran"
|
||||||
|
EOF
|
||||||
|
mkdir -p "$WT_DIR/cases/.claude/worktrees/nested"
|
||||||
|
cat > "$WT_DIR/cases/.claude/worktrees/nested/test-nested.sh" <<'EOF'
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
echo "nested suite ran"
|
||||||
|
exit 1
|
||||||
|
EOF
|
||||||
|
run_fake "$WT_DIR"
|
||||||
|
if [[ $FAKE_RC -ne 0 ]]; then
|
||||||
|
fail "a root under .claude/worktrees/ failed: $FAKE_OUT"
|
||||||
|
elif ! grep -q "own suite ran" <<< "$FAKE_OUT"; then
|
||||||
|
fail "a root under .claude/worktrees/ did not run its own suite: $FAKE_OUT"
|
||||||
|
elif grep -q "nested suite ran" <<< "$FAKE_OUT"; then
|
||||||
|
fail "a worktree nested below the root was discovered and run: $FAKE_OUT"
|
||||||
|
else
|
||||||
|
pass "a root under .claude/worktrees/ runs its own suites and skips nested worktrees"
|
||||||
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "Results: $PASS passed, $FAIL failed"
|
echo "Results: $PASS passed, $FAIL failed"
|
||||||
[[ $FAIL -eq 0 ]]
|
[[ $FAIL -eq 0 ]]
|
||||||
|
|||||||
Reference in New Issue
Block a user