| """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() | |