mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-10-18 10:40:12 +00:00
82 lines
2.9 KiB
Bash
Executable File
82 lines
2.9 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Runs Claude Code to repeat the smoke test with the ui helper, as claude-test.md describes, and passes when
|
|
# its final message ends with "CLAUDE-TEST: PASS".
|
|
# Usage: scripts/ci/desktop-linux/claude-test.sh <output dir> <transcript .jsonl>
|
|
# Expects the app started (smoke-test.sh ... start) with UI_OUT under <output dir>, claude and ui on PATH,
|
|
# CLAUDE_MODEL and CLAUDE_CODE_OAUTH_TOKEN. Claude works in <output dir>: the screenshots, its report.md and the
|
|
# prompt it was given end up there. The transcript, Claude Code's stderr (<transcript>.stderr) and the guard hook's
|
|
# log (<transcript>.guard.log) are kept outside it, where Claude can't write. If any of them holds the token, all are
|
|
# deleted and the run fails.
|
|
|
|
set -euo pipefail
|
|
|
|
: "${CLAUDE_CODE_OAUTH_TOKEN:?CLAUDE_CODE_OAUTH_TOKEN must be set}"
|
|
here=$(cd "$(dirname "$0")" && pwd)
|
|
out=$(cd "$1" && pwd)
|
|
transcript=$2
|
|
stderr=$transcript.stderr
|
|
settings=$(mktemp)
|
|
export CLAUDE_GUARD_LOG=$transcript.guard.log
|
|
: > "$CLAUDE_GUARD_LOG"
|
|
|
|
{
|
|
cat "$here/claude-test.md"
|
|
echo
|
|
echo '```'
|
|
"$here/ui" || true
|
|
echo '```'
|
|
} > "$out/prompt.md"
|
|
|
|
cat > "$settings" << EOF
|
|
{"hooks": {"PreToolUse": [{"matcher": "Bash", "hooks": [{"type": "command", "command": "$here/claude-guard.py"}]}]}}
|
|
EOF
|
|
|
|
claude --version
|
|
cd "$out"
|
|
status=0
|
|
claude -p "$(cat prompt.md)" \
|
|
--model "$CLAUDE_MODEL" \
|
|
--max-turns 60 \
|
|
--max-budget-usd 3 \
|
|
--output-format stream-json \
|
|
--verbose \
|
|
--tools Bash,Read,Write \
|
|
--permission-mode dontAsk \
|
|
--allowedTools "Bash(ui *)" "Read(/$out/**)" "Edit(/$out/**)" \
|
|
--disallowedTools "mcp__*" \
|
|
--strict-mcp-config \
|
|
--disable-slash-commands \
|
|
--no-session-persistence \
|
|
--settings "$settings" \
|
|
< /dev/null > "$transcript" 2> "$stderr" || status=$?
|
|
|
|
# A second safeguard to the file tools' limits: what the session wrote is printed and uploaded only when it is known
|
|
# not to hold the token. grep reads the token from a pipe, so it is in no process's arguments.
|
|
leak=0
|
|
printf '%s\n' "$CLAUDE_CODE_OAUTH_TOKEN" | grep -rqF -f - -- "$out" "$transcript" "$stderr" "$CLAUDE_GUARD_LOG" || leak=$?
|
|
if [ "$leak" -ne 1 ]; then
|
|
rm -rf -- "$out" "$transcript" "$stderr" "$CLAUDE_GUARD_LOG"
|
|
echo "error: the token is in the Claude session's output, or checking for it failed (grep exited $leak); the output, transcript, stderr and guard log are deleted"
|
|
exit 1
|
|
fi
|
|
|
|
echo "::group::claude stderr"
|
|
cat "$stderr"
|
|
echo "::endgroup::"
|
|
echo "::group::report.md"
|
|
cat report.md 2> /dev/null || echo "no report.md"
|
|
echo "::endgroup::"
|
|
echo "::group::guard hook decisions"
|
|
cat "$CLAUDE_GUARD_LOG"
|
|
echo "::endgroup::"
|
|
result=$(jq -r 'select(.type == "result") | .result // empty' "$transcript" 2> /dev/null | tail -n 20 || true)
|
|
echo "final message, last lines:"
|
|
echo "$result"
|
|
if [ "$status" -ne 0 ]; then
|
|
echo "error: claude exited with $status"
|
|
exit 1
|
|
fi
|
|
last=$(grep -v '^[[:space:]]*$' <<< "$result" | tail -n 1 || true)
|
|
grep -qxE '[*`]*CLAUDE-TEST: PASS[*`]*' <<< "$last"
|