Spaces:
Paused
Paused
Update app.py
Browse files
app.py
CHANGED
@@ -854,235 +854,6 @@ def handle_deploy(code, deploy_status):
|
|
854 |
}
|
855 |
|
856 |
|
857 |
-
#################################################
|
858 |
-
# 3) deploy_result = gr.HTML(unsafe_allow_html=True)
|
859 |
-
#################################################
|
860 |
-
deploy_result_container = gr.HTML(
|
861 |
-
"""
|
862 |
-
<div class="deploy-section">
|
863 |
-
<div class="deploy-header">📤 배포 결과</div>
|
864 |
-
<div id="deploy-result-box" class="deploy-result-box">
|
865 |
-
<div class="no-deploy">아직 배포된 게임이 없습니다.</div>
|
866 |
-
</div>
|
867 |
-
</div>
|
868 |
-
""",
|
869 |
-
unsafe_allow_html=True # <--- 핵심: 스크립트 실행 허용
|
870 |
-
)
|
871 |
-
|
872 |
-
|
873 |
-
#################################################
|
874 |
-
# 4) deploy_btn 클릭 이벤트
|
875 |
-
#################################################
|
876 |
-
deploy_btn.click(
|
877 |
-
fn=handle_deploy,
|
878 |
-
inputs=[code_output, deploy_status],
|
879 |
-
outputs=[deploy_result_container, deploy_status]
|
880 |
-
)
|
881 |
-
###############################################
|
882 |
-
# 1) deploy_to_vercel 함수 (로깅 및 HTML 반환)
|
883 |
-
###############################################
|
884 |
-
def deploy_to_vercel(code: str):
|
885 |
-
print("[DEBUG] deploy_to_vercel() 시작. code 길이:", len(code) if code else 0)
|
886 |
-
try:
|
887 |
-
if not code or len(code.strip()) < 10:
|
888 |
-
print("[DEBUG] code가 짧아서 배포할 수 없음.")
|
889 |
-
return """
|
890 |
-
<div style='color:red; padding:10px; border:1px solid red; border-radius:5px;'>
|
891 |
-
배포할 코드가 없습니다. 먼저 게임 코드를 생성해주세요.
|
892 |
-
</div>
|
893 |
-
<script>console.log('[DEBUG] 배포 실패: code가 너무 짧습니다.');</script>
|
894 |
-
"""
|
895 |
-
|
896 |
-
token = "A8IFZmgW2cqA4yUNlLPnci0N"
|
897 |
-
if not token:
|
898 |
-
print("[DEBUG] Vercel 토큰이 없음.")
|
899 |
-
return """
|
900 |
-
<div style='color:red; padding:10px; border:1px solid red; border-radius:5px;'>
|
901 |
-
Vercel 토큰이 설정되지 않았습니다.
|
902 |
-
</div>
|
903 |
-
<script>console.log('[DEBUG] 배포 실패: Vercel 토큰 없음');</script>
|
904 |
-
"""
|
905 |
-
|
906 |
-
project_name = ''.join(random.choice(string.ascii_lowercase) for i in range(6))
|
907 |
-
deploy_url = "https://api.vercel.com/v13/deployments"
|
908 |
-
print(f"[DEBUG] 생성된 project_name: {project_name}")
|
909 |
-
|
910 |
-
headers = {
|
911 |
-
"Authorization": f"Bearer {token}",
|
912 |
-
"Content-Type": "application/json"
|
913 |
-
}
|
914 |
-
package_json = {
|
915 |
-
"name": project_name,
|
916 |
-
"version": "1.0.0",
|
917 |
-
"private": True,
|
918 |
-
"dependencies": {"vite": "^5.0.0"},
|
919 |
-
"scripts": {
|
920 |
-
"dev": "vite",
|
921 |
-
"build": "echo 'No build needed' && mkdir -p dist && cp index.html dist/",
|
922 |
-
"preview": "vite preview"
|
923 |
-
}
|
924 |
-
}
|
925 |
-
files = [
|
926 |
-
{"file": "index.html", "data": code},
|
927 |
-
{"file": "package.json", "data": json.dumps(package_json, indent=2)}
|
928 |
-
]
|
929 |
-
project_settings = {
|
930 |
-
"buildCommand": "npm run build",
|
931 |
-
"outputDirectory": "dist",
|
932 |
-
"installCommand": "npm install",
|
933 |
-
"framework": None
|
934 |
-
}
|
935 |
-
deploy_data = {
|
936 |
-
"name": project_name,
|
937 |
-
"files": files,
|
938 |
-
"target": "production",
|
939 |
-
"projectSettings": project_settings
|
940 |
-
}
|
941 |
-
|
942 |
-
print("[DEBUG] Vercel API 요청 전송중...")
|
943 |
-
deploy_response = requests.post(deploy_url, headers=headers, json=deploy_data)
|
944 |
-
print("[DEBUG] 응답 status_code:", deploy_response.status_code)
|
945 |
-
print("[DEBUG] 응답 body:", deploy_response.text[:300], "..." if len(deploy_response.text) > 300 else "")
|
946 |
-
|
947 |
-
if deploy_response.status_code != 200:
|
948 |
-
return f"""
|
949 |
-
<div style='color:red; padding:10px; border:1px solid red; border-radius:5px;'>
|
950 |
-
배포 실패: {html.escape(deploy_response.text)}
|
951 |
-
</div>
|
952 |
-
<script>console.log('[DEBUG] 배포 실패: {html.escape(deploy_response.text)}');</script>
|
953 |
-
"""
|
954 |
-
|
955 |
-
deployment_url = f"https://{project_name}.vercel.app"
|
956 |
-
print("[DEBUG] 배포 성공 추정. 3초 대기 후 최종 안내...")
|
957 |
-
time.sleep(3)
|
958 |
-
|
959 |
-
success_html = f"""
|
960 |
-
<div style='padding: 15px; background-color: #f0fff4; border: 1px solid #34c759; border-radius: 8px;'>
|
961 |
-
<h3 style='margin-top: 0; color: #34c759;'>✅ 배포 완료!</h3>
|
962 |
-
<p>게임이 성공적으로 배포되었습니다.</p>
|
963 |
-
<div style='margin-top: 10px; padding: 10px; background: #f8fafc; border-radius: 6px; display: flex; justify-content: space-between; align-items: center;'>
|
964 |
-
<a href="{deployment_url}" target="_blank" style='color: #0066cc; text-decoration: none; word-break: break-all;'>{deployment_url}</a>
|
965 |
-
<button onclick="navigator.clipboard.writeText('{deployment_url}')" style='background: #0066cc; color: white; border: none; border-radius: 4px; padding: 5px 10px; cursor: pointer;'>복사</button>
|
966 |
-
</div>
|
967 |
-
</div>
|
968 |
-
<script>
|
969 |
-
console.log('[DEBUG] 배포 성공, deployment_url: {deployment_url}');
|
970 |
-
showDeployBanner('success','✅ 배포 완료!','게임이 성공적으로 배포되었습니다.','{deployment_url}');
|
971 |
-
document.getElementById('deploy-result-box').innerHTML = `
|
972 |
-
<div class="deploy-success">
|
973 |
-
<div class="success-icon">✅</div>
|
974 |
-
<div class="success-message">배포 완료!</div>
|
975 |
-
<div class="url-box">
|
976 |
-
<a href="{deployment_url}" target="_blank">{deployment_url}</a>
|
977 |
-
<button class="copy-btn" onclick="navigator.clipboard.writeText('{deployment_url}')">복사</button>
|
978 |
-
</div>
|
979 |
-
</div>
|
980 |
-
`;
|
981 |
-
</script>
|
982 |
-
"""
|
983 |
-
print("[DEBUG] 최종 리턴 HTML 생성 완료")
|
984 |
-
return success_html
|
985 |
-
|
986 |
-
except Exception as e:
|
987 |
-
print("[ERROR] deploy_to_vercel() 예외:", e)
|
988 |
-
return f"""
|
989 |
-
<div style='color:red; padding:10px; border:1px solid red; border-radius:5px;'>
|
990 |
-
오류 발생: {html.escape(str(e))}
|
991 |
-
</div>
|
992 |
-
<script>
|
993 |
-
console.log('[DEBUG] deploy_to_vercel 내부 예외: {html.escape(str(e))}');
|
994 |
-
showDeployBanner('error','⚠️ 시스템 오류','{html.escape(str(e))}');
|
995 |
-
</script>
|
996 |
-
"""
|
997 |
-
|
998 |
-
|
999 |
-
###############################################
|
1000 |
-
# 2) handle_deploy 함수 (로깅 + 반환 HTML)
|
1001 |
-
###############################################
|
1002 |
-
def handle_deploy(code, deploy_status):
|
1003 |
-
print("[DEBUG] handle_deploy() 함수가 호출되었습니다.")
|
1004 |
-
print("[DEBUG] 전달된 code:", repr(code[:300] if code else code))
|
1005 |
-
|
1006 |
-
if not code:
|
1007 |
-
js_code = """
|
1008 |
-
<script>
|
1009 |
-
console.log('[DEBUG] 배포할 코드가 없어 에러 처리');
|
1010 |
-
showDeployBanner('error', '⚠️ 배포 실패', '배포할 코드가 없습니다. 먼저 게임 코드를 생성해주세요.');
|
1011 |
-
document.getElementById('deploy-result-box').innerHTML = `
|
1012 |
-
<div class="deploy-error">
|
1013 |
-
<div class="error-icon">⚠️</div>
|
1014 |
-
<div class="error-message">배포할 코드가 없습니다.</div>
|
1015 |
-
</div>
|
1016 |
-
`;
|
1017 |
-
</script>
|
1018 |
-
"""
|
1019 |
-
print("[DEBUG] code가 없으므로 에러 HTML 반환")
|
1020 |
-
return js_code, {
|
1021 |
-
"is_deployed": False,
|
1022 |
-
"status": "error",
|
1023 |
-
"message": "배포할 코드가 없습니다.",
|
1024 |
-
"url": ""
|
1025 |
-
}
|
1026 |
-
|
1027 |
-
try:
|
1028 |
-
print("[DEBUG] 배포 로딩 상태 HTML 생성 중...")
|
1029 |
-
clean_code = remove_code_block(code)
|
1030 |
-
print("[DEBUG] remove_code_block 후 clean_code 길이:", len(clean_code))
|
1031 |
-
|
1032 |
-
print("[DEBUG] deploy_to_vercel() 호출 시작")
|
1033 |
-
result_html = deploy_to_vercel(clean_code)
|
1034 |
-
print("[DEBUG] deploy_to_vercel() 결과 수신:")
|
1035 |
-
print(result_html[:500], "..." if len(result_html) > 500 else "")
|
1036 |
-
|
1037 |
-
debug_injection = """
|
1038 |
-
<script>
|
1039 |
-
console.log('[DEBUG] 배포 후 결과 HTML:', %s);
|
1040 |
-
</script>
|
1041 |
-
""" % (json.dumps(result_html[:300]) if len(result_html) > 300 else json.dumps(result_html))
|
1042 |
-
|
1043 |
-
final_html = result_html + debug_injection
|
1044 |
-
|
1045 |
-
if "✅ 배포 완료!" in result_html:
|
1046 |
-
print("[DEBUG] 배포 성공으로 판단")
|
1047 |
-
return final_html, {
|
1048 |
-
"is_deployed": True,
|
1049 |
-
"status": "success",
|
1050 |
-
"url": "",
|
1051 |
-
"message": "배포 성공"
|
1052 |
-
}
|
1053 |
-
else:
|
1054 |
-
print("[DEBUG] 배포 실패 또는 오류")
|
1055 |
-
return final_html, {
|
1056 |
-
"is_deployed": False,
|
1057 |
-
"status": "error",
|
1058 |
-
"url": "",
|
1059 |
-
"message": "배포 실패"
|
1060 |
-
}
|
1061 |
-
|
1062 |
-
except Exception as e:
|
1063 |
-
error_msg = str(e)
|
1064 |
-
print("[ERROR] handle_deploy에서 예외 발생:", error_msg)
|
1065 |
-
exception_js = f"""
|
1066 |
-
<script>
|
1067 |
-
console.log('[DEBUG] handle_deploy 예외: {error_msg}');
|
1068 |
-
showDeployBanner('error', '⚠️ 시스템 오류', '{error_msg}');
|
1069 |
-
document.getElementById('deploy-result-box').innerHTML = `
|
1070 |
-
<div class="deploy-error">
|
1071 |
-
<div class="error-icon">⚠️</div>
|
1072 |
-
<div class="error-message">시스템 오류: {error_msg}</div>
|
1073 |
-
</div>
|
1074 |
-
`;
|
1075 |
-
</script>
|
1076 |
-
"""
|
1077 |
-
return exception_js, {
|
1078 |
-
"is_deployed": False,
|
1079 |
-
"status": "error",
|
1080 |
-
"message": error_msg,
|
1081 |
-
"url": ""
|
1082 |
-
}
|
1083 |
-
|
1084 |
-
|
1085 |
-
|
1086 |
# ------------------------
|
1087 |
# 8) Gradio / Modelscope UI 빌드
|
1088 |
# ------------------------
|
|
|
854 |
}
|
855 |
|
856 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
857 |
# ------------------------
|
858 |
# 8) Gradio / Modelscope UI 빌드
|
859 |
# ------------------------
|