Spaces:
Build error
Build error
| #!/usr/bin/env python | |
| """ | |
| .NET Forge Ultra - CLI Management Tool | |
| Complete command-line interface for managing your reverse engineering workstation | |
| """ | |
| import argparse | |
| import os | |
| import sys | |
| import subprocess | |
| import json | |
| from pathlib import Path | |
| from datetime import datetime | |
| # Colors for terminal | |
| class Colors: | |
| HEADER = '\033[95m' | |
| OKBLUE = '\033[94m' | |
| OKCYAN = '\033[96m' | |
| OKGREEN = '\033[92m' | |
| WARNING = '\033[93m' | |
| FAIL = '\033[91m' | |
| ENDC = '\033[0m' | |
| BOLD = '\033[1m' | |
| UNDERLINE = '\033[4m' | |
| def print_header(text): | |
| print(f"\n{Colors.HEADER}{Colors.BOLD}{'='*60}{Colors.ENDC}") | |
| print(f"{Colors.HEADER}{Colors.BOLD} {text}{Colors.ENDC}") | |
| print(f"{Colors.HEADER}{Colors.BOLD}{'='*60}{Colors.ENDC}\n") | |
| def print_success(text): | |
| print(f"[OK] {text}") | |
| def print_error(text): | |
| print(f"[ERROR] {text}") | |
| def print_warning(text): | |
| print(f"[WARN] {text}") | |
| def print_info(text): | |
| print(f"[INFO] {text}") | |
| def run_command(cmd, cwd=None, check=True): | |
| """Run shell command and return result""" | |
| try: | |
| result = subprocess.run( | |
| cmd, | |
| shell=True, | |
| cwd=cwd, | |
| capture_output=True, | |
| text=True, | |
| check=check | |
| ) | |
| return result.returncode == 0, result.stdout, result.stderr | |
| except subprocess.CalledProcessError as e: | |
| return False, e.stdout or "", e.stderr or "" | |
| def check_hf_login(): | |
| """Check if logged in to HuggingFace""" | |
| try: | |
| from huggingface_hub import HfApi | |
| api = HfApi() | |
| user = api.whoami() | |
| return True, user["name"] | |
| except: | |
| return False, None | |
| def hf_login(): | |
| """Login to HuggingFace via CLI""" | |
| print_header("HuggingFace Login") | |
| print_info("Starting authentication...") | |
| print_info("If browser doesn't open, go to: https://huggingface.co/settings/tokens") | |
| print_info("Create a token and paste it below:\n") | |
| try: | |
| from huggingface_hub import login, interpreter_login | |
| interpreter_login() | |
| print_success("Logged in to HuggingFace") | |
| return True | |
| except Exception as e: | |
| print_error(f"Login failed: {e}") | |
| return False | |
| def create_space(name, sdk="gradio", hardware="cpu-basic"): | |
| """Create HuggingFace Space""" | |
| print_info(f"Creating space: {name} (SDK: {sdk}, Hardware: {hardware})") | |
| try: | |
| from huggingface_hub import create_repo | |
| create_repo( | |
| repo_id=name, | |
| repo_type="space", | |
| space_sdk=sdk, | |
| space_hardware=hardware, | |
| exist_ok=True | |
| ) | |
| print_success(f"Space created: {name}") | |
| return True | |
| except Exception as e: | |
| print_error(f"Failed to create space: {e}") | |
| return False | |
| def deploy_to_space(space_name, files, sdk="gradio"): | |
| """Deploy files to HuggingFace Space""" | |
| print_info(f"Deploying to {space_name}...") | |
| try: | |
| from huggingface_hub import upload_file | |
| for file in files: | |
| if os.path.exists(file): | |
| print_info(f"Uploading {file}...") | |
| upload_file( | |
| path_or_fileobj=file, | |
| path_in_repo=os.path.basename(file), | |
| repo_id=space_name, | |
| repo_type="space", | |
| ) | |
| print_success(f"Uploaded {file}") | |
| else: | |
| print_warning(f"File not found: {file}") | |
| return True | |
| except Exception as e: | |
| print_error(f"Deployment failed: {e}") | |
| return False | |
| def set_space_secret(space_name, key, value): | |
| """Set space secret via API""" | |
| print_info(f"Setting secret {key} for {space_name}") | |
| # Note: Secrets must be set via web UI or API with proper auth | |
| print_warning("Secrets must be set via HuggingFace web UI:") | |
| print_info(f" https://huggingface.co/spaces/{space_name}/settings") | |
| return True | |
| def check_space_status(space_name): | |
| """Check space deployment status""" | |
| print_info(f"Checking status of {space_name}...") | |
| try: | |
| from huggingface_hub import HfApi | |
| api = HfApi() | |
| space = api.space_info(space_name) | |
| print_success(f"Space exists: {space.id}") | |
| print_info(f"SDK: {space.sdk}") | |
| print_info(f"Last modified: {space.lastModified}") | |
| return True | |
| except Exception as e: | |
| print_error(f"Space not found: {e}") | |
| return False | |
| def list_spaces(): | |
| """List all user spaces""" | |
| print_header("Your HuggingFace Spaces") | |
| try: | |
| from huggingface_hub import HfApi | |
| api = HfApi() | |
| user = api.whoami() | |
| spaces = api.list_spaces(author=user["name"]) | |
| for space in spaces: | |
| print(f"\n {Colors.OKCYAN}{space.id}{Colors.ENDC}") | |
| print(f" SDK: {space.sdk}") | |
| print(f" URL: https://huggingface.co/spaces/{space.id}") | |
| return True | |
| except Exception as e: | |
| print_error(f"Failed to list spaces: {e}") | |
| return False | |
| def install_requirements(req_file): | |
| """Install Python requirements""" | |
| print_info(f"Installing requirements from {req_file}...") | |
| success, stdout, stderr = run_command(f"pip install -r {req_file}") | |
| if success: | |
| print_success("Requirements installed") | |
| return True | |
| else: | |
| print_error(f"Failed: {stderr}") | |
| return False | |
| def build_react_app(cwd): | |
| """Build React app""" | |
| print_info("Building React app...") | |
| success, stdout, stderr = run_command("npm run build", cwd=cwd) | |
| if success: | |
| print_success("Build complete") | |
| return True | |
| else: | |
| print_error(f"Build failed: {stderr}") | |
| return False | |
| def show_space_url(space_name): | |
| """Display space URL""" | |
| url = f"https://huggingface.co/spaces/{space_name}" | |
| print_header("Space URL") | |
| print(f"\n {Colors.OKGREEN}{Colors.BOLD}{url}{Colors.ENDC}\n") | |
| def revoke_token_warning(): | |
| """Show token revocation warning""" | |
| print_header("SECURITY WARNING") | |
| print(f"{Colors.FAIL}{Colors.BOLD}If you exposed a HuggingFace token:{Colors.ENDC}\n") | |
| print("1. Revoke it immediately:") | |
| print(f" {Colors.OKBLUE}https://huggingface.co/settings/tokens{Colors.ENDC}\n") | |
| print("2. Create a new token with Read permissions only") | |
| print("3. Add it to your Space secrets\n") | |
| def main(): | |
| parser = argparse.ArgumentParser( | |
| description=".NET Forge Ultra - CLI Management Tool", | |
| formatter_class=argparse.RawDescriptionHelpFormatter, | |
| epilog=""" | |
| Examples: | |
| %(prog)s login # Login to HuggingFace | |
| %(prog)s list # List your spaces | |
| %(prog)s deploy dotnet-forge-ultra | |
| %(prog)s status dotnet-forge-ultra | |
| %(prog)s install # Install requirements | |
| %(prog)s build # Build React app | |
| %(prog)s url dotnet-forge-ultra | |
| """ | |
| ) | |
| subparsers = parser.add_subparsers(dest="command", help="Commands") | |
| # Login command | |
| subparsers.add_parser("login", help="Login to HuggingFace") | |
| # List command | |
| subparsers.add_parser("list", help="List all spaces") | |
| # Deploy command | |
| deploy_parser = subparsers.add_parser("deploy", help="Deploy to space") | |
| deploy_parser.add_argument("space", help="Space name") | |
| deploy_parser.add_argument("--files", nargs="+", help="Files to upload") | |
| deploy_parser.add_argument("--sdk", default="gradio", help="Space SDK") | |
| # Status command | |
| status_parser = subparsers.add_parser("status", help="Check space status") | |
| status_parser.add_argument("space", help="Space name") | |
| # URL command | |
| url_parser = subparsers.add_parser("url", help="Show space URL") | |
| url_parser.add_argument("space", help="Space name") | |
| # Install command | |
| install_parser = subparsers.add_parser("install", help="Install requirements") | |
| install_parser.add_argument("--file", default="requirements.txt", help="Requirements file") | |
| # Build command | |
| build_parser = subparsers.add_parser("build", help="Build React app") | |
| build_parser.add_argument("--dir", help="App directory") | |
| # Security command | |
| subparsers.add_parser("security", help="Show security warnings") | |
| # Init command | |
| init_parser = subparsers.add_parser("init", help="Initialize new space") | |
| init_parser.add_argument("name", help="Space name") | |
| init_parser.add_argument("--sdk", default="gradio", help="Space SDK") | |
| init_parser.add_argument("--hardware", default="cpu-basic", help="Hardware tier") | |
| args = parser.parse_args() | |
| if args.command == "login": | |
| hf_login() | |
| elif args.command == "list": | |
| list_spaces() | |
| elif args.command == "deploy": | |
| if not check_hf_login()[0]: | |
| print_error("Not logged in. Run: forge login") | |
| sys.exit(1) | |
| files = args.files or ["app.py", "requirements.txt", "README.md"] | |
| deploy_to_space(args.space, files, args.sdk) | |
| elif args.command == "status": | |
| check_space_status(args.space) | |
| elif args.command == "url": | |
| show_space_url(args.space) | |
| elif args.command == "install": | |
| install_requirements(args.file) | |
| elif args.command == "build": | |
| build_react_app(args.dir or os.getcwd()) | |
| elif args.command == "security": | |
| revoke_token_warning() | |
| elif args.command == "init": | |
| if not check_hf_login()[0]: | |
| print_error("Not logged in. Run: forge login") | |
| sys.exit(1) | |
| create_space(args.name, args.sdk, args.hardware) | |
| else: | |
| parser.print_help() | |
| if __name__ == "__main__": | |
| main() | |