import argparse
import sys
from pathlib import Path
from .api import serve
from .config import load_config
from .db.connection import connect
from .db.migrations import apply_migrations
from .reports import render_json, render_markdown
from .watcher import Watcher
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(prog="watcher")
parser.add_argument("--config", type=Path, default=Path("config.yaml"))
sub = parser.add_subparsers(dest="command", required=True)
sub.add_parser("migrate")
sub.add_parser("validate-config")
sub.add_parser("scan")
report = sub.add_parser("report")
report.add_argument("--format", choices=("json", "markdown"), default="json")
sub.add_parser("serve")
retention = sub.add_parser("retention")
retention.add_argument("--apply", action="store_true", help="delete records outside configured retention windows")
args = parser.parse_args(argv)
if args.command == "validate-config":
config = load_config(args.config)
print(f"valid: {args.config} ({len(config.collectors)} collectors)")
return 0
if args.command == "migrate":
config = load_config(args.config)
connection = connect(config.watcher.database_path)
version = apply_migrations(connection)
connection.close()
print(f"schema version: {version}")
return 0
config = load_config(args.config)
watcher = Watcher(config, args.config.parent)
try:
if args.command == "scan":
result = watcher.run_once()
print(f"cycle: {result.observations_created} observations, {result.collectors_failed} collector failures")
elif args.command == "report":
print(render_markdown(watcher) if args.format == "markdown" else render_json(watcher))
elif args.command == "serve":
serve(watcher, config.watcher.api_host, config.watcher.api_port)
elif args.command == "retention":
values = config.watcher.retention
counts = watcher.repository.retention({"job_observations": values.job_observations_days,
"job_runs": values.job_runs_days,
"status_events": values.status_events_days,
"collector_runs": values.collector_runs_days,
"watcher_events": values.watcher_events_days},
dry_run=not args.apply or not values.enabled)
mode = "dry-run" if not args.apply or not values.enabled else "applied"
print(f"retention {mode}: {counts}")
finally:
watcher.close()
return 0
if __name__ == "__main__":
sys.exit(main())