#!/usr/bin/env python3 """ Pre-deployment validation script Checks that the project is ready for HF deployment """ import os import sys from pathlib import Path def check_file_exists(filename, description): """Check if a file exists and return status""" if os.path.exists(filename): size = os.path.getsize(filename) print(f"✅ {filename} ({size:,} bytes) - {description}") return True else: print(f"❌ Missing: {filename} - {description}") return False def check_file_content(filename, required_content): """Check if file contains required content""" try: with open(filename, 'r', encoding='utf-8') as f: content = f.read() missing = [] for item in required_content: if item not in content: missing.append(item) if missing: print(f"⚠️ {filename} missing: {', '.join(missing)}") return False else: print(f"✅ {filename} content validated") return True except Exception as e: print(f"❌ Error reading {filename}: {e}") return False def validate_project(): """Run all validation checks""" print("Pre-Deployment Validation") print("=" * 40) all_good = True # Required files print("\n📁 File Structure Check:") required_files = [ ("docs/README.md", "HF Space configuration and docs"), ("src/app.py", "Main Gradio application"), ("src/mlx_campp.py", "MLX model implementation"), ("src/conversion_utils.py", "Conversion utilities"), ("requirements.txt", "Dependencies"), ("tests/test_converter.py", "Test suite"), (".gitignore", "Git ignore patterns"), ("docs/DEPLOYMENT_GUIDE.md", "Deployment instructions") ] for filename, desc in required_files: if not check_file_exists(filename, desc): all_good = False # Check README.md has HF Space configuration print("\n🎛️ HF Space Configuration Check:") readme_required = [ "title: CAM++ MLX Converter", "emoji: 🎤", "sdk: gradio", "app_file: app.py" ] if not check_file_content("docs/README.md", readme_required): all_good = False # Check app.py has required components print("\n⚙️ App.py Component Check:") app_required = [ "import gradio as gr", "from mlx_campp import CAMPPModel", "from conversion_utils import ConversionUtils", "def convert_model", "interface.launch()" ] if not check_file_content("src/app.py", app_required): all_good = False # Check requirements.txt has essential packages print("\n📦 Dependencies Check:") req_required = [ "mlx>=0.19.0", "gradio>=4.44.0", "huggingface_hub", "torch", "numpy" ] if not check_file_content("requirements.txt", req_required): all_good = False # Check for common issues print("\nCommon Issues Check:") # Check if any Python files have import errors try: # Try importing without actually running MLX (which might not be installed) import ast for py_file in ["src/app.py", "src/mlx_campp.py", "src/conversion_utils.py"]: try: with open(py_file, 'r') as f: ast.parse(f.read()) print(f"✅ {py_file} syntax is valid") except SyntaxError as e: print(f"❌ Syntax error in {py_file}: {e}") all_good = False except Exception as e: print(f"⚠️ Could not validate Python syntax: {e}") # File size checks print("\n📏 File Size Check:") for filename in ["src/app.py", "src/mlx_campp.py", "src/conversion_utils.py"]: if os.path.exists(filename): size = os.path.getsize(filename) if size < 1000: # Less than 1KB is suspicious print(f"⚠️ {filename} seems too small ({size} bytes)") elif size > 100000: # More than 100KB is unusual for these files print(f"⚠️ {filename} seems very large ({size} bytes)") else: print(f"✅ {filename} size looks good ({size:,} bytes)") # Check for secrets/tokens in files print("\n🔐 Security Check:") security_ok = True sensitive_patterns = ["hf_", "token", "password", "secret", "key"] for py_file in ["src/app.py", "src/mlx_campp.py", "src/conversion_utils.py"]: try: with open(py_file, 'r') as f: content = f.read().lower() for pattern in sensitive_patterns: if pattern in content and "example" not in content: # Check if it's actually a hardcoded secret lines = content.split('\n') for i, line in enumerate(lines): if pattern in line and '=' in line and len(line.split('=')[1].strip().strip('"\'')) > 10: print(f"⚠️ Possible hardcoded secret in {py_file}:{i+1}") security_ok = False break except Exception: pass if security_ok: print("✅ No hardcoded secrets detected") # Final assessment print("\n" + "=" * 40) if all_good: print("🎉 PROJECT IS READY FOR DEPLOYMENT!") print("\nNext steps:") print("1. Run: chmod +x deploy.sh && ./deploy.sh") print("2. Or follow DEPLOYMENT_GUIDE.md for manual deployment") print("3. Monitor your HF Space after deployment") return True else: print("❌ PROJECT NEEDS FIXES BEFORE DEPLOYMENT") print("\nPlease fix the issues above before deploying.") return False def show_deployment_preview(): """Show what the deployed space will look like""" print("\n🌐 Deployment Preview:") print("Your HF Space will have:") print("• URL: https://your-username-campp-mlx-converter.hf.space") print("• Title: 🎤 CAM++ MLX Converter") print("• Interface: Clean Gradio form for model conversion") print("• Features: PyTorch→MLX conversion with quantization") print("• Output: Models uploaded to mlx-community automatically") if __name__ == "__main__": print("CAM++ MLX Converter - Pre-Deployment Validation") print("=" * 50) is_valid = validate_project() if is_valid: show_deployment_preview() sys.exit(0) else: sys.exit(1)