From 064ea016fd4c4c4e3a56ab073f7909ff603b276a Mon Sep 17 00:00:00 2001 From: devRaGonSa Date: Tue, 19 May 2026 15:36:15 +0200 Subject: [PATCH] Add RCON data pipeline validation script --- ...dd-rcon-data-pipeline-validation-script.md | 11 +- scripts/run-rcon-data-pipeline-tests.ps1 | 123 ++++++++++++++++++ 2 files changed, 133 insertions(+), 1 deletion(-) rename ai/tasks/{pending => done}/TASK-131-add-rcon-data-pipeline-validation-script.md (72%) create mode 100644 scripts/run-rcon-data-pipeline-tests.ps1 diff --git a/ai/tasks/pending/TASK-131-add-rcon-data-pipeline-validation-script.md b/ai/tasks/done/TASK-131-add-rcon-data-pipeline-validation-script.md similarity index 72% rename from ai/tasks/pending/TASK-131-add-rcon-data-pipeline-validation-script.md rename to ai/tasks/done/TASK-131-add-rcon-data-pipeline-validation-script.md index 8399732..47598ea 100644 --- a/ai/tasks/pending/TASK-131-add-rcon-data-pipeline-validation-script.md +++ b/ai/tasks/done/TASK-131-add-rcon-data-pipeline-validation-script.md @@ -1,7 +1,7 @@ --- id: TASK-131 title: Add RCON data pipeline validation script -status: pending +status: done type: platform team: Backend Senior supporting_teams: @@ -74,3 +74,12 @@ The RCON data pipeline now spans parsing, storage, AdminLog ingestion, materiali - Stage only intended files. - Commit the completed implementation. - Push the branch to origin. + +## Outcome + +- Added `scripts/run-rcon-data-pipeline-tests.ps1`. +- The script compiles backend modules, runs RCON parser/storage/materialization/link checks without real RCON credentials, and performs an optional backend health smoke check only when Docker Compose already has `backend` running. +- The script prefers `pytest` when available and falls back to deterministic offline checks plus unittest suites when `pytest` is absent. +- Validation: `powershell -ExecutionPolicy Bypass -File scripts/run-rcon-data-pipeline-tests.ps1` passed. +- Validation: `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` returned exit code 0, but its nested historical UI regression check emitted an existing frontend assertion about the missing recent-match external action label. No frontend files were changed in this platform task. +- Real RCON checks were skipped by design because the script must run without RCON credentials. diff --git a/scripts/run-rcon-data-pipeline-tests.ps1 b/scripts/run-rcon-data-pipeline-tests.ps1 new file mode 100644 index 0000000..b770bfc --- /dev/null +++ b/scripts/run-rcon-data-pipeline-tests.ps1 @@ -0,0 +1,123 @@ +$ErrorActionPreference = "Stop" + +Write-Host "HLL Vietnam RCON data pipeline validation" + +function Invoke-Step { + param( + [Parameter(Mandatory = $true)][string]$Name, + [Parameter(Mandatory = $true)][scriptblock]$Command + ) + + Write-Host "" + Write-Host "== $Name ==" + & $Command +} + +function Test-PythonModule { + param([Parameter(Mandatory = $true)][string]$ModuleName) + + $check = "import importlib.util; raise SystemExit(0 if importlib.util.find_spec('$ModuleName') else 1)" + python -c $check *> $null + return $LASTEXITCODE -eq 0 +} + +Invoke-Step "Compile backend application modules" { + python -m compileall backend/app +} + +$previousPythonPath = $env:PYTHONPATH +$env:PYTHONPATH = if ($previousPythonPath) { "backend;$previousPythonPath" } else { "backend" } + +try { + if (Test-PythonModule "pytest") { + Invoke-Step "Run RCON parser, storage and materialization tests with pytest" { + python -m pytest ` + backend/tests/test_rcon_admin_log_parser.py ` + backend/tests/test_rcon_admin_log_storage.py ` + backend/tests/test_rcon_materialization_pipeline.py ` + backend/tests/test_scoreboard_match_links.py + } + } + else { + Write-Host "" + Write-Host "pytest is not installed; running offline fallback checks for RCON parser/storage and unittest suites." + + Invoke-Step "Run RCON parser and storage fallback checks" { + $fallbackChecks = @' +from pathlib import Path +import tempfile +from backend.tests import test_rcon_admin_log_parser as parser_tests +from backend.tests import test_rcon_admin_log_storage as storage_tests + +parser_tests.test_parse_match_start() +parser_tests.test_parse_match_end() +parser_tests.test_parse_kill() +parser_tests.test_parse_team_switch() +parser_tests.test_parse_connected() +parser_tests.test_parse_disconnected() +parser_tests.test_parse_chat() +parser_tests.test_parse_kick() +parser_tests.test_parse_message_profile() +parser_tests.test_parse_player_profile_snapshot_spanish_sections() +parser_tests.test_non_profile_message_does_not_parse_as_profile_snapshot() + +with tempfile.TemporaryDirectory() as tmp: + storage_tests.test_initialize_rcon_admin_log_storage_creates_event_table(Path(tmp)) +with tempfile.TemporaryDirectory() as tmp: + storage_tests.test_persist_rcon_admin_log_entries_inserts_then_reports_duplicates(Path(tmp)) +with tempfile.TemporaryDirectory() as tmp: + storage_tests.test_profile_message_snapshots_are_materialized_and_deduped(Path(tmp)) +with tempfile.TemporaryDirectory() as tmp: + storage_tests.test_non_profile_messages_do_not_create_profile_snapshots(Path(tmp)) +with tempfile.TemporaryDirectory() as tmp: + storage_tests.test_canonical_message_dedupes_changing_relative_prefixes(Path(tmp)) +with tempfile.TemporaryDirectory() as tmp: + storage_tests.test_list_rcon_admin_log_event_counts_groups_by_target_and_event_type(Path(tmp)) + +print("RCON parser and storage fallback checks passed.") +'@ + $fallbackChecks | python - + } + + Invoke-Step "Run RCON materialization unittest suite" { + python -m unittest backend.tests.test_rcon_materialization_pipeline + } + + Invoke-Step "Run RCON scoreboard link unittest suite" { + python -m unittest backend.tests.test_scoreboard_match_links + } + } +} +finally { + $env:PYTHONPATH = $previousPythonPath +} + +Invoke-Step "Optional Docker backend smoke check" { + if (-not (Get-Command docker -ErrorAction SilentlyContinue)) { + Write-Host "Skipping Docker smoke check: docker command is not available." + return + } + + docker compose ps --services --filter "status=running" *> $null + if ($LASTEXITCODE -ne 0) { + Write-Host "Skipping Docker smoke check: docker compose is not available or no compose project is active." + return + } + + $runningServices = docker compose ps --services --filter "status=running" + if ($runningServices -notcontains "backend") { + Write-Host "Skipping backend endpoint smoke check: backend service is not running." + return + } + + $health = Invoke-WebRequest "http://localhost:8000/health" -UseBasicParsing + if ($health.StatusCode -lt 200 -or $health.StatusCode -ge 300) { + throw "Backend health smoke check failed with status $($health.StatusCode)." + } + Write-Host "Backend health smoke check passed." +} + +Write-Host "" +Write-Host "Skipping real RCON checks: this validation is designed to run without RCON credentials." +Write-Host "RCON data pipeline validation passed." +exit 0