From 25e9e623897e010848858de67583f141d5de003b Mon Sep 17 00:00:00 2001 From: toki Date: Sat, 30 May 2026 20:51:05 +0900 Subject: [PATCH] update run_matrix.sh script --- .../scripts/run_matrix.sh | 215 +++++++++++++++--- 1 file changed, 185 insertions(+), 30 deletions(-) diff --git a/agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_matrix.sh b/agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_matrix.sh index 24746f4..bce70a7 100755 --- a/agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_matrix.sh +++ b/agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_matrix.sh @@ -27,6 +27,13 @@ repo_root="$(cd "$script_dir/../../../../.." && pwd)" log_dir="$(mktemp -d "${TMPDIR:-/tmp}/proto-socket-matrix.XXXXXX")" run_started_at="$(date -u +%Y-%m-%dT%H:%M:%SZ)" run_record_stamp="$(date -u +%Y%m%d-%H%M%S)" +remote_web_host="${PROTO_SOCKET_DART_WEB_REMOTE:-toki@toki-labs.com}" +remote_web_root_expr="${PROTO_SOCKET_DART_WEB_REMOTE_ROOT:-~/works}" +remote_web_repo_name="${PROTO_SOCKET_DART_WEB_REMOTE_REPO:-proto-socket-dart-web}" +remote_web_repo_url="${PROTO_SOCKET_DART_WEB_REMOTE_URL:-$(git -C "$repo_root" config --get remote.origin.url 2>/dev/null || true)}" +remote_web_ref="${PROTO_SOCKET_DART_WEB_REF:-$(git -C "$repo_root" rev-parse --abbrev-ref HEAD 2>/dev/null || echo master)}" +remote_web_execution="local" +remote_web_prepare_summary="" case "$mode" in all) record_profile="proto-socket-full-matrix" ;; @@ -119,6 +126,15 @@ count_lines() { echo "${count:-0}" } +single_quote() { + printf "'%s'" "$(printf '%s' "$1" | sed "s/'/'\\\\''/g")" +} + +remote_exec() { + local cmd="$1" + ssh -o BatchMode=yes -o ConnectTimeout=10 "$remote_web_host" "zsh -lc $(single_quote "$cmd")" +} + run_logged() { local name="$1" local dir="$2" @@ -139,6 +155,87 @@ chrome_available() { command -v google-chrome >/dev/null 2>&1 } +remote_chrome_export_command() { + cat <<'REMOTE_CHROME' +if [ -x "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" ]; then + export CHROME_EXECUTABLE="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" +elif command -v google-chrome >/dev/null 2>&1; then + export CHROME_EXECUTABLE="$(command -v google-chrome)" +elif command -v chromium >/dev/null 2>&1; then + export CHROME_EXECUTABLE="$(command -v chromium)" +elif command -v chromium-browser >/dev/null 2>&1; then + export CHROME_EXECUTABLE="$(command -v chromium-browser)" +else + echo "Chrome executable not found on remote." >&2 + exit 90 +fi +REMOTE_CHROME +} + +prepare_remote_web_repo() { + local repo_name_q repo_url_q repo_ref_q chrome_cmd + + if [ -z "$remote_web_repo_url" ]; then + echo "remote repository URL is not configured" >&2 + return 1 + fi + + repo_name_q="$(single_quote "$remote_web_repo_name")" + repo_url_q="$(single_quote "$remote_web_repo_url")" + repo_ref_q="$(single_quote "$remote_web_ref")" + chrome_cmd="$(remote_chrome_export_command)" + + remote_exec " +set -e +repo_parent=$remote_web_root_expr +repo_name=$repo_name_q +repo_url=$repo_url_q +repo_ref=$repo_ref_q +mkdir -p \"\$repo_parent\" +repo_dir=\"\$repo_parent/\$repo_name\" +if [ ! -d \"\$repo_dir/.git\" ]; then + git clone \"\$repo_url\" \"\$repo_dir\" +fi +cd \"\$repo_dir\" +git fetch origin --prune +git checkout \"\$repo_ref\" +git pull --ff-only origin \"\$repo_ref\" +(cd dart && dart pub get) +if [ -f typescript/package.json ]; then + (cd typescript && npm install) +fi +if [ -f python/pyproject.toml ]; then + (cd python && python3 -m pip install -e '.[dev]') +fi +$chrome_cmd +printf 'remote Dart.web repo: %s\n' \"\$repo_dir\" +printf 'remote Dart.web git ref: %s\n' \"\$(git rev-parse --short HEAD)\" +" +} + +run_remote_web_logged() { + local server="$1" + local dir="$2" + local cmd="$3" + local log_file="$4" + local rel_dir chrome_cmd rel_dir_q + + rel_dir="${dir#$repo_root/}" + rel_dir_q="$(single_quote "$rel_dir")" + chrome_cmd="$(remote_chrome_export_command)" + + printf 'RUN remote web %s->Dart.web: %s\n' "$server" "$cmd" >&2 + remote_exec " +set -e +repo_parent=$remote_web_root_expr +repo_name=$(single_quote "$remote_web_repo_name") +repo_dir=\"\$repo_parent/\$repo_name\" +$chrome_cmd +cd \"\$repo_dir\"/$rel_dir_q +$cmd +" >"$log_file" 2>&1 +} + run_unit_tests() { local lang cmd dir log_file status for lang in "${languages[@]}"; do @@ -194,18 +291,43 @@ run_cross_tests() { } run_web_tests() { - local item server dir cmd key log_file status pass_count fail_count + local item server dir cmd key log_file status pass_count fail_count remote_reason if ! chrome_available; then + if ! prepare_remote_web_repo >"$log_dir/remote_web_prepare.log" 2>&1; then + remote_reason="$(tail -n 20 "$log_dir/remote_web_prepare.log" | tr '\n' ' ')" + for item in "${web_cases[@]}"; do + IFS='|' read -r server dir cmd <<<"$item" + key="$server" + web_cmds[$key]="ssh $remote_web_host '(cd $remote_web_root_expr/$remote_web_repo_name/${dir#$repo_root/} && $cmd)'" + web_status[$key]="127" + web_pass_lines[$key]="0" + web_fail_lines[$key]="0" + web_result[$key]="BLOCKED" + web_block_reason[$key]="Remote Dart.web environment unavailable: $remote_reason" + printf 'BLOCKED remote web %s->Dart.web: %s\n' "$server" "$remote_reason" >&2 + done + return + fi + remote_web_execution="remote" + remote_web_prepare_summary="$(grep '^remote Dart.web ' "$log_dir/remote_web_prepare.log" 2>/dev/null | tr '\n' ' ')" + for item in "${web_cases[@]}"; do IFS='|' read -r server dir cmd <<<"$item" key="$server" - web_cmds[$key]="(cd ${dir#$repo_root/} && $cmd)" - web_status[$key]="127" - web_pass_lines[$key]="0" - web_fail_lines[$key]="0" - web_result[$key]="BLOCKED" - web_block_reason[$key]="Chrome executable not found. Install google-chrome or set CHROME_EXECUTABLE." - printf 'BLOCKED web %s->Dart.web: Chrome executable not found\n' "$server" >&2 + log_file="$log_dir/web_${server}.log" + web_cmds[$key]="ssh $remote_web_host '(cd $remote_web_root_expr/$remote_web_repo_name/${dir#$repo_root/} && $cmd)'" + run_remote_web_logged "$server" "$dir" "$cmd" "$log_file" + status=$? + pass_count="$(count_lines '^PASS scenario=' "$log_file")" + fail_count="$(count_lines '^FAIL ' "$log_file")" + web_status[$key]="$status" + web_pass_lines[$key]="$pass_count" + web_fail_lines[$key]="$fail_count" + if [ "$status" -eq 0 ] && [ "$fail_count" -eq 0 ] && [ "$pass_count" -eq "$expected_web_pass_lines" ]; then + web_result[$key]="PASS" + else + web_result[$key]="FAIL" + fi done return fi @@ -247,10 +369,38 @@ print_unit_table() { done } -cell_value() { - local server="$1" - local client="$2" - local key="$server|$client" +language_key() { + local label="$1" + if [ "$label" = "Dart.io" ]; then + echo "Dart" + return + fi + echo "$label" +} + +display_language_label() { + local label="$1" + if [ "$label" = "Dart" ]; then + echo "Dart.io" + return + fi + echo "$label" +} + +language_matrix_cell() { + local server_label="$1" + local client_label="$2" + local server client key + + if [ "$client_label" = "Dart.web" ]; then + echo "${web_result[$server_label]:--}" + return + fi + + server="$(language_key "$server_label")" + client="$(language_key "$client_label")" + key="$server|$client" + if [ "$server" = "$client" ]; then if [ "$mode" = "all" ] || [ "$mode" = "unit" ]; then echo "${unit_result[$server]:--}" @@ -259,18 +409,22 @@ cell_value() { fi return fi + echo "${cross_result[$key]:--}" } -print_cross_table() { +print_language_pass_matrix() { local server client - printf '\n**언어간 통신**\n' - printf '| 서버 \\ 클라이언트 | Dart | Go | Kotlin | Python | TypeScript |\n' - printf '|---|---|---|---|---|---|\n' - for server in "${languages[@]}"; do + local servers=("Dart.io" "Go" "Kotlin" "Python" "TypeScript") + local clients=("Dart.io" "Dart.web" "Go" "Kotlin" "Python" "TypeScript") + + printf '\n**언어 PASS 매트릭스**\n' + printf '| 서버 \\ 클라이언트 | Dart.io | Dart.web | Go | Kotlin | Python | TypeScript |\n' + printf '|---|---|---|---|---|---|---|\n' + for server in "${servers[@]}"; do printf '| %s' "$server" - for client in "${languages[@]}"; do - printf ' | %s' "$(cell_value "$server" "$client")" + for client in "${clients[@]}"; do + printf ' | %s' "$(language_matrix_cell "$server" "$client")" done printf ' |\n' done @@ -285,19 +439,13 @@ print_cross_detail_table() { IFS='|' read -r server client dir cmd <<<"$item" key="$server|$client" printf '| %s -> %s | %s | %s | %s | %s |\n' \ - "$server" "$client" "${cross_result[$key]:--}" "${cross_pass_lines[$key]:--}" "$expected_cross_pass_lines" "${cross_fail_lines[$key]:--}" + "$(display_language_label "$server")" "$(display_language_label "$client")" \ + "${cross_result[$key]:--}" "${cross_pass_lines[$key]:--}" "$expected_cross_pass_lines" "${cross_fail_lines[$key]:--}" done -} - -print_dart_web_table() { - local item server dir cmd key - printf '\n**Dart.web 클라이언트 통신**\n' - printf '| 서버 | Dart.web (WS) | PASS scenarios | Expected | FAIL lines |\n' - printf '|---|---:|---:|---:|---:|\n' for item in "${web_cases[@]}"; do IFS='|' read -r server dir cmd <<<"$item" key="$server" - printf '| %s | %s | %s | %s | %s |\n' \ + printf '| %s -> Dart.web | %s | %s | %s | %s |\n' \ "$server" "${web_result[$key]:--}" "${web_pass_lines[$key]:--}" "$expected_web_pass_lines" "${web_fail_lines[$key]:--}" done } @@ -417,9 +565,8 @@ print_report_body() { print_unit_table fi if [ "$mode" = "all" ] || [ "$mode" = "cross" ]; then - print_cross_table + print_language_pass_matrix print_cross_detail_table - print_dart_web_table fi printf '\n로그 디렉터리: `%s`\n' "$log_dir" @@ -457,6 +604,14 @@ write_result_record() { printf -- '- 실행 명령: `bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_matrix.sh --%s`\n' "$mode" printf -- '- exit code: %s\n' "$exit_code" printf -- '- 로그 디렉터리: `%s`\n' "$log_dir" + if [ "$mode" = "all" ] || [ "$mode" = "cross" ]; then + printf -- '- Dart.web 실행 환경: %s\n' "$remote_web_execution" + if [ "$remote_web_execution" = "remote" ]; then + printf -- '- Dart.web remote host: `%s`\n' "$remote_web_host" + printf -- '- Dart.web remote path: `%s/%s`\n' "$remote_web_root_expr" "$remote_web_repo_name" + printf -- '- Dart.web remote 준비: %s\n' "$remote_web_prepare_summary" + fi + fi printf -- '- 전체 결과값: %s\n\n' "$overall_result" printf '## git status 요약\n\n' printf '```text\n'