From b6cd0e9d76c384e603069eb3aadd40cd017c8f2e Mon Sep 17 00:00:00 2001 From: toki Date: Sat, 30 May 2026 19:14:34 +0900 Subject: [PATCH] update project files and test matrix script --- .gitignore | 4 + AGENTS.md | 3 + README.md | 4 +- agent-ops/rules/project/rules.md | 7 + .../scripts/run_matrix.sh | 175 ++++++++++++++++-- 5 files changed, 175 insertions(+), 18 deletions(-) diff --git a/.gitignore b/.gitignore index cfa3b5a..e4e8714 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,7 @@ Desktop.ini # ── Agent-Ops private rules ─────────────────────── agent-ops/rules/private/ + +# ── Agent test local rules/results ──────────────── +agent-test/local/ +agent-test/runs/ diff --git a/AGENTS.md b/AGENTS.md index 7862e61..0ef64f6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -41,3 +41,6 @@ **테스트 실행/검증 작업이 포함된 경우, 작업 환경에 맞게 최초 1회 읽고 수행한다. 환경 미지정은 local로 본다.** - local: `agent-test/local/rules.md` (없으면 `create-test`) +- 이 프로젝트의 주 사용 방식은 Git 기반 소비와 내부 로컬 검증 결과 확인이다. +- CI/CD runner 연결은 현재 설계 범위가 아니며, 사용자가 명시적으로 요청하지 않으면 제안하거나 요구하지 않는다. +- 검증 완전성 판단은 기본적으로 `run_matrix.sh --all` 실행 결과와 실패 로그 재현성으로 한다. diff --git a/README.md b/README.md index d691fdc..8b92a80 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Protocol Buffers 직렬화, TCP 4바이트 빅엔디안 길이 프리픽스 프 이 프로젝트는 새 언어 대상을 늘리거나 패키지 registry에 배포하기 전 안정화와 유지보수 단계에 있다. 지금은 이 저장소를 Git 기반으로 소비하는 흐름을 기본 지원 방식으로 둔다. C#과 Swift는 계획된 대상이지만, 실제 수요가 생기기 전까지 구현을 미룬다. -프로토콜이나 구현을 바꿀 때는 아래 로컬 검증 매트릭스를 안정성 gate로 사용한다. +프로토콜이나 구현을 바꿀 때는 아래 내부 로컬 검증 매트릭스를 안정성 gate로 사용한다. 현재 주 사용 방식은 Git 기반 소비이므로, CI/CD runner 연결은 기본 운영 모델이 아니며 이 프로젝트 규모와 배포 방식에서는 설계상 과하다. ```bash bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_matrix.sh --all @@ -227,7 +227,7 @@ bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_matrix.sh 이 명령은 proto schema sync, 동일 언어 테스트, 크로스 언어 검증을 실행하고, 실패가 있으면 재현 명령과 함께 PASS/FAIL 표를 출력한다. 더 작은 범위만 확인하려면 `--proto`, `--unit`, `--cross`를 사용한다. -외부 CI runner 연동은 상위 `../oto` 프로젝트가 실행 경로를 표준화할 때까지 보류한다. 그 전까지는 위 로컬 매트릭스를 프로젝트 안정성 gate로 본다. +외부 CI runner 연동은 이 저장소의 기본 운영 목표가 아니다. 현재 주 사용 방식은 Git 기반 소비와 내부 로컬 매트릭스 결과 확인이며, 이 범위에서는 별도 CI/CD runner 연결을 요구하지 않는다. Proto schema sync: diff --git a/agent-ops/rules/project/rules.md b/agent-ops/rules/project/rules.md index cdf2193..c6c9d69 100644 --- a/agent-ops/rules/project/rules.md +++ b/agent-ops/rules/project/rules.md @@ -48,6 +48,13 @@ VERSIONING.md — 프로토콜/패키지 버전 정책 - 새 언어 구현은 PORTING_GUIDE.md에 따라 동일 언어 테스트 + 크로스 언어 테스트 통과 후 Available 표시 - 프로토콜 버전과 패키지 버전은 분리 관리 (VERSIONING.md 참조) +## 검증 운영 기준 + +- 이 프로젝트의 주 사용 방식은 package registry나 CI/CD 배포 흐름이 아니라 Git 기반 소비다. +- 검증 루프는 내부 로컬 매트릭스 실행 결과를 기준으로 판단한다. +- 기본 검증 명령은 `bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_matrix.sh --all`이다. +- CI/CD runner 연결은 현재 설계상 과하며, 사용자가 명시적으로 요청하지 않으면 제안하거나 요구하지 않는다. + ## 마일스톤 컨텍스트 로딩 - 기능 추가, 구조 변경, 스킬 추가/수정, 문서 구조 변경 작업을 수행할 때는 `agent-roadmap/current.md`를 먼저 읽는다. 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 eb67591..24746f4 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 @@ -7,6 +7,7 @@ Usage: run_matrix.sh [--all|--unit|--cross|--proto] Runs Proto Socket proto schema sync, unit/same-language tests, and/or cross-language communication tests, then prints Markdown PASS/FAIL tables. +Each run also writes a local result record under agent-test/runs/. Defaults to --all. USAGE } @@ -24,6 +25,15 @@ esac script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 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)" + +case "$mode" in + all) record_profile="proto-socket-full-matrix" ;; + unit) record_profile="proto-socket-unit-matrix" ;; + cross) record_profile="proto-socket-cross-matrix" ;; + proto) record_profile="proto-socket-proto-sync" ;; +esac languages=("Dart" "Go" "Kotlin" "Python" "TypeScript") @@ -93,6 +103,7 @@ declare -A web_status declare -A web_pass_lines declare -A web_fail_lines declare -A web_cmds +declare -A web_block_reason expected_web_pass_lines=2 @@ -121,6 +132,13 @@ run_logged() { ) >"$log_file" 2>&1 } +chrome_available() { + if [ -n "${CHROME_EXECUTABLE:-}" ] && [ -x "$CHROME_EXECUTABLE" ]; then + return 0 + fi + command -v google-chrome >/dev/null 2>&1 +} + run_unit_tests() { local lang cmd dir log_file status for lang in "${languages[@]}"; do @@ -177,6 +195,21 @@ run_cross_tests() { run_web_tests() { local item server dir cmd key log_file status pass_count fail_count + if ! chrome_available; then + 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 + done + return + fi + for item in "${web_cases[@]}"; do IFS='|' read -r server dir cmd <<<"$item" key="$server" @@ -309,7 +342,12 @@ print_failures() { for item in "${web_cases[@]}"; do IFS='|' read -r server dir cmd <<<"$item" key="$server" - if [ "${web_result[$key]:-}" = "FAIL" ]; then + if [ "${web_result[$key]:-}" = "BLOCKED" ]; then + failed=1 + printf '\n**차단: %s -> Dart.web 크로스테스트**\n' "$server" + printf '재현 명령: `%s`\n' "${web_cmds[$key]}" + printf '차단 사유: %s\n\n' "${web_block_reason[$key]:-unknown}" + elif [ "${web_result[$key]:-}" = "FAIL" ]; then failed=1 log_file="$log_dir/web_${server}.log" printf '\n**실패: %s -> Dart.web 크로스테스트**\n' "$server" @@ -322,7 +360,117 @@ print_failures() { return "$failed" } +has_blocked_results() { + local item server dir cmd key + for item in "${web_cases[@]}"; do + IFS='|' read -r server dir cmd <<<"$item" + key="$server" + if [ "${web_result[$key]:-}" = "BLOCKED" ]; then + return 0 + fi + done + return 1 +} + +has_fail_results() { + local lang item server client dir cmd key + if [ "${proto_result:-}" = "FAIL" ]; then + return 0 + fi + for lang in "${languages[@]}"; do + if [ "${unit_result[$lang]:-}" = "FAIL" ]; then + return 0 + fi + done + for item in "${cross_cases[@]}"; do + IFS='|' read -r server client dir cmd <<<"$item" + key="$server|$client" + if [ "${cross_result[$key]:-}" = "FAIL" ]; then + return 0 + fi + done + for item in "${web_cases[@]}"; do + IFS='|' read -r server dir cmd <<<"$item" + key="$server" + if [ "${web_result[$key]:-}" = "FAIL" ]; then + return 0 + fi + done + return 1 +} + +overall_result_value() { + if has_fail_results; then + echo "FAIL" + elif has_blocked_results; then + echo "BLOCKED" + else + echo "PASS" + fi +} + +print_report_body() { + if [ "$mode" = "all" ] || [ "$mode" = "proto" ]; then + print_proto_table + fi + if [ "$mode" = "all" ] || [ "$mode" = "unit" ]; then + print_unit_table + fi + if [ "$mode" = "all" ] || [ "$mode" = "cross" ]; then + print_cross_table + print_cross_detail_table + print_dart_web_table + fi + + printf '\n로그 디렉터리: `%s`\n' "$log_dir" + + if print_failures; then + return 0 + fi + return 1 +} + +write_result_record() { + local report_body="$1" + local exit_code="$2" + local overall_result record_dir record_file git_ref + + overall_result="$(overall_result_value)" + + record_dir="$repo_root/agent-test/runs" + mkdir -p "$record_dir" + record_file="$record_dir/${run_record_stamp}-${record_profile}.md" + git_ref="$(git -C "$repo_root" rev-parse --short HEAD 2>/dev/null || echo "unknown")" + + { + printf '%s\n' '---' + printf 'test_env: local\n' + printf 'record_type: test-result\n' + printf 'test_profile: %s\n' "$record_profile" + printf 'created_at: %s\n' "$run_started_at" + printf 'overall_result: %s\n' "$overall_result" + printf '%s\n\n' '---' + printf '# %s local 결과 기록\n\n' "$record_profile" + printf '## 실행 정보\n\n' + printf -- '- 실행 일시: %s\n' "$run_started_at" + printf -- '- git ref: %s\n' "$git_ref" + 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" + printf -- '- 전체 결과값: %s\n\n' "$overall_result" + printf '## git status 요약\n\n' + printf '```text\n' + git -C "$repo_root" status --short 2>/dev/null || true + printf '```\n\n' + cat "$report_body" + } >"$record_file" + + printf '%s' "$record_file" +} + main() { + local report_body exit_code record_file display_record_file + case "$mode" in all) run_proto_sync @@ -342,24 +490,19 @@ main() { ;; esac - if [ "$mode" = "all" ] || [ "$mode" = "proto" ]; then - print_proto_table - fi - if [ "$mode" = "all" ] || [ "$mode" = "unit" ]; then - print_unit_table - fi - if [ "$mode" = "all" ] || [ "$mode" = "cross" ]; then - print_cross_table - print_cross_detail_table - print_dart_web_table + report_body="$log_dir/report.md" + if print_report_body >"$report_body"; then + exit_code=0 + else + exit_code=1 fi - printf '\n로그 디렉터리: `%s`\n' "$log_dir" + record_file="$(write_result_record "$report_body" "$exit_code")" + cat "$report_body" + display_record_file="${record_file#$repo_root/}" + printf '\n결과 기록 파일: `%s`\n' "$display_record_file" - if print_failures; then - exit 0 - fi - exit 1 + exit "$exit_code" } main "$@"