Spaces:
Running
Running
File size: 5,490 Bytes
e317359 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | #!/usr/bin/env python3
"""Validate and publish one atomic Gradio Space revision (app plus public results)."""
from __future__ import annotations
import argparse
import json
import os
from pathlib import Path
import shutil
import sys
import tempfile
import time
from types import SimpleNamespace
from dotenv import load_dotenv
ROOT = Path(__file__).resolve().parents[1]
SPACE = ROOT / "space"
sys.path.insert(0, str(ROOT / "scripts"))
def stage_space(destination: Path, results: Path) -> None:
from push_results_to_hf import stage_public_results
for name in ("app.py", "requirements.txt", "constraints.txt", "README.md"):
shutil.copy2(SPACE / name, destination / name)
shutil.copytree(
SPACE / "src",
destination / "src",
ignore=shutil.ignore_patterns("__pycache__", "*.pyc", ".DS_Store"),
)
stage_public_results(results, destination / "results")
if not list((destination / "results").glob("*/all_results.csv")):
raise ValueError("No leaderboard CSVs. Run scripts/bootstrap_data.py first.")
for p in (destination / "results").rglob("*.json"):
json.loads(p.read_text())
def main() -> int:
load_dotenv(ROOT / ".env")
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"--repo", default=os.getenv("HF_SPACE_REPO", "ThinkcatLab/LiveHouse-TS")
)
parser.add_argument("--results", type=Path, default=SPACE / "results")
parser.add_argument("--results-repo", default=os.getenv("HF_RESULTS_REPO"))
parser.add_argument(
"--dry-run", action="store_true", help="Validate deployment without publishing"
)
parser.add_argument(
"--app-only",
action="store_true",
help="Update UI code while retaining all remote result tables",
)
args = parser.parse_args()
from push_results_to_hf import (
ensure_space_repo,
get_hf_api,
prune_remote_non_leaderboard_artifacts,
push_via_api,
)
with tempfile.TemporaryDirectory(prefix="livehouse-space-") as temp:
stage = Path(temp)
stage_space(stage, args.results)
# Results have their own Dataset; the Space holds application code only.
shutil.rmtree(stage / "results")
count = sum(p.is_file() for p in stage.rglob("*"))
print(f"Validated Space deployment: {count} public files.")
if args.dry_run:
return 0
token = (os.getenv("HF_TOKEN") or "").strip()
if not token:
raise SystemExit("HF_TOKEN required in .env")
api = get_hf_api(token)
# Stop an older snapshot from replacing newer online scores.
from huggingface_hub import hf_hub_download
from huggingface_hub.utils import EntryNotFoundError, RepositoryNotFoundError
remote = None
results_repo = args.results_repo or args.repo + "-results"
if not args.app_only:
try:
remote = Path(
hf_hub_download(
results_repo,
"results/online_status.json",
repo_type="dataset",
token=token,
)
)
except (EntryNotFoundError, RepositoryNotFoundError):
pass
if remote:
from datetime import datetime
online = json.loads(remote.read_text()).get("finished_at")
local = json.loads((args.results / "online_status.json").read_text()).get(
"finished_at"
)
if online and (
not local
or datetime.fromisoformat(online.replace("Z", "+00:00"))
> datetime.fromisoformat(local.replace("Z", "+00:00"))
):
raise SystemExit(
"Remote evaluation is newer. Restore its latest operator backup before deploying; refusing rollback."
)
ensure_space_repo(token, args.repo)
if not args.app_only:
if push_via_api(SimpleNamespace(repo=args.repo, results_repo=results_repo,
results=args.results, restart_space=False,
commit_message="Publish verified LiveHouse-TS metrics"), token):
return 1
if not prune_remote_non_leaderboard_artifacts(token, args.repo):
return 1
variables = api.get_space_variables(args.repo)
current = variables.get("HF_RESULTS_REPO")
if current is None or current.value != results_repo:
api.add_space_variable(args.repo, key="HF_RESULTS_REPO", value=results_repo)
for attempt in range(3):
try:
commit = api.upload_folder(
folder_path=stage, repo_id=args.repo, repo_type="space",
commit_message="Deploy maintained LiveHouse-TS application",
)
break
except Exception as exc:
status = getattr(getattr(exc, "response", None), "status_code", None)
if attempt == 2 or status not in (None, 429, 502, 503, 504):
raise
time.sleep(3 * (attempt + 1))
print(f"Deployed {commit.oid}: https://huggingface.co/spaces/{args.repo}")
print("Run scripts/check_health.py --online to verify the rebuilt Space.")
return 0
if __name__ == "__main__":
raise SystemExit(main())
|