119 lines
3.7 KiB
Python
119 lines
3.7 KiB
Python
#!/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())
|