JHyeok5 commited on
Commit
01057f3
·
verified ·
1 Parent(s): 9f8f4a9

Upload folder using huggingface_hub

Browse files
Dockerfile CHANGED
@@ -13,5 +13,9 @@ COPY . .
13
  # Expose port (HuggingFace Spaces uses 7860)
14
  EXPOSE 7860
15
 
 
 
 
 
16
  # Run the application
17
  CMD ["uvicorn", "server:app", "--host", "0.0.0.0", "--port", "7860"]
 
13
  # Expose port (HuggingFace Spaces uses 7860)
14
  EXPOSE 7860
15
 
16
+ # Health check for container orchestrators
17
+ HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
18
+ CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:7860/health')" || exit 1
19
+
20
  # Run the application
21
  CMD ["uvicorn", "server:app", "--host", "0.0.0.0", "--port", "7860"]
db/supabase_client.py CHANGED
@@ -14,7 +14,7 @@ load_dotenv()
14
 
15
  # 환경변수 이름 매핑 (서버용 우선, VITE_* 폴백)
16
  SUPABASE_URL = os.getenv("SUPABASE_URL") or os.getenv("VITE_SUPABASE_URL")
17
- SUPABASE_SERVICE_KEY = os.getenv("SUPABASE_SERVICE_ROLE_KEY") or os.getenv("SUPABASE_SERVICE_KEY")
18
 
19
  _supabase_client: Optional[Client] = None
20
 
@@ -24,9 +24,9 @@ def get_supabase() -> Client:
24
  global _supabase_client
25
 
26
  if _supabase_client is None:
27
- if not SUPABASE_URL or not SUPABASE_SERVICE_KEY:
28
  raise ValueError("SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY must be set")
29
- _supabase_client = create_client(SUPABASE_URL, SUPABASE_SERVICE_KEY)
30
 
31
  return _supabase_client
32
 
 
14
 
15
  # 환경변수 이름 매핑 (서버용 우선, VITE_* 폴백)
16
  SUPABASE_URL = os.getenv("SUPABASE_URL") or os.getenv("VITE_SUPABASE_URL")
17
+ SUPABASE_SERVICE_ROLE_KEY = os.getenv("SUPABASE_SERVICE_ROLE_KEY")
18
 
19
  _supabase_client: Optional[Client] = None
20
 
 
24
  global _supabase_client
25
 
26
  if _supabase_client is None:
27
+ if not SUPABASE_URL or not SUPABASE_SERVICE_ROLE_KEY:
28
  raise ValueError("SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY must be set")
29
+ _supabase_client = create_client(SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY)
30
 
31
  return _supabase_client
32
 
routers/health.py CHANGED
@@ -395,7 +395,7 @@ async def _check_supabase() -> DependencyStatus:
395
 
396
  # 설정 확인
397
  supabase_url = os.getenv("SUPABASE_URL") or os.getenv("VITE_SUPABASE_URL")
398
- supabase_key = os.getenv("SUPABASE_SERVICE_ROLE_KEY") or os.getenv("SUPABASE_SERVICE_KEY")
399
 
400
  if not supabase_url or not supabase_key:
401
  return DependencyStatus(
 
395
 
396
  # 설정 확인
397
  supabase_url = os.getenv("SUPABASE_URL") or os.getenv("VITE_SUPABASE_URL")
398
+ supabase_key = os.getenv("SUPABASE_SERVICE_ROLE_KEY")
399
 
400
  if not supabase_url or not supabase_key:
401
  return DependencyStatus(
routers/models.py CHANGED
@@ -6,7 +6,7 @@ course.py에서 분리 (리팩토링)
6
  """
7
  import logging
8
  from datetime import datetime
9
- from typing import Optional, List, Dict, Any
10
 
11
  from pydantic import BaseModel, Field, field_validator
12
 
@@ -410,7 +410,7 @@ class QuickCourseCard(BaseModel):
410
  spots_preview: List[SpotPreview]
411
  estimated_minutes: int
412
  estimated_distance_km: float
413
- difficulty: str = "light"
414
  tags: List[str] = []
415
  spot_ids: List[str] = []
416
 
@@ -474,7 +474,7 @@ class TrendingCourseCard(BaseModel):
474
  spots_preview: List[TrendingSpotPreview]
475
  estimated_minutes: int
476
  estimated_distance_km: float
477
- difficulty: str = "light"
478
  tags: List[str] = []
479
  spot_ids: List[str] = []
480
  generated_at: str
 
6
  """
7
  import logging
8
  from datetime import datetime
9
+ from typing import Optional, List, Dict, Any, Literal
10
 
11
  from pydantic import BaseModel, Field, field_validator
12
 
 
410
  spots_preview: List[SpotPreview]
411
  estimated_minutes: int
412
  estimated_distance_km: float
413
+ difficulty: Literal["light", "moderate", "active"] = "light"
414
  tags: List[str] = []
415
  spot_ids: List[str] = []
416
 
 
474
  spots_preview: List[TrendingSpotPreview]
475
  estimated_minutes: int
476
  estimated_distance_km: float
477
+ difficulty: Literal["light", "moderate", "active"] = "light"
478
  tags: List[str] = []
479
  spot_ids: List[str] = []
480
  generated_at: str
scripts/run_trend_engine.py CHANGED
@@ -57,7 +57,7 @@ logger = logging.getLogger("trend_engine.orchestrator")
57
 
58
  def _get_supabase_client():
59
  url = os.environ.get("SUPABASE_URL") or os.environ.get("VITE_SUPABASE_URL")
60
- key = os.environ.get("SUPABASE_SERVICE_ROLE_KEY") or os.environ.get("SUPABASE_SERVICE_KEY")
61
  if not url or not key:
62
  raise ValueError("SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY must be set")
63
  return create_client(url, key)
 
57
 
58
  def _get_supabase_client():
59
  url = os.environ.get("SUPABASE_URL") or os.environ.get("VITE_SUPABASE_URL")
60
+ key = os.environ.get("SUPABASE_SERVICE_ROLE_KEY")
61
  if not url or not key:
62
  raise ValueError("SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY must be set")
63
  return create_client(url, key)
server.py CHANGED
@@ -151,14 +151,20 @@ app = FastAPI(
151
  )
152
 
153
  # CORS 설정 - 프로덕션 환경에서는 특정 도메인만 허용
154
- ALLOWED_ORIGINS = [
155
- "http://localhost:5173",
156
- "http://localhost:3000",
157
- "http://127.0.0.1:5173",
158
- "http://127.0.0.1:3000",
159
- "https://aewol-ai-gemini-v2.netlify.app",
160
- "https://aewol-replay.netlify.app",
161
- ]
 
 
 
 
 
 
162
 
163
  app.add_middleware(
164
  CORSMiddleware,
 
151
  )
152
 
153
  # CORS 설정 - 프로덕션 환경에서는 특정 도메인만 허용
154
+ if IS_PRODUCTION:
155
+ ALLOWED_ORIGINS = [
156
+ "https://aewol-ai-gemini-v2.netlify.app",
157
+ "https://aewol-replay.netlify.app",
158
+ ]
159
+ else:
160
+ ALLOWED_ORIGINS = [
161
+ "http://localhost:5173",
162
+ "http://localhost:3000",
163
+ "http://127.0.0.1:5173",
164
+ "http://127.0.0.1:3000",
165
+ "https://aewol-ai-gemini-v2.netlify.app",
166
+ "https://aewol-replay.netlify.app",
167
+ ]
168
 
169
  app.add_middleware(
170
  CORSMiddleware,
tests/test_job_manager.py CHANGED
@@ -1,6 +1,6 @@
1
  """
2
  Tests for job_manager module
3
- Note: These tests require SUPABASE_URL and SUPABASE_SERVICE_KEY to be set
4
  """
5
  import pytest
6
  import asyncio
@@ -14,7 +14,7 @@ from lib.supabase_client import get_supabase_client, reset_supabase_client
14
  def test_job_id():
15
  """Create a test job and return its ID"""
16
  # Skip if Supabase credentials not available
17
- if not os.getenv("SUPABASE_URL") or not os.getenv("SUPABASE_SERVICE_KEY"):
18
  pytest.skip("Supabase credentials not configured")
19
 
20
  supabase = get_supabase_client()
@@ -115,18 +115,18 @@ def test_missing_credentials():
115
  """Test handling of missing Supabase credentials"""
116
  # Clear env vars
117
  original_url = os.getenv("SUPABASE_URL")
118
- original_key = os.getenv("SUPABASE_SERVICE_KEY")
119
 
120
  os.environ.pop("SUPABASE_URL", None)
121
- os.environ.pop("SUPABASE_SERVICE_KEY", None)
122
  reset_supabase_client()
123
 
124
- with pytest.raises(ValueError, match="SUPABASE_URL and SUPABASE_SERVICE_KEY must be set"):
125
  get_supabase_client()
126
 
127
  # Restore
128
  if original_url:
129
  os.environ["SUPABASE_URL"] = original_url
130
  if original_key:
131
- os.environ["SUPABASE_SERVICE_KEY"] = original_key
132
  reset_supabase_client()
 
1
  """
2
  Tests for job_manager module
3
+ Note: These tests require SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY to be set
4
  """
5
  import pytest
6
  import asyncio
 
14
  def test_job_id():
15
  """Create a test job and return its ID"""
16
  # Skip if Supabase credentials not available
17
+ if not os.getenv("SUPABASE_URL") or not os.getenv("SUPABASE_SERVICE_ROLE_KEY"):
18
  pytest.skip("Supabase credentials not configured")
19
 
20
  supabase = get_supabase_client()
 
115
  """Test handling of missing Supabase credentials"""
116
  # Clear env vars
117
  original_url = os.getenv("SUPABASE_URL")
118
+ original_key = os.getenv("SUPABASE_SERVICE_ROLE_KEY")
119
 
120
  os.environ.pop("SUPABASE_URL", None)
121
+ os.environ.pop("SUPABASE_SERVICE_ROLE_KEY", None)
122
  reset_supabase_client()
123
 
124
+ with pytest.raises(ValueError, match="SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY must be set"):
125
  get_supabase_client()
126
 
127
  # Restore
128
  if original_url:
129
  os.environ["SUPABASE_URL"] = original_url
130
  if original_key:
131
+ os.environ["SUPABASE_SERVICE_ROLE_KEY"] = original_key
132
  reset_supabase_client()
trend_engine/place_extractor.py CHANGED
@@ -67,7 +67,7 @@ ADDRESS_PATTERNS = [
67
 
68
  def _get_supabase_client() -> Client:
69
  url = os.environ.get("SUPABASE_URL") or os.environ.get("VITE_SUPABASE_URL")
70
- key = os.environ.get("SUPABASE_SERVICE_ROLE_KEY") or os.environ.get("SUPABASE_SERVICE_KEY")
71
  if not url or not key:
72
  raise ValueError("SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY must be set")
73
  return create_client(url, key)
 
67
 
68
  def _get_supabase_client() -> Client:
69
  url = os.environ.get("SUPABASE_URL") or os.environ.get("VITE_SUPABASE_URL")
70
+ key = os.environ.get("SUPABASE_SERVICE_ROLE_KEY")
71
  if not url or not key:
72
  raise ValueError("SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY must be set")
73
  return create_client(url, key)
trend_engine/spot_matcher.py CHANGED
@@ -32,7 +32,7 @@ SYSTEM_NAME_PATTERNS = [
32
 
33
  def _get_supabase_client() -> Client:
34
  url = os.environ.get("SUPABASE_URL") or os.environ.get("VITE_SUPABASE_URL")
35
- key = os.environ.get("SUPABASE_SERVICE_ROLE_KEY") or os.environ.get("SUPABASE_SERVICE_KEY")
36
  if not url or not key:
37
  raise ValueError("SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY must be set")
38
  return create_client(url, key)
 
32
 
33
  def _get_supabase_client() -> Client:
34
  url = os.environ.get("SUPABASE_URL") or os.environ.get("VITE_SUPABASE_URL")
35
+ key = os.environ.get("SUPABASE_SERVICE_ROLE_KEY")
36
  if not url or not key:
37
  raise ValueError("SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY must be set")
38
  return create_client(url, key)
trend_engine/trend_scorer.py CHANGED
@@ -31,7 +31,7 @@ CHANNEL_WEIGHTS: dict[str, float] = {
31
 
32
  def _get_supabase_client() -> Client:
33
  url = os.environ.get("SUPABASE_URL") or os.environ.get("VITE_SUPABASE_URL")
34
- key = os.environ.get("SUPABASE_SERVICE_ROLE_KEY") or os.environ.get("SUPABASE_SERVICE_KEY")
35
  if not url or not key:
36
  raise ValueError("SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY must be set")
37
  return create_client(url, key)
 
31
 
32
  def _get_supabase_client() -> Client:
33
  url = os.environ.get("SUPABASE_URL") or os.environ.get("VITE_SUPABASE_URL")
34
+ key = os.environ.get("SUPABASE_SERVICE_ROLE_KEY")
35
  if not url or not key:
36
  raise ValueError("SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY must be set")
37
  return create_client(url, key)
utils/env_validator.py CHANGED
@@ -267,8 +267,7 @@ def validate_backend_env() -> Dict[str, Any]:
267
  is_api_key=True
268
  )
269
  if not supabase_service_key:
270
- # Fallback
271
- validator.require("SUPABASE_SERVICE_KEY", "Supabase 서비스 키 (대체)", is_api_key=True)
272
 
273
  # ===== 선택적 환경 변수 =====
274
 
@@ -303,7 +302,7 @@ def print_env_summary():
303
 
304
  # Supabase
305
  supabase_url = os.getenv("SUPABASE_URL") or os.getenv("VITE_SUPABASE_URL")
306
- supabase_key = os.getenv("SUPABASE_SERVICE_ROLE_KEY") or os.getenv("SUPABASE_SERVICE_KEY")
307
  logger.info(f"Supabase URL: {'✅ Configured' if supabase_url else '❌ Not configured'}")
308
  logger.info(f"Supabase Key: {'✅ Configured' if supabase_key else '❌ Not configured'}")
309
 
 
267
  is_api_key=True
268
  )
269
  if not supabase_service_key:
270
+ validator.errors.append("❌ 'SUPABASE_SERVICE_ROLE_KEY' is required but not set")
 
271
 
272
  # ===== 선택적 환경 변수 =====
273
 
 
302
 
303
  # Supabase
304
  supabase_url = os.getenv("SUPABASE_URL") or os.getenv("VITE_SUPABASE_URL")
305
+ supabase_key = os.getenv("SUPABASE_SERVICE_ROLE_KEY")
306
  logger.info(f"Supabase URL: {'✅ Configured' if supabase_url else '❌ Not configured'}")
307
  logger.info(f"Supabase Key: {'✅ Configured' if supabase_key else '❌ Not configured'}")
308