"""Who or what started each run, as the runs list and run detail say it. A run records the user who started it (triggered_by) and where it came from (origin / origin_id, migration 0031): a schedule, an alert rule, or an agent over MCP. This turns those into "schedule nightly", "alert rule nas down", "alice via MCP" or "alice", in three queries for a whole page of runs. """ from __future__ import annotations from sqlalchemy import select from steward.models.alerts import AlertRule from steward.models.ansible_schedule import AnsibleSchedule from steward.models.users import User def describe_origin(run, users: dict, schedules: dict, rules: dict) -> dict: """{"text", "url", "kind"} for one run, from id → name maps. A schedule or rule deleted since is named as such; a run with neither a user nor an origin predates origins and was started by Steward itself.""" who = users.get(run.triggered_by, "a deleted user") if run.triggered_by else None if run.origin == "schedule": name = schedules.get(run.origin_id) text = f"schedule {name}" if name else "a deleted schedule" if who: text += f" (run now by {who})" return {"text": text, "url": f"/ansible/schedules/{run.origin_id}" if name else None, "kind": "schedule"} if run.origin == "alert": name = rules.get(run.origin_id) return {"text": f"alert rule {name}" if name else "a deleted alert rule", "url": f"/alerts/history?rule={run.origin_id}" if name else None, "kind": "alert"} if run.origin == "mcp": return {"text": f"{who or 'an agent'} via MCP", "url": None, "kind": "mcp"} if who: return {"text": who, "url": None, "kind": "user"} return {"text": "Steward", "url": None, "kind": "system"} async def run_origins(db, runs) -> dict[str, dict]: """{run id: describe_origin(run)} for a page of runs.""" runs = list(runs) user_ids = {r.triggered_by for r in runs if r.triggered_by} sched_ids = {r.origin_id for r in runs if r.origin == "schedule" and r.origin_id} rule_ids = {r.origin_id for r in runs if r.origin == "alert" and r.origin_id} users = dict((await db.execute( select(User.id, User.username).where(User.id.in_(user_ids)))).all()) if user_ids else {} schedules = dict((await db.execute( select(AnsibleSchedule.id, AnsibleSchedule.name).where(AnsibleSchedule.id.in_(sched_ids)))).all()) \ if sched_ids else {} rules = dict((await db.execute( select(AlertRule.id, AlertRule.name).where(AlertRule.id.in_(rule_ids)))).all()) if rule_ids else {} return {r.id: describe_origin(r, users, schedules, rules) for r in runs}