Spaces:
Sleeping
Sleeping
Download scripts/deploy_hf.py from cpuai/minecraft-file-converter: direct link, hf CLI and curl.
- Browser
- Download file 4.27 kB
-
https://huggingface.co/spaces/cpuai/minecraft-file-converter/resolve/main/scripts/deploy_hf.py
- Command line
-
hf download hf://spaces/cpuai/minecraft-file-converter/scripts/deploy_hf.py
-
curl -L -o deploy_hf.py https://huggingface.co/spaces/cpuai/minecraft-file-converter/resolve/main/scripts/deploy_hf.py
4.27 kB
| """在用户指定的开发机或服务器运行;HF_TOKEN 仅从环境变量读取。""" | |
| from pathlib import Path | |
| import argparse,json,os,sys,time | |
| def main(): | |
| parser=argparse.ArgumentParser(description='发布我的世界文件转换器到 Hugging Face Docker Space') | |
| parser.add_argument('--repo',help='可选的 owner/space-name,默认当前账号/minecraft-file-converter') | |
| parser.add_argument('--private',action='store_true',help='创建私有 Space') | |
| parser.add_argument('--verify-only',action='store_true',help='仅检查已存在空间') | |
| args=parser.parse_args() | |
| token=os.environ.get('HF_TOKEN') | |
| if not token: parser.error('请先在当前进程设置 HF_TOKEN 环境变量,不要把密钥写进脚本') | |
| try: | |
| from huggingface_hub import HfApi | |
| import httpx | |
| except ImportError: parser.error('请先运行 python -m pip install huggingface_hub httpx') | |
| api=HfApi(token=token); owner=api.whoami()['name']; repo=args.repo or owner+'/minecraft-file-converter' | |
| if not args.verify_only: | |
| api.create_repo(repo,repo_type='space',space_sdk='docker',private=args.private,exist_ok=True) | |
| api.upload_folder(repo_id=repo,repo_type='space',folder_path=str(Path(__file__).resolve().parents[1]), | |
| ignore_patterns=['.venv/**','.git/**','**/__pycache__/**','.pytest_cache/**','**/*.log','.env*','test-results/**','artifacts/**'], | |
| commit_message='Deploy BlockBridge Minecraft file converter 2.1.0 with independent world conversion') | |
| print('源码已上传: https://huggingface.co/spaces/'+repo,flush=True) | |
| # 空间构建是异步过程。只在真正可访问且完成在线转换时报告部署成功。 | |
| headers={'Authorization':'Bearer '+token} | |
| client=httpx.Client(timeout=60,headers=headers,follow_redirects=True) | |
| space_url=None | |
| for attempt in range(120): | |
| info=api.space_info(repo); runtime=api.get_space_runtime(repo) | |
| stage=str(runtime.stage); print('构建状态:'+stage,flush=True) | |
| if any(x in stage for x in ['BUILD_ERROR','RUNTIME_ERROR','CONFIG_ERROR']): raise RuntimeError('Space 构建/运行失败,请查看空间日志') | |
| host=getattr(info,'host',None) | |
| if host: space_url=host if host.startswith('https://') else 'https://'+host | |
| # 重发时旧容器可能仍返回 200,必须等待本次构建完成。 | |
| if space_url and stage == 'RUNNING': | |
| try: | |
| r=client.get(space_url+'/healthz') | |
| if r.status_code==200 and r.json().get('status')=='ok': break | |
| except (httpx.HTTPError,ValueError): pass | |
| time.sleep(10) | |
| else: raise RuntimeError('等待空间启动超时;不能标记部署成功') | |
| sample=client.get(space_url+'/api/samples/bedrock'); sample.raise_for_status() | |
| upload=client.post(space_url+'/api/upload',files={'file':('online-test.mcstructure',sample.content)}); upload.raise_for_status(); key=upload.json()['job_id'] | |
| def wait_for(expected): | |
| for _ in range(120): | |
| r=client.get(space_url+'/api/jobs/'+key); r.raise_for_status(); state=r.json() | |
| if state['state']==expected: return state | |
| if state['state'] in ('error','cancelled'): raise RuntimeError('在线验收失败:'+state.get('message','')) | |
| time.sleep(2) | |
| raise RuntimeError('在线验收超时') | |
| wait_for('ready') | |
| client.post(space_url+'/api/jobs/'+key+'/convert',json={'target':'mcworld','strict':True}).raise_for_status() | |
| result=wait_for('done') | |
| artifact=client.get(space_url+'/api/jobs/'+key+'/files/converted.mcworld'); artifact.raise_for_status() | |
| if not artifact.content.startswith(b'PK'): raise RuntimeError('在线下载不是有效世界 ZIP') | |
| print(json.dumps({'deployed':True,'repo':repo,'url':space_url,'online_conversion_verified':True,'bytes':len(artifact.content),'validation':result['result']['report']['validation']},ensure_ascii=False,indent=2)) | |
| if __name__=='__main__': | |
| try: main() | |
| except Exception as e: | |
| # 不打印带认证头的 HTTP 调试信息。 | |
| print('部署未完成:'+str(e).replace(os.environ.get('HF_TOKEN','\0'),'[REDACTED]'),file=sys.stderr) | |
| raise SystemExit(1) | |