| from __future__ import annotations |
|
|
| import argparse |
| import json |
| import sys |
| from pathlib import Path |
|
|
|
|
| ROOT_DIR = Path(__file__).resolve().parent.parent |
| if str(ROOT_DIR) not in sys.path: |
| sys.path.insert(0, str(ROOT_DIR)) |
|
|
| from scripts.configure_vercel_worker import DEFAULT_SITE_URL, configure_vercel_worker |
| from scripts.deploy_hf_space import DEFAULT_BUNDLE_DIR, deploy_hf_space, token_available, worker_url_for_repo |
| from scripts.prove_live_deployment import prove_live_deployment |
|
|
|
|
| def finish_live_deployment( |
| repo_id: str, |
| site_url: str = DEFAULT_SITE_URL, |
| code: str = "1234", |
| bundle_dir: Path = DEFAULT_BUNDLE_DIR, |
| token: str | None = None, |
| private: bool = False, |
| force_export: bool = True, |
| verify_site_after_vercel: bool = True, |
| run_proof: bool = True, |
| smoke_ocr_engine: str = "arabic", |
| smoke_voice_id: str = "espeak-ar-clear", |
| smoke_timeout: float = 180, |
| ) -> dict[str, object]: |
| deploy_result = deploy_hf_space( |
| repo_id=repo_id, |
| bundle_dir=bundle_dir, |
| token=token, |
| private=private, |
| force_export=force_export, |
| ) |
| worker_url = str(deploy_result["workerUrl"]) |
| vercel_result = configure_vercel_worker( |
| worker_url, |
| site_url=site_url, |
| code=code, |
| redeploy=True, |
| verify=verify_site_after_vercel, |
| ) |
| proof_result = None |
| if run_proof: |
| proof_result = prove_live_deployment( |
| worker_url, |
| site_url, |
| code=code, |
| smoke_voice_id=smoke_voice_id, |
| smoke_ocr_engine=smoke_ocr_engine, |
| smoke_timeout=smoke_timeout, |
| ) |
| return { |
| "repoId": repo_id, |
| "siteUrl": site_url.rstrip("/"), |
| "workerUrl": worker_url, |
| "workerDeploy": deploy_result, |
| "vercel": vercel_result, |
| "proof": proof_result, |
| "complete": bool(proof_result and proof_result.get("complete")), |
| "nextCommand": ( |
| f"python scripts\\prove_live_deployment.py {worker_url} --origin {site_url.rstrip('/')} " |
| f"--code {code} --smoke-ocr-engine {smoke_ocr_engine}" |
| ), |
| } |
|
|
|
|
| def dry_run_finish_live_deployment( |
| repo_id: str, |
| site_url: str = DEFAULT_SITE_URL, |
| code: str = "1234", |
| bundle_dir: Path = DEFAULT_BUNDLE_DIR, |
| token: str | None = None, |
| smoke_ocr_engine: str = "arabic", |
| ) -> dict[str, object]: |
| worker_url = worker_url_for_repo(repo_id) |
| site_url = site_url.rstrip("/") |
| return { |
| "dryRun": True, |
| "repoId": repo_id, |
| "siteUrl": site_url, |
| "workerUrl": worker_url, |
| "bundleDir": str(bundle_dir), |
| "tokenAvailable": token_available(token), |
| "willUploadWorker": True, |
| "willConfigureVercel": True, |
| "willRunProof": True, |
| "commands": { |
| "setToken": '$env:HF_TOKEN="<your-hugging-face-write-token>"', |
| "finish": ( |
| f"python scripts\\finish_live_deployment.py {repo_id} " |
| f"--site-url {site_url} --code {code} --smoke-ocr-engine {smoke_ocr_engine}" |
| ), |
| "configureVercelOnly": ( |
| f"python scripts\\configure_vercel_worker.py {worker_url} " |
| f"--site-url {site_url} --code {code} --verify" |
| ), |
| "proofOnly": ( |
| f"python scripts\\prove_live_deployment.py {worker_url} " |
| f"--origin {site_url} --code {code} --smoke-ocr-engine {smoke_ocr_engine}" |
| ), |
| }, |
| } |
|
|
|
|
| def main_with_args(argv: list[str] | None = None) -> int: |
| parser = argparse.ArgumentParser( |
| description="Upload the HF worker, configure Vercel WORKER_BASE_URL, redeploy, and run live proof." |
| ) |
| parser.add_argument("repo_id", help="Hugging Face Space repo id, e.g. username/arabic-audio-reader-worker.") |
| parser.add_argument("--site-url", default=DEFAULT_SITE_URL) |
| parser.add_argument("--code", default="1234") |
| parser.add_argument("--bundle-dir", type=Path, default=DEFAULT_BUNDLE_DIR) |
| parser.add_argument("--token", help="Hugging Face write token. Prefer HF_TOKEN in the environment.") |
| parser.add_argument("--private", action="store_true") |
| parser.add_argument("--no-force-export", action="store_true") |
| parser.add_argument("--skip-site-verify", action="store_true") |
| parser.add_argument("--skip-proof", action="store_true") |
| parser.add_argument("--dry-run", action="store_true", help="Print the planned deployment without changing HF or Vercel.") |
| parser.add_argument("--smoke-ocr-engine", default="arabic") |
| parser.add_argument("--smoke-voice-id", default="espeak-ar-clear") |
| parser.add_argument("--smoke-timeout", type=float, default=180) |
| parser.add_argument("--json", action="store_true") |
| args = parser.parse_args(argv) |
|
|
| if args.dry_run: |
| result = dry_run_finish_live_deployment( |
| args.repo_id, |
| site_url=args.site_url, |
| code=args.code, |
| bundle_dir=args.bundle_dir, |
| token=args.token, |
| smoke_ocr_engine=args.smoke_ocr_engine, |
| ) |
| if args.json: |
| print(json.dumps(result, ensure_ascii=False, indent=2)) |
| else: |
| print(f"Predicted worker URL: {result['workerUrl']}") |
| print(f"Hugging Face token available: {'yes' if result['tokenAvailable'] else 'no'}") |
| print("Command:") |
| print(result["commands"]["finish"]) |
| return 0 |
|
|
| result = finish_live_deployment( |
| args.repo_id, |
| site_url=args.site_url, |
| code=args.code, |
| bundle_dir=args.bundle_dir, |
| token=args.token, |
| private=args.private, |
| force_export=not args.no_force_export, |
| verify_site_after_vercel=not args.skip_site_verify, |
| run_proof=not args.skip_proof, |
| smoke_ocr_engine=args.smoke_ocr_engine, |
| smoke_voice_id=args.smoke_voice_id, |
| smoke_timeout=args.smoke_timeout, |
| ) |
| if args.json: |
| print(json.dumps(result, ensure_ascii=False, indent=2)) |
| else: |
| print(f"Worker URL: {result['workerUrl']}") |
| print(f"Vercel site: {result['siteUrl']}") |
| if result["complete"]: |
| print("Live deployment proof is complete.") |
| else: |
| print("Live deployment still needs proof:") |
| print(result["nextCommand"]) |
| return 0 if result["complete"] or args.skip_proof else 1 |
|
|
|
|
| def main() -> int: |
| return main_with_args() |
|
|
|
|
| if __name__ == "__main__": |
| raise SystemExit(main()) |
|
|