193 lines
5.4 KiB
Bash
Executable File
193 lines
5.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# Docker clone test — simulates fresh user: setup.sh → verify hooks → run direct tests
|
|
# Run from inside the container with /repo bind-mounted read-only.
|
|
#
|
|
set -uo pipefail
|
|
|
|
echo "========================================="
|
|
echo " AIPass Fresh-Clone Test"
|
|
echo "========================================="
|
|
echo ""
|
|
|
|
# --- Phase 1: Copy repo (simulates git clone) ---
|
|
echo "--- Phase 1: Simulating git clone ---"
|
|
rm -rf ~/workspace/AIPass
|
|
cp -r /repo ~/workspace/AIPass
|
|
cd ~/workspace/AIPass
|
|
|
|
echo " Repo copied to ~/workspace/AIPass"
|
|
echo " Python: $(python3 --version)"
|
|
echo " Git: $(git --version)"
|
|
echo ""
|
|
|
|
# --- Phase 2: Run setup.sh ---
|
|
echo "--- Phase 2: Running setup.sh ---"
|
|
bash setup.sh 2>&1 | tail -30 || echo " WARNING: setup.sh exited non-zero"
|
|
echo ""
|
|
|
|
# --- Phase 3: Inspect provider settings ---
|
|
echo "--- Phase 3: Inspecting ~/.claude/settings.json ---"
|
|
SETTINGS="$HOME/.claude/settings.json"
|
|
if [ ! -f "$SETTINGS" ]; then
|
|
echo " FAIL: $SETTINGS does not exist!"
|
|
exit 1
|
|
fi
|
|
|
|
echo " File exists: $SETTINGS"
|
|
echo " Size: $(wc -c < "$SETTINGS") bytes"
|
|
echo ""
|
|
|
|
# Check hooks are wired
|
|
echo " Hook events wired:"
|
|
jq -r '.hooks | keys[]' "$SETTINGS" 2>/dev/null | while read -r event; do
|
|
count=$(jq -r ".hooks.\"$event\" | length" "$SETTINGS")
|
|
echo " $event: $count matcher(s)"
|
|
done
|
|
echo ""
|
|
|
|
# Check env vars
|
|
echo " Env vars:"
|
|
jq -r '.env // {} | to_entries[] | " \(.key) = \(.value)"' "$SETTINGS" 2>/dev/null
|
|
echo ""
|
|
|
|
# Check deny rules
|
|
deny_count=$(jq -r '.permissions.deny | length' "$SETTINGS" 2>/dev/null || echo "0")
|
|
echo " Deny rules: $deny_count"
|
|
|
|
# Check ask rules
|
|
ask_count=$(jq -r '.permissions.ask | length' "$SETTINGS" 2>/dev/null || echo "0")
|
|
echo " Ask rules: $ask_count"
|
|
echo ""
|
|
|
|
# --- Phase 4: Verify specific hooks exist ---
|
|
echo "--- Phase 4: Hook script verification ---"
|
|
HOOKS_DIR="$HOME/workspace/AIPass/.claude/hooks"
|
|
expected_hooks=(
|
|
"global_prompt_loader.py"
|
|
"branch_prompt_loader.py"
|
|
"identity_injector.py"
|
|
"email_notification.py"
|
|
"tool_use_sound.py"
|
|
"pre_edit_gate.py"
|
|
"git_gate.py"
|
|
"auto_fix_diagnostics.py"
|
|
"subagent_stop_gate.py"
|
|
"pre_compact.py"
|
|
"stop_sound.py"
|
|
"notification_sound.py"
|
|
"hook_log.py"
|
|
"hook_test.py"
|
|
"hook_report.py"
|
|
)
|
|
|
|
pass=0
|
|
fail=0
|
|
for hook in "${expected_hooks[@]}"; do
|
|
if [ -f "$HOOKS_DIR/$hook" ]; then
|
|
echo " OK $hook"
|
|
((pass++))
|
|
else
|
|
echo " FAIL $hook — NOT FOUND"
|
|
((fail++))
|
|
fi
|
|
done
|
|
echo " Scripts: $pass found, $fail missing"
|
|
echo ""
|
|
|
|
# --- Phase 5: Run direct hook tests ---
|
|
echo "--- Phase 5: Running hook_test.py --direct ---"
|
|
export AIPASS_HOME="$HOME/workspace/AIPass"
|
|
|
|
# Activate the venv setup.sh created so python3 finds the right env
|
|
if [ -f "$AIPASS_HOME/.venv/bin/activate" ]; then
|
|
source "$AIPASS_HOME/.venv/bin/activate"
|
|
fi
|
|
|
|
python3 "$HOOKS_DIR/hook_test.py" --direct --verbose 2>&1 || true
|
|
echo ""
|
|
|
|
# --- Phase 6: Check settings.json matches Patrick's machine pattern ---
|
|
echo "--- Phase 6: Settings validation ---"
|
|
checks_passed=0
|
|
checks_total=0
|
|
|
|
# AIPASS_HOME in env
|
|
((checks_total++))
|
|
if jq -e '.env.AIPASS_HOME' "$SETTINGS" > /dev/null 2>&1; then
|
|
echo " OK AIPASS_HOME in env"
|
|
((checks_passed++))
|
|
else
|
|
echo " FAIL AIPASS_HOME not in env"
|
|
fi
|
|
|
|
# CLAUDE_CODE_DISABLE_AUTO_MEMORY
|
|
((checks_total++))
|
|
if jq -e '.env.CLAUDE_CODE_DISABLE_AUTO_MEMORY' "$SETTINGS" > /dev/null 2>&1; then
|
|
echo " OK CLAUDE_CODE_DISABLE_AUTO_MEMORY in env"
|
|
((checks_passed++))
|
|
else
|
|
echo " FAIL CLAUDE_CODE_DISABLE_AUTO_MEMORY not in env"
|
|
fi
|
|
|
|
# git deny rules present
|
|
((checks_total++))
|
|
if jq -e '.permissions.deny[] | select(contains("git reset"))' "$SETTINGS" > /dev/null 2>&1; then
|
|
echo " OK git deny rules present"
|
|
((checks_passed++))
|
|
else
|
|
echo " FAIL git deny rules missing"
|
|
fi
|
|
|
|
# secrets deny rules present
|
|
((checks_total++))
|
|
if jq -e '.permissions.deny[] | select(contains(".secrets"))' "$SETTINGS" > /dev/null 2>&1; then
|
|
echo " OK secrets deny rules present"
|
|
((checks_passed++))
|
|
else
|
|
echo " FAIL secrets deny rules missing"
|
|
fi
|
|
|
|
# ask rules for ~/.claude
|
|
((checks_total++))
|
|
if jq -e '.permissions.ask[] | select(contains(".claude"))' "$SETTINGS" > /dev/null 2>&1; then
|
|
echo " OK ask rules for ~/.claude"
|
|
((checks_passed++))
|
|
else
|
|
echo " FAIL ask rules for ~/.claude missing"
|
|
fi
|
|
|
|
# UserPromptSubmit has 4 hooks
|
|
((checks_total++))
|
|
ups_count=$(jq -r '.hooks.UserPromptSubmit | length' "$SETTINGS" 2>/dev/null || echo "0")
|
|
if [ "$ups_count" -eq 4 ]; then
|
|
echo " OK UserPromptSubmit: 4 hooks"
|
|
((checks_passed++))
|
|
else
|
|
echo " FAIL UserPromptSubmit: expected 4, got $ups_count"
|
|
fi
|
|
|
|
# PreToolUse has 3 matchers
|
|
((checks_total++))
|
|
ptu_count=$(jq -r '.hooks.PreToolUse | length' "$SETTINGS" 2>/dev/null || echo "0")
|
|
if [ "$ptu_count" -eq 3 ]; then
|
|
echo " OK PreToolUse: 3 matchers"
|
|
((checks_passed++))
|
|
else
|
|
echo " FAIL PreToolUse: expected 3, got $ptu_count"
|
|
fi
|
|
|
|
# global_prompt_loader.py used (not cat)
|
|
((checks_total++))
|
|
if jq -r '.hooks.UserPromptSubmit[0].hooks[0].command' "$SETTINGS" 2>/dev/null | grep -q "global_prompt_loader.py"; then
|
|
echo " OK Uses global_prompt_loader.py (not cat)"
|
|
((checks_passed++))
|
|
else
|
|
echo " FAIL Still using cat instead of global_prompt_loader.py"
|
|
fi
|
|
|
|
echo ""
|
|
echo "========================================="
|
|
echo " Results: $checks_passed/$checks_total settings checks passed"
|
|
echo "========================================="
|