Initial import of watchdog-discord-route skill
This commit is contained in:
118
scripts/owner_report_driver.py
Normal file
118
scripts/owner_report_driver.py
Normal file
@@ -0,0 +1,118 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Minimal owner-report driver.
|
||||
|
||||
Consumes one pending owner report, calls an external send command, and only moves
|
||||
it to sent/ after the send command succeeds.
|
||||
|
||||
This is a deliberately small manual driver for debugging the owner-report chain.
|
||||
It does not watch directories, retry, or send anything by itself.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
from owner_report_consumer import OWNER_REPORT_ROOT, PENDING_DIR, parse_pending_report, resolve_input
|
||||
|
||||
SENT_DIR = OWNER_REPORT_ROOT / "sent"
|
||||
|
||||
|
||||
def _build_send_env(payload: dict) -> dict[str, str]:
|
||||
env = os.environ.copy()
|
||||
env.update(
|
||||
{
|
||||
"OWNER_REPORT_JSON": json.dumps(payload, ensure_ascii=False),
|
||||
"OWNER_REPORT_ID": str(payload.get("report_id") or ""),
|
||||
"OWNER_REPORT_TEAM": str(payload.get("team") or ""),
|
||||
"OWNER_REPORT_SOURCE": str(payload.get("source") or ""),
|
||||
"OWNER_REPORT_KIND": str(payload.get("report_kind") or "checkpoint"),
|
||||
"OWNER_REPORT_CREATED_AT": str(payload.get("created_at") or ""),
|
||||
"OWNER_REPORT_MESSAGE": str(payload.get("message") or ""),
|
||||
"OWNER_REPORT_PATH": str(payload.get("path") or ""),
|
||||
}
|
||||
)
|
||||
return env
|
||||
|
||||
|
||||
def _sent_path(src: Path) -> Path:
|
||||
SENT_DIR.mkdir(parents=True, exist_ok=True)
|
||||
return SENT_DIR / src.name
|
||||
|
||||
|
||||
def _finalize_successful_send(src: Path) -> dict[str, object]:
|
||||
dest = _sent_path(src)
|
||||
if src.exists():
|
||||
src.rename(dest)
|
||||
return {"moved": True, "already_archived": False, "final_path": str(dest)}
|
||||
|
||||
if dest.exists():
|
||||
return {"moved": False, "already_archived": True, "final_path": str(dest)}
|
||||
|
||||
raise FileNotFoundError(
|
||||
f"successful send completed but pending report disappeared before archiving: pending={src} sent={dest}"
|
||||
)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
ap = argparse.ArgumentParser(description="Send one pending owner report via external command")
|
||||
ap.add_argument("report", help="Pending report path, filename, or report_id")
|
||||
ap.add_argument(
|
||||
"--send-cmd",
|
||||
help="Shell command used to send the report. Can also come from OWNER_REPORT_SEND_CMD.",
|
||||
)
|
||||
ap.add_argument("--dry-run", action="store_true", help="Print what would be sent and do not move files")
|
||||
args = ap.parse_args()
|
||||
|
||||
src = resolve_input(args.report)
|
||||
payload = parse_pending_report(src)
|
||||
|
||||
send_cmd = args.send_cmd or os.environ.get("OWNER_REPORT_SEND_CMD")
|
||||
if not send_cmd and not args.dry_run:
|
||||
raise SystemExit("missing send command: use --send-cmd or OWNER_REPORT_SEND_CMD")
|
||||
|
||||
if args.dry_run:
|
||||
print(json.dumps({
|
||||
"ok": True,
|
||||
"dry_run": True,
|
||||
"action": "would_send",
|
||||
"pending_path": str(src),
|
||||
"sent_path": str(_sent_path(src)),
|
||||
"payload": payload,
|
||||
"send_cmd": send_cmd,
|
||||
}, ensure_ascii=False, indent=2))
|
||||
return 0
|
||||
|
||||
proc = subprocess.run(
|
||||
["bash", "-lc", send_cmd],
|
||||
text=True,
|
||||
capture_output=True,
|
||||
env=_build_send_env(payload),
|
||||
)
|
||||
|
||||
result = {
|
||||
"ok": proc.returncode == 0,
|
||||
"dry_run": False,
|
||||
"pending_path": str(src),
|
||||
"sent_path": str(_sent_path(src)),
|
||||
"send_cmd": send_cmd,
|
||||
"exit_code": proc.returncode,
|
||||
"stdout": proc.stdout,
|
||||
"stderr": proc.stderr,
|
||||
"payload": payload,
|
||||
}
|
||||
|
||||
if proc.returncode != 0:
|
||||
print(json.dumps(result, ensure_ascii=False, indent=2))
|
||||
return proc.returncode
|
||||
|
||||
result.update(_finalize_successful_send(src))
|
||||
print(json.dumps(result, ensure_ascii=False, indent=2))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user