| """Push the ForgeEnv environment Space and the demo Space to the Hub. |
| |
| Usage (from repo root, with ``HF_TOKEN`` set or after ``huggingface-cli |
| login``):: |
| |
| python scripts/deploy_spaces.py \ |
| --user akhiilll \ |
| --env-space-name forgeenv \ |
| --demo-space-name forgeenv-demo |
| |
| The script is idempotent: if the Spaces already exist it just uploads the |
| folders. It does NOT push the trained model weights — that happens from |
| the Colab notebook after GRPO finishes. |
| """ |
| from __future__ import annotations |
|
|
| import argparse |
| import os |
| import sys |
| from pathlib import Path |
|
|
|
|
| def _require_token() -> str: |
| token = os.environ.get("HF_TOKEN") or os.environ.get("HUGGINGFACE_TOKEN") |
| if not token: |
| sys.exit( |
| "[deploy] No HF token in env. Set HF_TOKEN or run " |
| "`huggingface-cli login` first." |
| ) |
| return token |
|
|
|
|
| def _ensure_space(api, repo_id: str, sdk: str, token: str) -> None: |
| from huggingface_hub.utils import HfHubHTTPError |
|
|
| try: |
| api.repo_info(repo_id=repo_id, repo_type="space", token=token) |
| print(f"[deploy] Space exists: {repo_id}") |
| except HfHubHTTPError: |
| print(f"[deploy] Creating Space: {repo_id} (sdk={sdk})") |
| api.create_repo( |
| repo_id=repo_id, |
| repo_type="space", |
| space_sdk=sdk, |
| token=token, |
| exist_ok=True, |
| ) |
|
|
|
|
| def _upload(api, repo_id: str, folder: Path, token: str) -> None: |
| print(f"[deploy] Uploading {folder} -> {repo_id}") |
| api.upload_folder( |
| folder_path=str(folder), |
| repo_id=repo_id, |
| repo_type="space", |
| token=token, |
| commit_message="ForgeEnv deploy", |
| ignore_patterns=[ |
| "__pycache__", |
| "*.pyc", |
| ".pytest_cache", |
| "*.egg-info", |
| ".venv", |
| "node_modules", |
| ], |
| ) |
|
|
|
|
| def main() -> None: |
| parser = argparse.ArgumentParser(description="Deploy ForgeEnv Spaces") |
| parser.add_argument("--user", required=True, help="HF username / org") |
| parser.add_argument("--env-space-name", default="forgeenv") |
| parser.add_argument("--demo-space-name", default="forgeenv-demo") |
| parser.add_argument( |
| "--env-folder", |
| default="forgeenv-space", |
| help="Local path to the environment Space folder", |
| ) |
| parser.add_argument( |
| "--demo-folder", |
| default="demo-space", |
| help="Local path to the Gradio demo Space folder", |
| ) |
| parser.add_argument( |
| "--skip-demo", |
| action="store_true", |
| help="Only deploy the environment Space", |
| ) |
| args = parser.parse_args() |
|
|
| token = _require_token() |
| from huggingface_hub import HfApi |
|
|
| api = HfApi() |
|
|
| repo_root = Path(__file__).resolve().parents[1] |
| env_folder = (repo_root / args.env_folder).resolve() |
| demo_folder = (repo_root / args.demo_folder).resolve() |
|
|
| if not env_folder.is_dir(): |
| sys.exit(f"[deploy] env folder not found: {env_folder}") |
|
|
| env_repo = f"{args.user}/{args.env_space_name}" |
| _ensure_space(api, env_repo, sdk="docker", token=token) |
| _upload(api, env_repo, env_folder, token) |
| print(f"[deploy] Environment live: https://huggingface.co/spaces/{env_repo}") |
|
|
| if args.skip_demo: |
| return |
| if not demo_folder.is_dir(): |
| print(f"[deploy] demo folder missing ({demo_folder}); skipping demo") |
| return |
|
|
| demo_repo = f"{args.user}/{args.demo_space_name}" |
| _ensure_space(api, demo_repo, sdk="gradio", token=token) |
| _upload(api, demo_repo, demo_folder, token) |
| print(f"[deploy] Demo live: https://huggingface.co/spaces/{demo_repo}") |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|