Align reviewer runtime and Telegram notifications

This commit is contained in:
Stefano Fiorini
2026-03-24 11:45:58 -05:00
parent 4d37674626
commit 63a048a26c
17 changed files with 1756 additions and 200 deletions

View File

@@ -34,6 +34,9 @@ check_skill_file() {
assert_contains "$file" '$(cat /tmp/'
assert_contains "$file" "--strict-mcp-config"
assert_contains "$file" "--setting-sources user"
assert_contains "$file" "### P0"
assert_contains "$file" "In progress N"
assert_contains "$file" "notify-telegram.sh"
assert_not_contains "$file" "--allowedTools Read"
}

82
skills/reviewer-runtime/tests/smoke-test.sh Normal file → Executable file
View File

@@ -66,6 +66,28 @@ run_helper() {
return "$exit_code"
}
run_helper_allowing_success_file() {
local command_file=$1
local stdout_file=$2
local stderr_file=$3
local status_file=$4
local success_file=$5
shift 5
set +e
"$HELPER_PATH" \
--command-file "$command_file" \
--stdout-file "$stdout_file" \
--stderr-file "$stderr_file" \
--status-file "$status_file" \
--success-file "$success_file" \
"$@"
local exit_code=$?
set -e
return "$exit_code"
}
test_delayed_success() {
local dir=$1
local command_file=$dir/delayed-success.sh
@@ -120,6 +142,36 @@ printf "completed after soft timeout\n"
assert_file_contains "$status_file" "state=completed"
}
test_in_progress_heartbeats() {
local dir=$1
local command_file=$dir/in-progress-heartbeats.sh
local stdout_file=$dir/in-progress-heartbeats.stdout
local stderr_file=$dir/in-progress-heartbeats.stderr
local status_file=$dir/in-progress-heartbeats.status
make_command "$command_file" '
sleep 3
printf "finished with heartbeat coverage\n"
'
if run_helper "$command_file" "$stdout_file" "$stderr_file" "$status_file" \
--poll-seconds 1 \
--heartbeat-seconds 1 \
--soft-timeout-seconds 5 \
--stall-warning-seconds 4 \
--hard-timeout-seconds 10; then
local exit_code=0
else
local exit_code=$?
fi
assert_exit_code "$exit_code" 0
assert_file_contains "$stdout_file" "finished with heartbeat coverage"
assert_file_contains "$status_file" "state=in-progress"
assert_file_contains "$status_file" "In progress 1"
assert_file_contains "$status_file" "In progress 2"
}
test_nonzero_failure() {
local dir=$1
local command_file=$dir/nonzero-failure.sh
@@ -173,6 +225,34 @@ exit 0
assert_file_contains "$status_file" "state=completed-empty-output"
}
test_success_file_allows_empty_stdout() {
local dir=$1
local command_file=$dir/success-file.sh
local stdout_file=$dir/success-file.stdout
local stderr_file=$dir/success-file.stderr
local status_file=$dir/success-file.status
local success_file=$dir/review-output.md
make_command "$command_file" "
printf 'review body from redirected file\\n' > \"$success_file\"
exit 0
"
if run_helper_allowing_success_file "$command_file" "$stdout_file" "$stderr_file" "$status_file" "$success_file" \
--poll-seconds 1 \
--soft-timeout-seconds 5 \
--stall-warning-seconds 3 \
--hard-timeout-seconds 10; then
local exit_code=0
else
local exit_code=$?
fi
assert_exit_code "$exit_code" 0
assert_file_contains "$success_file" "review body from redirected file"
assert_file_contains "$status_file" "state=completed"
}
test_signal_cleanup() {
local dir=$1
local command_file=$dir/signal-child.sh
@@ -252,8 +332,10 @@ main() {
test_delayed_success "$tmp_dir"
test_soft_timeout_continues "$tmp_dir"
test_in_progress_heartbeats "$tmp_dir"
test_nonzero_failure "$tmp_dir"
test_empty_output_is_terminal "$tmp_dir"
test_success_file_allows_empty_stdout "$tmp_dir"
test_signal_cleanup "$tmp_dir"
test_hard_timeout_escalation "$tmp_dir"

View File

@@ -0,0 +1,158 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
HELPER_PATH=$(cd "$SCRIPT_DIR/.." && pwd)/notify-telegram.sh
fail() {
echo "FAIL: $*" >&2
exit 1
}
assert_equals() {
local actual=$1
local expected=$2
if [[ "$actual" != "$expected" ]]; then
fail "expected '$expected', got '$actual'"
fi
}
assert_file_contains() {
local file=$1
local pattern=$2
if ! grep -qF -- "$pattern" "$file"; then
echo "--- $file ---" >&2
sed -n '1,200p' "$file" >&2 || true
fail "expected '$pattern' in $file"
fi
}
capture_curl() {
local bin_dir=$1
local curl_args_file=$2
mkdir -p "$bin_dir"
cat >"$bin_dir/curl" <<EOF
#!/usr/bin/env bash
printf '%s\n' "\$@" >"$curl_args_file"
printf '{"ok":true}\n'
EOF
chmod +x "$bin_dir/curl"
}
read_curl_value() {
local file=$1
local key=$2
awk -v prefix="${key}=" 'index($0, prefix) == 1 { print substr($0, length(prefix) + 1); exit }' "$file"
}
test_missing_credentials() {
local tmp_dir=$1
local output_file=$tmp_dir/missing-credentials.out
set +e
env -u TELEGRAM_BOT_TOKEN -u TELEGRAM_CHAT_ID \
"$HELPER_PATH" --message "hello" >"$output_file" 2>&1
local exit_code=$?
set -e
[[ "$exit_code" -eq 2 ]] || fail "expected exit code 2 for missing credentials, got $exit_code"
assert_file_contains "$output_file" "bot token is required"
}
test_rejects_message_and_message_file_together() {
local tmp_dir=$1
local message_file=$tmp_dir/message.txt
local output_file=$tmp_dir/message-and-file.out
printf 'hello from file\n' >"$message_file"
set +e
TELEGRAM_BOT_TOKEN=test-token \
TELEGRAM_CHAT_ID=123456 \
"$HELPER_PATH" --message "hello" --message-file "$message_file" >"$output_file" 2>&1
local exit_code=$?
set -e
[[ "$exit_code" -eq 2 ]] || fail "expected exit code 2 for mutually exclusive arguments, got $exit_code"
assert_file_contains "$output_file" "use either --message or --message-file, not both"
}
test_successful_request() {
local tmp_dir=$1
local bin_dir=$tmp_dir/bin
local curl_args_file=$tmp_dir/curl-args.txt
capture_curl "$bin_dir" "$curl_args_file"
PATH="$bin_dir:$PATH" \
TELEGRAM_BOT_TOKEN=test-token \
TELEGRAM_CHAT_ID=123456 \
"$HELPER_PATH" --message "Plan completed"
assert_file_contains "$curl_args_file" "https://api.telegram.org/bottest-token/sendMessage"
assert_file_contains "$curl_args_file" "chat_id=123456"
assert_file_contains "$curl_args_file" "text=Plan completed"
assert_file_contains "$curl_args_file" "disable_web_page_preview=true"
assert_file_contains "$curl_args_file" "parse_mode=HTML"
}
test_message_file_and_custom_api_base() {
local tmp_dir=$1
local bin_dir=$tmp_dir/bin-message-file
local curl_args_file=$tmp_dir/curl-message-file.txt
local message_file=$tmp_dir/telegram-message.txt
capture_curl "$bin_dir" "$curl_args_file"
printf 'Plan completed from file\n' >"$message_file"
PATH="$bin_dir:$PATH" \
TELEGRAM_BOT_TOKEN=test-token \
TELEGRAM_CHAT_ID=654321 \
"$HELPER_PATH" \
--message-file "$message_file" \
--api-base-url "https://telegram.example.test/custom"
assert_file_contains "$curl_args_file" "https://telegram.example.test/custom/bottest-token/sendMessage"
assert_file_contains "$curl_args_file" "chat_id=654321"
assert_file_contains "$curl_args_file" "text=Plan completed from file"
}
test_truncates_long_message() {
local tmp_dir=$1
local bin_dir=$tmp_dir/bin-truncate
local curl_args_file=$tmp_dir/curl-truncate.txt
local long_message_file=$tmp_dir/long-message.txt
local truncated_message
capture_curl "$bin_dir" "$curl_args_file"
python3 - <<'PY' >"$long_message_file"
print("A" * 5000, end="")
PY
PATH="$bin_dir:$PATH" \
TELEGRAM_BOT_TOKEN=test-token \
TELEGRAM_CHAT_ID=123456 \
"$HELPER_PATH" --message-file "$long_message_file"
truncated_message=$(read_curl_value "$curl_args_file" "text")
assert_equals "${#truncated_message}" "4096"
}
main() {
[[ -x "$HELPER_PATH" ]] || fail "helper is not executable: $HELPER_PATH"
local tmp_dir
tmp_dir=$(mktemp -d)
trap "rm -rf '$tmp_dir'" EXIT
test_missing_credentials "$tmp_dir"
test_rejects_message_and_message_file_together "$tmp_dir"
test_successful_request "$tmp_dir"
test_message_file_and_custom_api_base "$tmp_dir"
test_truncates_long_message "$tmp_dir"
echo "PASS: telegram notifier tests"
}
main "$@"