Files
ai-exchange/scripts/run_offline_checks.py
2026-05-06 22:43:29 +08:00

102 lines
3.6 KiB
Python

from pathlib import Path
import json
import os
import shutil
import subprocess
import sys
from typing import Dict, List, Tuple
ROOT = Path(__file__).resolve().parents[1]
DEFAULT_CHECKS = [
("unit_tests", [sys.executable, "-m", "unittest", "discover", "-s", "tests/unit", "-p", "test_*.py"]),
("training_case_package", [sys.executable, "scripts/run_training_case_package.py"]),
("migration_static_checks", [sys.executable, "scripts/run_migration_static_checks.py"]),
("script_static_checks", [sys.executable, "scripts/run_script_static_checks.py"]),
("trading_delivery_readiness", [sys.executable, "scripts/check_trading_delivery_readiness.py"]),
("dashboard_js_syntax", ["node", "--check", "src/web/app.js"]),
("training_console_js_syntax", ["node", "--check", "src/web/training.js"]),
]
def build_check_commands(env=None) -> List[Tuple[str, List[str]]]:
env = os.environ if env is None else env
commands = list(DEFAULT_CHECKS)
replay_file = env.get("OFFLINE_REPLAY_FILE")
if replay_file:
commands.append(("replay_file", [sys.executable, "scripts/run_replay_file.py", replay_file]))
return commands
def run_checks(commands=None, runner=subprocess.run, cwd=ROOT, node_available=None, env=None) -> int:
commands = commands or build_check_commands(env=env)
if node_available is None:
node_available = shutil.which("node") is not None
env = os.environ if env is None else env
subprocess_env = dict(os.environ)
subprocess_env.update(env)
json_output = _get_bool(env, "OFFLINE_CHECKS_OUTPUT_JSON", False)
results = []
for name, command in commands:
if command[0] == "node" and not node_available:
results.append({"name": name, "status": "skipped", "exit_code": 0, "reason": "node_not_available"})
if not json_output:
print(f"Offline check skipped: {name} (node not available)")
continue
if not json_output:
print(f"Offline check started: {name}")
result = runner(command, cwd=cwd, capture_output=True, text=True, check=False, env=subprocess_env)
results.append(
{
"name": name,
"status": "passed" if result.returncode == 0 else "failed",
"exit_code": result.returncode,
"stdout": result.stdout,
"stderr": result.stderr,
}
)
if result.stdout and not json_output:
print(result.stdout.rstrip())
if result.stderr and not json_output:
print(result.stderr.rstrip())
if result.returncode != 0:
if json_output:
_print_json_summary(results)
else:
print(f"Offline check failed: {name} exit_code={result.returncode}")
return result.returncode
if not json_output:
print(f"Offline check passed: {name}")
if json_output:
_print_json_summary(results)
return 0
def main() -> int:
return run_checks()
def _get_bool(env, key: str, default: bool) -> bool:
value = env.get(key)
if value is None or value == "":
return default
return str(value).strip().lower() in {"1", "true", "yes", "on"}
def _print_json_summary(results: List[Dict[str, object]]) -> None:
print(
json.dumps(
{
"passed": all(item["status"] in {"passed", "skipped"} for item in results),
"checks": results,
},
ensure_ascii=False,
sort_keys=True,
)
)
if __name__ == "__main__":
raise SystemExit(main())