Fix Alembic migration import error in containerized environment

This commit is contained in:
Automated Action 2025-05-19 01:13:45 +00:00
parent a1c3bee298
commit 522284ce84
3 changed files with 140 additions and 11 deletions

View File

@ -6,13 +6,25 @@ from logging.config import fileConfig
from pathlib import Path
from alembic import context
# Custom module to help with finding modules in containerized environments
from alembic.find_modules import setup_python_path
from sqlalchemy import engine_from_config, pool
# Setup Python path to find app modules in various environments
setup_python_path()
# Get the directory where this script is located
current_dir = Path(__file__).resolve().parent
# Import our custom module for path setup
sys.path.insert(0, str(current_dir))
try:
from find_modules import setup_python_path
# Setup Python path to find app modules in various environments
setup_python_path()
except ImportError:
# Fallback for direct path setup if the module can't be imported
project_root = current_dir.parent
sys.path.insert(0, str(project_root))
# Check if we're in a Docker container with code mounted at /app/repo
repo_path = Path('/app/repo')
if repo_path.exists():
sys.path.insert(0, str(repo_path))
# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
@ -32,7 +44,6 @@ except ImportError:
try:
# Path-based import for some container setups
import importlib.util
import sys
# Try to find the module file
for base_path in sys.path:
@ -55,7 +66,26 @@ except ImportError:
Base = getattr(db_module, "Base")
break
else:
raise ImportError("Could not find app modules in any path")
# Try to find modules in the container-specific location
model_path = Path('/app/repo/app/models/todo.py')
db_path = Path('/app/repo/app/core/database.py')
if model_path.exists() and db_path.exists():
# Load the todo module
spec = importlib.util.spec_from_file_location("todo", model_path)
todo_module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(todo_module)
# Load the database module
spec = importlib.util.spec_from_file_location("database", db_path)
db_module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(db_module)
# Get the required objects
Todo = getattr(todo_module, "Todo")
Base = getattr(db_module, "Base")
else:
raise ImportError("Could not find app modules in any path")
except Exception as e:
print(f"Error importing models: {e}")
print(f"Current sys.path: {sys.path}")

View File

@ -20,10 +20,54 @@ def setup_python_path():
if str(project_root) not in sys.path:
sys.path.insert(0, str(project_root))
# Check if we're in a Docker container with code mounted at /app/repo
repo_path = Path('/app/repo')
if repo_path.exists() and str(repo_path) not in sys.path:
sys.path.insert(0, str(repo_path))
# Container environments often mount code in specific locations
# Check multiple possible locations
possible_repo_paths = [
Path('/app/repo'), # Common Kubernetes/Docker path
Path('/app'), # Another common Docker path
Path('/projects/simpletodoapp-ayt143') # Local development path
]
# Add all existing paths to sys.path
for repo_path in possible_repo_paths:
if repo_path.exists() and str(repo_path) not in sys.path:
sys.path.insert(0, str(repo_path))
# Debug information to help troubleshoot path issues
print(f"Python sys.path configured as: {sys.path}")
# Return the actual Python paths used, for debugging
return sys.path
def find_module_path(module_name, possible_paths=None):
"""
Try to find a module by checking multiple possible locations.
Returns the full path to the module if found, None otherwise.
Args:
module_name: Name of the module to find (e.g. 'app.models.todo')
possible_paths: List of base paths to check
Returns:
Path object if module found, None otherwise
"""
if possible_paths is None:
possible_paths = sys.path
module_parts = module_name.split('.')
for base_path in possible_paths:
path = Path(base_path)
for part in module_parts:
path = path / part
py_path = path.with_suffix('.py')
init_path = path / '__init__.py'
if py_path.exists():
return py_path
elif init_path.exists():
return init_path
return None

55
test_migrations.py Normal file
View File

@ -0,0 +1,55 @@
"""
Test script to verify that Alembic migrations will work in the container environment.
"""
import os
import sys
from pathlib import Path
print(f"Current working directory: {os.getcwd()}")
print(f"Initial Python path: {sys.path}")
# Simulate the container environment where alembic is executed
repo_dir = Path('/app/repo')
if not repo_dir.exists():
print(f"Simulating the /app/repo directory structure (not found on disk)")
# Just for testing, we'll use the current directory
repo_dir = Path(os.getcwd())
# Get paths for important files
alembic_dir = repo_dir / 'alembic'
env_py = alembic_dir / 'env.py'
find_modules_py = alembic_dir / 'find_modules.py'
print(f"Alembic directory: {alembic_dir}")
print(f"env.py exists: {env_py.exists()}")
print(f"find_modules.py exists: {find_modules_py.exists()}")
# Add alembic directory to Python path
if str(alembic_dir) not in sys.path:
sys.path.insert(0, str(alembic_dir))
print(f"Added alembic directory to sys.path: {sys.path}")
# Try to import our module
try:
from find_modules import setup_python_path
print(f"Successfully imported setup_python_path from find_modules")
# Try to set up the Python path
paths = setup_python_path()
print(f"Updated Python path: {paths}")
# Try to import our models
try:
from app.models import Todo
print(f"Successfully imported Todo model: {Todo}")
from app.core.database import Base
print(f"Successfully imported Base from database module: {Base}")
print("Migration imports should work correctly!")
except ImportError as e:
print(f"Error importing app modules: {e}")
print("You may need to run this script from the project root directory.")
except ImportError as e:
print(f"Error importing find_modules: {e}")
print("Make sure you're running this script from the project root directory.")