Spaces:
Sleeping
Sleeping
| from __future__ import annotations | |
| import argparse | |
| import json | |
| import os | |
| import subprocess | |
| import sys | |
| from datetime import UTC, datetime | |
| from pathlib import Path | |
| from typing import Any | |
| from urllib.error import HTTPError, URLError | |
| from urllib.request import Request, urlopen | |
| from check_public_space import DEFAULT_SPACE, run_checks | |
| from huggingface_hub import HfApi | |
| DEFAULT_MODEL_REPO = "build-small-hackathon/dota2tuned-qwen3-4b-2507-lora" | |
| DEFAULT_DATASET_REPO = "build-small-hackathon/dota2tuned-data" | |
| DEFAULT_MODAL_URL = "https://dracufeuer--dota2tuned-ui.modal.run" | |
| DEFAULT_GITHUB_REPO = "https://github.com/1ncompleteness/DOTA2Tuned" | |
| MANUAL_ITEMS = [ | |
| "Record short demo video.", | |
| "Publish social post.", | |
| "Submit Space link, demo video link, and social post link by June 15, 2026.", | |
| ] | |
| def _http_status(url: str, *, timeout: int = 30) -> dict[str, Any]: | |
| request = Request(url, headers={"User-Agent": "DOTA2Tuned submission checker"}) | |
| try: | |
| with urlopen(request, timeout=timeout) as response: | |
| return {"ok": 200 <= response.status < 400, "status": response.status} | |
| except HTTPError as exc: | |
| return {"ok": False, "status": exc.code, "error": str(exc)} | |
| except URLError as exc: | |
| return {"ok": False, "status": None, "error": str(exc.reason)} | |
| def _git_status() -> dict[str, Any]: | |
| result = subprocess.run( | |
| ["git", "status", "--short", "--branch"], | |
| check=False, | |
| capture_output=True, | |
| text=True, | |
| ) | |
| lines = result.stdout.strip().splitlines() | |
| changed = [line for line in lines[1:] if line.strip()] | |
| return { | |
| "ok": result.returncode == 0 and not changed, | |
| "returncode": result.returncode, | |
| "status": lines, | |
| } | |
| def _repo_has_file(api: HfApi, repo_id: str, repo_type: str, filename: str) -> dict[str, Any]: | |
| try: | |
| if repo_type == "model": | |
| info = api.model_info(repo_id) | |
| elif repo_type == "dataset": | |
| info = api.dataset_info(repo_id) | |
| else: | |
| raise ValueError(f"unsupported repo_type: {repo_type}") | |
| files = {sibling.rfilename for sibling in info.siblings} | |
| return {"ok": filename in files, "file": filename, "repo": repo_id} | |
| except Exception as exc: # pragma: no cover - network smoke script | |
| return {"ok": False, "file": filename, "repo": repo_id, "error": repr(exc)} | |
| def _space_runtime(api: HfApi, space_id: str) -> dict[str, Any]: | |
| try: | |
| info = api.space_info(space_id) | |
| runtime = getattr(info, "runtime", None) | |
| stage = getattr(runtime, "stage", str(runtime)) | |
| return {"ok": stage == "RUNNING", "stage": stage, "space": space_id} | |
| except Exception as exc: # pragma: no cover - network smoke script | |
| return {"ok": False, "space": space_id, "error": repr(exc)} | |
| def run_submission_checks(args: argparse.Namespace) -> dict[str, Any]: | |
| token = os.getenv("HF_TOKEN") | |
| api = HfApi(token=token) | |
| space_id = args.space_repo | |
| checks: dict[str, Any] = { | |
| "git_clean": _git_status(), | |
| "space_http": _http_status(args.space_url), | |
| "modal_http": _http_status(args.modal_url), | |
| "github_http": _http_status(args.github_repo), | |
| "space_runtime": _space_runtime(api, space_id), | |
| "model_card": _repo_has_file(api, args.model_repo, "model", "README.md"), | |
| "dataset_card": _repo_has_file(api, args.dataset_repo, "dataset", "README.md"), | |
| } | |
| if not args.skip_public_api: | |
| public_api = run_checks(args.space_url) | |
| checks["public_space_api"] = { | |
| "ok": all(item["status"] == "ok" for item in public_api["checks"]), | |
| "checks": public_api["checks"], | |
| } | |
| return { | |
| "generated_at": datetime.now(UTC).isoformat(), | |
| "machine_checks": checks, | |
| "manual_remaining": MANUAL_ITEMS, | |
| "links": { | |
| "space": args.space_url, | |
| "github": args.github_repo, | |
| "model": f"https://huggingface.co/{args.model_repo}", | |
| "dataset": f"https://huggingface.co/datasets/{args.dataset_repo}", | |
| "modal": args.modal_url, | |
| }, | |
| } | |
| def _machine_ok(payload: dict[str, Any]) -> bool: | |
| return all(check.get("ok") is True for check in payload["machine_checks"].values()) | |
| def main() -> None: | |
| parser = argparse.ArgumentParser(description="Run final DOTA2Tuned submission checks.") | |
| parser.add_argument("--space-url", default=DEFAULT_SPACE) | |
| parser.add_argument("--space-repo", default="build-small-hackathon/dota2tuned") | |
| parser.add_argument("--model-repo", default=DEFAULT_MODEL_REPO) | |
| parser.add_argument("--dataset-repo", default=DEFAULT_DATASET_REPO) | |
| parser.add_argument("--modal-url", default=DEFAULT_MODAL_URL) | |
| parser.add_argument("--github-repo", default=DEFAULT_GITHUB_REPO) | |
| parser.add_argument( | |
| "--output", | |
| default="submission_evidence/final_submission_check.json", | |
| help="Path for JSON evidence output.", | |
| ) | |
| parser.add_argument( | |
| "--skip-public-api", | |
| action="store_true", | |
| help="Skip Gradio endpoint checks when only public artifact status is needed.", | |
| ) | |
| args = parser.parse_args() | |
| payload = run_submission_checks(args) | |
| output_path = Path(args.output) | |
| output_path.parent.mkdir(parents=True, exist_ok=True) | |
| output_path.write_text(json.dumps(payload, indent=2), encoding="utf-8") | |
| print("Machine checks:") | |
| for name, check in payload["machine_checks"].items(): | |
| detail = check.get("stage") or check.get("status") or check.get("file") or "" | |
| print(f"- {name}: {'ok' if check.get('ok') else 'fail'} {detail}") | |
| print("\nManual remaining:") | |
| for item in payload["manual_remaining"]: | |
| print(f"- {item}") | |
| print(f"\nWrote {output_path}") | |
| if not _machine_ok(payload): | |
| sys.exit(1) | |
| if __name__ == "__main__": | |
| main() | |