forgeenv-source / scripts /deploy_spaces.py
akhiilll's picture
forgeenv source snapshot for training job
a15535e verified
"""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()