diff --git a/Dockerfile b/Dockerfile index 49bb29445..9e4f83d56 100644 --- a/Dockerfile +++ b/Dockerfile @@ -34,10 +34,6 @@ COPY README.md pyproject.toml uv.lock entrypoint.sh ./ RUN --mount=type=cache,target=/root/.cache/uv \ uv sync --extra debug --extra api --extra postgres --extra neo4j --extra llama-index --extra ollama --extra mistral --extra groq --extra anthropic --extra chromadb --frozen --no-install-project --no-dev --no-editable -# Copy Alembic configuration -COPY alembic.ini /app/alembic.ini -COPY alembic/ /app/alembic - # Then, add the rest of the project source code and install it # Installing separately from its dependencies allows optimal layer caching COPY ./cognee /app/cognee diff --git a/cognee-mcp/Dockerfile b/cognee-mcp/Dockerfile index 6608102c8..cf30466df 100644 --- a/cognee-mcp/Dockerfile +++ b/cognee-mcp/Dockerfile @@ -34,8 +34,8 @@ RUN --mount=type=cache,target=/root/.cache/uv \ uv sync --frozen --no-install-project --no-dev --no-editable # Copy Alembic configuration -COPY alembic.ini /app/alembic.ini -COPY alembic/ /app/alembic +COPY cognee/alembic.ini /app/cognee/alembic.ini +COPY cognee/alembic/ /app/cognee/alembic # Then, add the rest of the project source code and install it # Installing separately from its dependencies allows optimal layer caching diff --git a/cognee-mcp/entrypoint.sh b/cognee-mcp/entrypoint.sh index b4df5ba00..60b6ad459 100644 --- a/cognee-mcp/entrypoint.sh +++ b/cognee-mcp/entrypoint.sh @@ -56,24 +56,22 @@ if [ -n "$API_URL" ]; then echo "Skipping database migrations (API server handles its own database)" else echo "Direct mode: Using local cognee instance" - # Run Alembic migrations with proper error handling. - # Note on UserAlreadyExists error handling: - # During database migrations, we attempt to create a default user. If this user - # already exists (e.g., from a previous deployment or migration), it's not a - # critical error and shouldn't prevent the application from starting. This is - # different from other migration errors which could indicate database schema - # inconsistencies and should cause the startup to fail. This check allows for - # smooth redeployments and container restarts while maintaining data integrity. echo "Running database migrations..." - MIGRATION_OUTPUT=$(alembic upgrade head) + set +e # Disable exit on error to handle specific migration errors + MIGRATION_OUTPUT=$(cd cognee && alembic upgrade head) MIGRATION_EXIT_CODE=$? + set -e if [[ $MIGRATION_EXIT_CODE -ne 0 ]]; then - if [[ "$MIGRATION_OUTPUT" == *"UserAlreadyExists"* ]] || [[ "$MIGRATION_OUTPUT" == *"User default_user@example.com already exists"* ]]; then - echo "Warning: Default user already exists, continuing startup..." - else - echo "Migration failed with unexpected error." + + echo "Migration failed with unexpected error. Trying to run Cognee without migrations." + echo "Initializing database tables..." + python /app/src/run_cognee_database_setup.py + INIT_EXIT_CODE=$? + + if [[ $INIT_EXIT_CODE -ne 0 ]]; then + echo "Database initialization failed!" exit 1 fi fi diff --git a/cognee-mcp/pyproject.toml b/cognee-mcp/pyproject.toml index 27b80e72e..03b8c448e 100644 --- a/cognee-mcp/pyproject.toml +++ b/cognee-mcp/pyproject.toml @@ -8,7 +8,6 @@ requires-python = ">=3.10" dependencies = [ # For local cognee repo usage remove comment bellow and add absolute path to cognee. Then run `uv sync --reinstall` in the mcp folder on local cognee changes. #"cognee[postgres,codegraph,gemini,huggingface,docs,neo4j] @ file:/Users/igorilic/Desktop/cognee", - # TODO: Remove gemini from optional dependecnies for new Cognee version after 0.3.4 "cognee[postgres,docs,neo4j]==0.5.0", "fastmcp>=2.10.0,<3.0.0", "mcp>=1.12.0,<2.0.0", diff --git a/cognee-mcp/src/run_cognee_database_setup.py b/cognee-mcp/src/run_cognee_database_setup.py new file mode 100644 index 000000000..e0ac91ec4 --- /dev/null +++ b/cognee-mcp/src/run_cognee_database_setup.py @@ -0,0 +1,5 @@ +from cognee.modules.engine.operations.setup import setup +import asyncio + +if __name__ == "__main__": + asyncio.run(setup()) diff --git a/cognee-mcp/src/server.py b/cognee-mcp/src/server.py index 5a0515436..fc745b24b 100755 --- a/cognee-mcp/src/server.py +++ b/cognee-mcp/src/server.py @@ -892,26 +892,11 @@ async def main(): await setup() - # Run Alembic migrations from the main cognee directory where alembic.ini is located + # Run Cognee migrations logger.info("Running database migrations...") - migration_result = subprocess.run( - ["python", "-m", "alembic", "upgrade", "head"], - capture_output=True, - text=True, - cwd=Path(__file__).resolve().parent.parent.parent, - ) + from cognee.run_migrations import run_migrations - if migration_result.returncode != 0: - migration_output = migration_result.stderr + migration_result.stdout - # Check for the expected UserAlreadyExists error (which is not critical) - if ( - "UserAlreadyExists" in migration_output - or "User default_user@example.com already exists" in migration_output - ): - logger.warning("Warning: Default user already exists, continuing startup...") - else: - logger.error(f"Migration failed with unexpected error: {migration_output}") - sys.exit(1) + await run_migrations() logger.info("Database migrations done.") elif args.api_url: diff --git a/cognee/__init__.py b/cognee/__init__.py index 4d150ce4e..cea55e031 100644 --- a/cognee/__init__.py +++ b/cognee/__init__.py @@ -33,3 +33,5 @@ from .api.v1.ui import start_ui # Pipelines from .modules import pipelines + +from cognee.run_migrations import run_migrations diff --git a/alembic.ini b/cognee/alembic.ini similarity index 100% rename from alembic.ini rename to cognee/alembic.ini diff --git a/alembic/README b/cognee/alembic/README similarity index 100% rename from alembic/README rename to cognee/alembic/README diff --git a/alembic/env.py b/cognee/alembic/env.py similarity index 100% rename from alembic/env.py rename to cognee/alembic/env.py diff --git a/alembic/script.py.mako b/cognee/alembic/script.py.mako similarity index 100% rename from alembic/script.py.mako rename to cognee/alembic/script.py.mako diff --git a/alembic/versions/1a58b986e6e1_enable_delete_for_old_tutorial_notebooks.py b/cognee/alembic/versions/1a58b986e6e1_enable_delete_for_old_tutorial_notebooks.py similarity index 100% rename from alembic/versions/1a58b986e6e1_enable_delete_for_old_tutorial_notebooks.py rename to cognee/alembic/versions/1a58b986e6e1_enable_delete_for_old_tutorial_notebooks.py diff --git a/alembic/versions/1d0bb7fede17_add_pipeline_run_status.py b/cognee/alembic/versions/1d0bb7fede17_add_pipeline_run_status.py similarity index 100% rename from alembic/versions/1d0bb7fede17_add_pipeline_run_status.py rename to cognee/alembic/versions/1d0bb7fede17_add_pipeline_run_status.py diff --git a/alembic/versions/1daae0df1866_incremental_loading.py b/cognee/alembic/versions/1daae0df1866_incremental_loading.py similarity index 100% rename from alembic/versions/1daae0df1866_incremental_loading.py rename to cognee/alembic/versions/1daae0df1866_incremental_loading.py diff --git a/alembic/versions/211ab850ef3d_add_sync_operations_table.py b/cognee/alembic/versions/211ab850ef3d_add_sync_operations_table.py similarity index 100% rename from alembic/versions/211ab850ef3d_add_sync_operations_table.py rename to cognee/alembic/versions/211ab850ef3d_add_sync_operations_table.py diff --git a/alembic/versions/45957f0a9849_add_notebook_table.py b/cognee/alembic/versions/45957f0a9849_add_notebook_table.py similarity index 100% rename from alembic/versions/45957f0a9849_add_notebook_table.py rename to cognee/alembic/versions/45957f0a9849_add_notebook_table.py diff --git a/alembic/versions/46a6ce2bd2b2_expand_dataset_database_with_json_.py b/cognee/alembic/versions/46a6ce2bd2b2_expand_dataset_database_with_json_.py similarity index 100% rename from alembic/versions/46a6ce2bd2b2_expand_dataset_database_with_json_.py rename to cognee/alembic/versions/46a6ce2bd2b2_expand_dataset_database_with_json_.py diff --git a/alembic/versions/482cd6517ce4_add_default_user.py b/cognee/alembic/versions/482cd6517ce4_add_default_user.py similarity index 100% rename from alembic/versions/482cd6517ce4_add_default_user.py rename to cognee/alembic/versions/482cd6517ce4_add_default_user.py diff --git a/alembic/versions/76625596c5c3_expand_dataset_database_for_multi_user.py b/cognee/alembic/versions/76625596c5c3_expand_dataset_database_for_multi_user.py similarity index 100% rename from alembic/versions/76625596c5c3_expand_dataset_database_for_multi_user.py rename to cognee/alembic/versions/76625596c5c3_expand_dataset_database_for_multi_user.py diff --git a/alembic/versions/8057ae7329c2_initial_migration.py b/cognee/alembic/versions/8057ae7329c2_initial_migration.py similarity index 100% rename from alembic/versions/8057ae7329c2_initial_migration.py rename to cognee/alembic/versions/8057ae7329c2_initial_migration.py diff --git a/alembic/versions/9e7a3cb85175_loader_separation.py b/cognee/alembic/versions/9e7a3cb85175_loader_separation.py similarity index 100% rename from alembic/versions/9e7a3cb85175_loader_separation.py rename to cognee/alembic/versions/9e7a3cb85175_loader_separation.py diff --git a/alembic/versions/a1b2c3d4e5f6_add_label_column_to_data.py b/cognee/alembic/versions/a1b2c3d4e5f6_add_label_column_to_data.py similarity index 100% rename from alembic/versions/a1b2c3d4e5f6_add_label_column_to_data.py rename to cognee/alembic/versions/a1b2c3d4e5f6_add_label_column_to_data.py diff --git a/alembic/versions/ab7e313804ae_permission_system_rework.py b/cognee/alembic/versions/ab7e313804ae_permission_system_rework.py similarity index 100% rename from alembic/versions/ab7e313804ae_permission_system_rework.py rename to cognee/alembic/versions/ab7e313804ae_permission_system_rework.py diff --git a/alembic/versions/b9274c27a25a_kuzu_11_migration.py b/cognee/alembic/versions/b9274c27a25a_kuzu_11_migration.py similarity index 100% rename from alembic/versions/b9274c27a25a_kuzu_11_migration.py rename to cognee/alembic/versions/b9274c27a25a_kuzu_11_migration.py diff --git a/alembic/versions/c946955da633_multi_tenant_support.py b/cognee/alembic/versions/c946955da633_multi_tenant_support.py similarity index 100% rename from alembic/versions/c946955da633_multi_tenant_support.py rename to cognee/alembic/versions/c946955da633_multi_tenant_support.py diff --git a/alembic/versions/e1ec1dcb50b6_add_last_accessed_to_data.py b/cognee/alembic/versions/e1ec1dcb50b6_add_last_accessed_to_data.py similarity index 100% rename from alembic/versions/e1ec1dcb50b6_add_last_accessed_to_data.py rename to cognee/alembic/versions/e1ec1dcb50b6_add_last_accessed_to_data.py diff --git a/alembic/versions/e4ebee1091e7_expand_data_model_info.py b/cognee/alembic/versions/e4ebee1091e7_expand_data_model_info.py similarity index 100% rename from alembic/versions/e4ebee1091e7_expand_data_model_info.py rename to cognee/alembic/versions/e4ebee1091e7_expand_data_model_info.py diff --git a/cognee/run_migrations.py b/cognee/run_migrations.py new file mode 100644 index 000000000..e501456dd --- /dev/null +++ b/cognee/run_migrations.py @@ -0,0 +1,48 @@ +import os +import sys +import subprocess +from pathlib import Path +import importlib.resources as pkg_resources + +# Assuming your package is named 'cognee' and the migrations are under 'cognee/alembic' +# This is a placeholder for the path logic. +MIGRATIONS_PACKAGE = "cognee" +MIGRATIONS_DIR_NAME = "alembic" + + +async def run_migrations(): + """ + Finds the Alembic configuration within the installed package and + programmatically executes 'alembic upgrade head'. + """ + # 1. Locate the base path of the installed package. + # This reliably finds the root directory of the installed 'cognee' package. + # We look for the parent of the 'migrations' directory. + package_root = str(pkg_resources.files(MIGRATIONS_PACKAGE)) + + # 2. Define the paths for config and scripts + alembic_ini_path = os.path.join(package_root, "alembic.ini") + script_location_path = os.path.join(package_root, MIGRATIONS_DIR_NAME) + + if not os.path.exists(alembic_ini_path): + raise FileNotFoundError( + f"Error: alembic.ini not found at expected locations for package '{MIGRATIONS_PACKAGE}'." + ) + if not os.path.exists(script_location_path): + raise FileNotFoundError( + f"Error: Migrations directory not found at expected locations for package '{MIGRATIONS_PACKAGE}'." + ) + + migration_result = subprocess.run( + ["python", "-m", "alembic", "upgrade", "head"], + capture_output=True, + text=True, + cwd=Path(package_root), + ) + + if migration_result.returncode != 0: + migration_output = migration_result.stderr + migration_result.stdout + print(f"Migration failed with unexpected error: {migration_output}") + sys.exit(1) + + print("Migration completed successfully.") diff --git a/entrypoint.sh b/entrypoint.sh index 82c4a2fea..ed7e6b15d 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -11,34 +11,24 @@ echo "Debug port: $DEBUG_PORT" echo "HTTP port: $HTTP_PORT" # Run Alembic migrations with proper error handling. -# Note on UserAlreadyExists error handling: -# During database migrations, we attempt to create a default user. If this user -# already exists (e.g., from a previous deployment or migration), it's not a -# critical error and shouldn't prevent the application from starting. This is -# different from other migration errors which could indicate database schema -# inconsistencies and should cause the startup to fail. This check allows for -# smooth redeployments and container restarts while maintaining data integrity. echo "Running database migrations..." +# Move to the cognee directory to run alembic migrations from there set +e # Disable exit on error to handle specific migration errors -MIGRATION_OUTPUT=$(alembic upgrade head) +MIGRATION_OUTPUT=$(cd cognee && alembic upgrade head) MIGRATION_EXIT_CODE=$? set -e if [[ $MIGRATION_EXIT_CODE -ne 0 ]]; then - if [[ "$MIGRATION_OUTPUT" == *"UserAlreadyExists"* ]] || [[ "$MIGRATION_OUTPUT" == *"User default_user@example.com already exists"* ]]; then - echo "Warning: Default user already exists, continuing startup..." - else - echo "Migration failed with unexpected error. Trying to run Cognee without migrations." + echo "Migration failed with unexpected error. Trying to run Cognee without migrations." - echo "Initializing database tables..." - python /app/cognee/modules/engine/operations/setup.py - INIT_EXIT_CODE=$? + echo "Initializing database tables..." + python /app/cognee/modules/engine/operations/setup.py + INIT_EXIT_CODE=$? - if [[ $INIT_EXIT_CODE -ne 0 ]]; then - echo "Database initialization failed!" - exit 1 - fi + if [[ $INIT_EXIT_CODE -ne 0 ]]; then + echo "Database initialization failed!" + exit 1 fi else echo "Database migrations done."