@@ -239,11 +239,25 @@ class StudioUpgradeResponse(BaseModel):
239239@asynccontextmanager
240240async def lifespan (app : FastAPI ):
241241 """Lifespan context manager for the FastAPI application"""
242- # Create document upload directory on startup
243- #path_manager.make_dirs(path_manager.upload_dir)
242+ # Startup code
244243 os .makedirs (UPLOAD_DIR , exist_ok = True )
245244 print (f"Document upload directory created at: { UPLOAD_DIR } " )
245+
246+ # Run database migrations (init_db() already called by DatabaseManager)
247+ try :
248+ print ("Running database migrations via external script..." )
249+ result = subprocess .run (
250+ ["uv" , "run" , "python" , "run_migrations.py" ],
251+ capture_output = True ,
252+ text = True ,
253+ check = True
254+ )
255+ print (f"Migration completed: { result .stdout } " )
256+ except subprocess .CalledProcessError as e :
257+ print (f"Migration warning: { e .stderr } " )
258+
246259 yield
260+ print ("Application shutting down..." )
247261
248262
249263app = FastAPI (
@@ -338,12 +352,12 @@ def get_timeout_for_request(request: Request) -> float:
338352
339353
340354
341- @app .on_event ("startup" )
342- async def startup_event ():
343- """Check for and apply any pending migrations on startup"""
344- success , message = await alembic_manager .handle_database_upgrade ()
345- if not success :
346- print (f"Warning: { message } " )
355+ # @app.on_event("startup")
356+ # async def startup_event():
357+ # """Check for and apply any pending migrations on startup"""
358+ # success, message = await alembic_manager.handle_database_upgrade()
359+ # if not success:
360+ # print(f"Warning: {message}")
347361
348362@app .post ("/get_project_files" , include_in_schema = True , responses = responses ,
349363 description = "get project file details" )
@@ -1318,12 +1332,10 @@ async def get_example_payloads(use_case:UseCase):
13181332 return payload
13191333
13201334
1321- # Add these two endpoints
13221335@app .get ("/synthesis-studio/check-upgrade" , response_model = StudioUpgradeStatus )
13231336async def check_upgrade_status ():
13241337 """Check if any upgrades are available"""
13251338 try :
1326-
13271339 # Fetch latest changes
13281340 subprocess .run (["git" , "fetch" ], check = True , capture_output = True )
13291341
@@ -1357,39 +1369,22 @@ async def check_upgrade_status():
13571369 git_remote_commit = remote_commit ,
13581370 updates_available = updates_available
13591371 )
1372+
1373+ except subprocess .CalledProcessError as e :
1374+ raise HTTPException (status_code = 500 , detail = f"Git error: { str (e )} " )
13601375 except Exception as e :
13611376 raise HTTPException (status_code = 500 , detail = str (e ))
1362-
13631377
1364- # Ensure uv is installed
1365- def ensure_uv_installed ():
1366- try :
1367- print (subprocess .run (["uv" , "--version" ], check = True , capture_output = True ))
1368- except (subprocess .CalledProcessError , FileNotFoundError ):
1369- print (subprocess .run (["curl -LsSf https://astral.sh/uv/install.sh | sh" ], shell = True , check = True ))
1370- os .environ ["PATH" ] = f"{ os .environ ['HOME' ]} /.cargo/bin:{ os .environ ['PATH' ]} "
13711378
1372- # Setup virtual environment and dependencies
1373- def setup_environment (PROJECT_ROOT ):
1374-
1375- venv_dir = PROJECT_ROOT / ".venv"
1376-
1377- # Create venv if it doesn't exist - specifying the path explicitly
1378- if not venv_dir .exists ():
1379- print (subprocess .run (["uv" , "venv" , ".venv" ], cwd = PROJECT_ROOT , check = True ))
1380-
1381- # Install dependencies with uv pip instead of sync to avoid pyproject.toml parsing issues
1382- print (subprocess .run (["uv" , "pip" , "install" , "-e" , "." ], cwd = PROJECT_ROOT , check = True ))
13831379
13841380@app .post ("/synthesis-studio/upgrade" , response_model = StudioUpgradeResponse )
13851381async def perform_upgrade ():
13861382 """
13871383 Perform upgrade process:
13881384 1. Pull latest code
1389- 2. Run database migrations with Alembic
1390- 3. Run build_client.sh
1391- 4. Run start_application.py
1392- 5. Restart CML application
1385+ 2. Run database migrations
1386+ 3. Build frontend (includes dependency sync)
1387+ 4. Restart application
13931388 """
13941389 try :
13951390 messages = []
@@ -1398,75 +1393,65 @@ async def perform_upgrade():
13981393 db_upgraded = False
13991394
14001395 PROJECT_ROOT = Path (os .getcwd ())
1396+
14011397 # 1. Git operations
14021398 try :
1403-
14041399 # Stash any changes
1405- print ( subprocess .run (["git" , "stash" ], check = True , capture_output = True ) )
1400+ subprocess .run (["git" , "stash" ], check = True , capture_output = True )
14061401
14071402 # Pull updates
1408- print ( subprocess .run (["git" , "pull" ], check = True , capture_output = True ) )
1403+ subprocess .run (["git" , "pull" ], check = True , capture_output = True )
14091404
14101405 # Try to pop stash
14111406 try :
1412- print ( subprocess .run (["git" , "stash" , "pop" ], check = True , capture_output = True ) )
1407+ subprocess .run (["git" , "stash" , "pop" ], check = True , capture_output = True )
14131408 except subprocess .CalledProcessError :
14141409 messages .append ("Warning: Could not restore local changes" )
14151410
14161411 git_updated = True
14171412 messages .append ("Git repository updated" )
1418- print (messages )
14191413
14201414 except subprocess .CalledProcessError as e :
14211415 messages .append (f"Git update failed: { e } " )
14221416 raise HTTPException (status_code = 500 , detail = str (e ))
14231417
14241418 # 2. Database migrations
14251419 try :
1426- # In your upgrade endpoint, you can add this debug line:
1427- print (f"Current working directory: { os .getcwd ()} " )
1428- print (f"Alembic.ini exists: { os .path .exists ('alembic.ini' )} " )
1429- print ("--- Starting database migration via external script ---" )
1430- # Use `uv run` to ensure the script runs within the project's virtual environment
1431- # This is more robust than just calling 'python'
14321420 result = subprocess .run (
14331421 ["uv" , "run" , "python" , "run_migrations.py" ],
14341422 capture_output = True ,
14351423 text = True ,
1436- check = True # This will raise CalledProcessError on failure
1424+ check = True ,
1425+ cwd = PROJECT_ROOT
14371426 )
14381427
1439- print (result .stdout ) # Log the output from the script
1428+ print (result .stdout )
14401429 db_upgraded = True
1441- messages .append ("Database migration check completed successfully. " )
1442- except Exception as e :
1430+ messages .append ("Database migrations completed" )
1431+ except subprocess . CalledProcessError as e :
14431432 messages .append (f"Database migration failed: { str (e )} " )
14441433 raise HTTPException (status_code = 500 , detail = str (e ))
14451434
1446- # 3. Run build_client.sh
1435+ # 3. Build frontend ( build_client.sh handles uv and dependencies)
14471436 try :
1448-
1449- ensure_uv_installed ()
1450-
1451- setup_environment (PROJECT_ROOT )
1452-
1453- subprocess .run (["bash build/shell_scripts/build_client.sh" ], shell = True , check = True )
1437+ subprocess .run (
1438+ ["bash" , "build/shell_scripts/build_client.sh" ],
1439+ check = True ,
1440+ cwd = PROJECT_ROOT
1441+ )
14541442 frontend_rebuilt = True
14551443 messages .append ("Frontend rebuilt successfully" )
14561444 except subprocess .CalledProcessError as e :
14571445 messages .append (f"Frontend build failed: { e } " )
14581446 raise HTTPException (status_code = 500 , detail = str (e ))
14591447
1460-
1448+ # 4. Restart application
14611449 if git_updated or frontend_rebuilt or db_upgraded :
14621450 try :
1463- # Small delay to ensure logs are captured
1464- time .sleep (10 )
1465- print ("application restart will happen now" )
1451+ time .sleep (5 )
14661452 restart_application ()
14671453 messages .append ("Application restart initiated" )
14681454
1469- # Note: This response might not reach the client due to the restart
14701455 return StudioUpgradeResponse (
14711456 success = True ,
14721457 message = "; " .join (messages ),
@@ -1479,10 +1464,7 @@ async def perform_upgrade():
14791464 raise HTTPException (status_code = 500 , detail = str (e ))
14801465
14811466 except Exception as e :
1482- raise HTTPException (
1483- status_code = 500 ,
1484- detail = f"Upgrade failed: { str (e )} "
1485- )
1467+ raise HTTPException (status_code = 500 , detail = f"Upgrade failed: { str (e )} " )
14861468#****** comment below for testing just backend**************
14871469current_directory = os .path .dirname (os .path .abspath (__file__ ))
14881470client_build_path = os .path .join (current_directory , "client" , "dist" )
0 commit comments