File size: 6,710 Bytes
368806f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
#!/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)