v1.1.46: phase2 — scenario runner MVP (YAML config, DB schema, API endpoints, UI section)

This commit is contained in:
2026-07-30 13:48:34 +04:00
parent 0ab6b3a89e
commit 7eeb1131b3
7 changed files with 458 additions and 1 deletions
+86
View File
@@ -0,0 +1,86 @@
"""
API для запуска сценариев автотестирования.
POST /api/scenario/run — запустить сценарий (фон)
GET /api/scenario/status/<id> — поллинг статуса сценария
GET /api/scenarios — список доступных сценариев
GET /api/scenario/history — история запусков сценариев
"""
from flask import Blueprint, current_app, jsonify, request
import threading
from api.auth import get_client, get_client_id, get_stand, get_token_info
from operations.scenario import load_scenarios, run_scenario
from db.pool import get_conn, put_conn
bp = Blueprint("api_scenario", __name__)
@bp.route("/api/scenarios")
def api_scenarios():
"""Список доступных сценариев из config.yaml."""
try:
scenarios = load_scenarios()
result = [{"name": name, "steps": len(s.get("steps", []))} for name, s in scenarios.items()]
return jsonify(sorted(result, key=lambda x: x["name"]))
except Exception as e:
return jsonify({"error": str(e)}), 500
@bp.route("/api/scenario/run", methods=["POST"])
def api_scenario_run():
"""Запустить сценарий. Возвращает scenario_run_id сразу, выполнение в фоне."""
try:
data = request.get_json()
scenario_name = (data.get("scenario") or "").strip()
if not scenario_name:
return jsonify({"error": "scenario name is required"}), 400
client = get_client()
user_email = get_token_info().get("email", "")
app_version = current_app.config.get("VERSION", "")
# Запуск в фоне
threading.Thread(
target=run_scenario,
args=(client, scenario_name, get_client_id(), get_stand(), user_email, app_version),
daemon=True,
).start()
return jsonify({"status": "RUNNING", "scenario": scenario_name})
except Exception as e:
import traceback
print(f"[SCENARIO API] run error: {traceback.format_exc()}", flush=True)
return jsonify({"error": str(e)}), 500
@bp.route("/api/scenario/status")
def api_scenario_status():
"""Последний запущенный сценарий (или несколько последних)."""
conn = get_conn()
if not conn:
return jsonify([])
try:
cur = conn.cursor()
cur.execute("""
SELECT id, created_at, scenario_name, status, current_step, total_steps,
duration_sec, error_log
FROM scenario_runs
WHERE client_id = %s AND stand = %s
ORDER BY created_at DESC
LIMIT 10
""", (get_client_id(), get_stand()))
rows = cur.fetchall()
cols = [d[0] for d in cur.description]
result = []
for r in rows:
d = dict(zip(cols, r))
if d["created_at"]:
d["created_at"] = d["created_at"].isoformat()
result.append(d)
return jsonify(result)
except Exception as e:
return jsonify({"error": str(e)}), 500
finally:
put_conn(conn)