sapcedeploy / app /deploy.py
Leeflour's picture
Upload folder using huggingface_hub
b7bd3ec verified
from __future__ import annotations
import shutil, tempfile, textwrap, time
from pathlib import Path
from typing import Dict
import git
from huggingface_hub import HfApi
from huggingface_hub.errors import HfHubHTTPError
from .exceptions import (
DockerfileMissingError,
RepoCloneError,
SpaceBuildTimeoutError,
SpaceCreationError,
SpaceDeployError,
)
__all__ = [
"deploy_space",
"SpaceDeployError",
]
from .utils import _chmod_and_retry
def deploy_space(*, hf_token: str, git_repo_url: str, deploy_path: str, space_name: str, space_port: int, description: str, env_vars: Dict[str, str], private: bool) -> str:
deploy_path = deploy_path.strip(".").strip("/")
api = HfApi(token=hf_token)
try:
username = api.whoami().get("name", None)
repo_id = f"{username}/{space_name}"
api.create_repo(
repo_id=repo_id,
repo_type="space",
space_sdk="docker",
private=private,
# space_variables=[{}],
space_secrets=[{"key": k, "value": v} for k, v in env_vars.items()],
exist_ok=False,
)
except HfHubHTTPError as exc:
raise SpaceCreationError(exc) from exc
tmp = tempfile.mkdtemp(prefix="hf_space_")
try:
try:
if not deploy_path:
git.Repo.clone_from(
git_repo_url,
tmp,
depth=1,
multi_options=["--single-branch"]
)
else:
repo = git.Repo.clone_from(
git_repo_url, tmp,
depth=1,
no_checkout=True,
filter=["tree:0"],
sparse=True,
multi_options=["--single-branch"],
)
repo.git.sparse_checkout("init", "--no-cone")
repo.git.sparse_checkout("set", "--no-cone", f"/{deploy_path}/**")
repo.git.checkout()
# 平移文件到根目录
src = Path(tmp, deploy_path)
for item in src.iterdir():
shutil.move(item, tmp) # 根目录目前是空的
shutil.rmtree(src)
except git.GitCommandError as exc:
raise RepoCloneError(str(exc)) from exc
git_dir = Path(tmp, ".git")
if git_dir.exists() and git_dir.is_dir():
shutil.rmtree(git_dir, onerror=_chmod_and_retry)
if not Path(tmp, "Dockerfile").exists():
raise DockerfileMissingError()
readme = Path(tmp, "README.md")
header = (
f"---\n"
f"title: \"{space_name}\"\n"
f"emoji: \"🚀\"\n"
f"colorFrom: blue\n"
f"colorTo: green\n"
f"sdk: docker\n"
f"app_port: {space_port}\n"
f"---\n"
)
badge = (
f"### 🚀 一键部署\n"
f"[![Deploy with HFSpaceDeploy](https://img.shields.io/badge/Deploy_with-HFSpaceDeploy-green?style=social&logo=rocket)](https://github.com/kfcx/HFSpaceDeploy)\n\n"
f"本项目由[HFSpaceDeploy](https://github.com/kfcx/HFSpaceDeploy)一键部署\n"
)
readme.write_text(f"{header}\n{badge}\n{description}\n", encoding="utf-8")
api.upload_folder(folder_path=tmp, repo_id=repo_id, repo_type="space", ignore_patterns=[".git"])
finally:
shutil.rmtree(tmp, ignore_errors=True)
deadline = time.time() + 15 * 60
while time.time() < deadline:
stage = api.get_space_runtime(repo_id).stage
if stage == "RUNNING":
return f"https://huggingface.co/spaces/{repo_id}"
if stage in ("BUILD_ERROR", "CONFIG_ERROR", "RUNTIME_ERROR",):
raise SpaceDeployError("Space failed during config/build/runtime")
if stage in ("NO_APP_FILE", "STOPPED", "PAUSED", "DELETING", ):
raise SpaceDeployError("Space is currently unavailable")
time.sleep(5)
raise SpaceBuildTimeoutError()