Skip to content

feat: implement Alembic migrations - #68

Merged
Cipher208 merged 1 commit into
masterfrom
feat/alembic-migrations
Aug 7, 2026
Merged

feat: implement Alembic migrations#68
Cipher208 merged 1 commit into
masterfrom
feat/alembic-migrations

Conversation

@Cipher208

@Cipher208 Cipher208 commented Aug 7, 2026

Copy link
Copy Markdown
Owner

Replaced custom migration manager with Alembic. Includes baseline v8 schema migration and dynamic DB path resolution.

Summary by CodeRabbit

  • New Features

    • Added database migration support for initializing and upgrading the application’s SQLite schema.
    • Added migration tracking with current version and migration status reporting.
    • Added support for offline and online migration execution.
  • Bug Fixes

    • Improved migration handling when the database version is unavailable or requires initialization.

@Cipher208
Cipher208 merged commit f6b8c85 into master Aug 7, 2026
@Cipher208
Cipher208 deleted the feat/alembic-migrations branch August 7, 2026 21:21
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 7a5ff0a0-3fb4-4112-832a-fac50ceafbfc

📥 Commits

Reviewing files that changed from the base of the PR and between 42bc2e2 and a01bd4a.

📒 Files selected for processing (6)
  • alembic.ini
  • alembic/README
  • alembic/env.py
  • alembic/script.py.mako
  • alembic/versions/a38d67fcd99e_init_v8_schema.py
  • shared/migrations.py

Walkthrough

The PR replaces embedded migrations with Alembic. It adds the Alembic runtime configuration, creates the v8 SQLite schema through an initial revision, and updates MigrationManager to run upgrades and read alembic_version.

Changes

Alembic migration integration

Layer / File(s) Summary
Alembic runtime setup
alembic.ini, alembic/README, alembic/env.py, alembic/script.py.mako
Adds Alembic configuration, SQLite URL resolution, offline and online migration execution, logging, and revision templates.
Baseline v8 schema migration
alembic/versions/a38d67fcd99e_init_v8_schema.py
Creates the v8 SQLite tables, indexes, FTS5 virtual tables, and default memory-kind registry data. The downgrade is a no-op.
MigrationManager Alembic integration
shared/migrations.py
Runs upgrade head in a worker thread, reads alembic_version, returns string versions and migration status, and reports pending work as Update to head.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant MigrationManager
  participant Alembic
  participant AlembicEnv
  participant SQLiteDatabase
  MigrationManager->>Alembic: run upgrade to head
  Alembic->>AlembicEnv: load migration environment
  AlembicEnv->>SQLiteDatabase: apply baseline migration
  MigrationManager->>SQLiteDatabase: query alembic_version
  SQLiteDatabase-->>MigrationManager: return version or None
Loading
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/alembic-migrations

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Aug 7, 2026

Copy link
Copy Markdown

Greptile Summary

Replaces the custom eight-step SQLite migration manager with Alembic, adds a baseline v8 schema revision, and resolves the migration database dynamically.

  • Adds Alembic configuration, environment, revision template, and the initial v8 schema.
  • Runs synchronous Alembic upgrades from the asynchronous migration manager.
  • Changes migration versions from numeric values to Alembic revision identifiers.

Confidence Score: 2/5

This PR is not safe to merge until existing databases are upgraded correctly, migrations target the requested database, and the readiness check supports Alembic revision identifiers.

Existing installations can be stamped at the Alembic baseline without receiving required columns, injected connection managers migrate a different file, and every readiness request treats the new revision value as an incompatible integer.

Files Needing Attention: alembic/versions/a38d67fcd99e_init_v8_schema.py, alembic/env.py, shared/migrations.py

Important Files Changed

Filename Overview
shared/migrations.py Replaces incremental migrations with Alembic but breaks legacy upgrade handling, injected database targeting, and the readiness consumer’s numeric version contract.
alembic/env.py Configures online and offline Alembic execution but resolves the database independently from MigrationManager’s connection manager.
alembic/versions/a38d67fcd99e_init_v8_schema.py Defines the final v8 schema for fresh databases but cannot bring existing pre-v8 tables to that schema.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Server startup] --> B[MigrationManager.migrate]
    B --> C[get_current_version via AsyncConnectionManager]
    B --> D[Alembic upgrade in worker thread]
    D --> E[env.py resolves memory.db]
    E --> F[Apply baseline v8 revision]
    F --> G[Create or stamp alembic_version]
    B --> H[Read resulting revision]
Loading

Fix All in Codex

Prompt To Fix All With AI
### Issue 1
alembic/versions/a38d67fcd99e_init_v8_schema.py:21-30
**Legacy schemas remain incomplete**

If an existing database was created by a pre-v8 custom migration, Alembic runs this baseline but `CREATE TABLE IF NOT EXISTS` leaves existing table definitions unchanged. Alembic then records the revision while required columns such as `core_memory.memory_kind` and `rag_chunks.bin_embedding` remain absent, causing subsequent writes and searches to fail with SQLite schema errors.

### Issue 2
alembic/env.py:14-17
**Migration targets the wrong database**

When `MigrationManager` receives an `AsyncConnectionManager` with a custom `base_dir`, version checks use that directory while Alembic independently resolves the database from `MCP_MEMORY_DATA_DIR`. The upgrade therefore modifies another database and leaves the requested database unmigrated, causing missing-table or missing-column failures for custom-directory consumers.

### Issue 3
shared/migrations.py:32-38
**Revision type breaks readiness**

`get_current_version()` now returns an Alembic revision string or `None`, but the readiness endpoint still compares the result with integer `2`. That comparison raises `TypeError`, which the endpoint converts into `ready=false` and `migration_version=0`, so health-check-driven deployments never become ready after a successful migration.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "feat: implement Alembic migrations for m..." | Re-trigger Greptile

Comment on lines +21 to +30
def upgrade() -> None:
# 1. Core tables
op.execute("""
CREATE TABLE IF NOT EXISTS core_memory (
entry_id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT NOT NULL, key TEXT NOT NULL, value TEXT NOT NULL,
importance REAL DEFAULT 0.5, is_conflict INTEGER DEFAULT 0,
conflict_group_id TEXT, created_at REAL NOT NULL, updated_at REAL NOT NULL,
memory_kind TEXT, expires_at REAL, source TEXT DEFAULT 'manual', metadata TEXT
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Legacy schemas remain incomplete

If an existing database was created by a pre-v8 custom migration, Alembic runs this baseline but CREATE TABLE IF NOT EXISTS leaves existing table definitions unchanged. Alembic then records the revision while required columns such as core_memory.memory_kind and rag_chunks.bin_embedding remain absent, causing subsequent writes and searches to fail with SQLite schema errors.

Prompt To Fix With AI
This is a comment left during a code review.
Path: alembic/versions/a38d67fcd99e_init_v8_schema.py
Line: 21-30

Comment:
**Legacy schemas remain incomplete**

If an existing database was created by a pre-v8 custom migration, Alembic runs this baseline but `CREATE TABLE IF NOT EXISTS` leaves existing table definitions unchanged. Alembic then records the revision while required columns such as `core_memory.memory_kind` and `rag_chunks.bin_embedding` remain absent, causing subsequent writes and searches to fail with SQLite schema errors.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Codex

Comment thread alembic/env.py
Comment on lines +14 to +17
def get_url():
data_dir = os.environ.get("MCP_MEMORY_DATA_DIR", str(Path.home() / ".mcp-ariel-memory"))
db_path = Path(data_dir) / "memory.db"
return f"sqlite:///{db_path}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Migration targets the wrong database

When MigrationManager receives an AsyncConnectionManager with a custom base_dir, version checks use that directory while Alembic independently resolves the database from MCP_MEMORY_DATA_DIR. The upgrade therefore modifies another database and leaves the requested database unmigrated, causing missing-table or missing-column failures for custom-directory consumers.

Prompt To Fix With AI
This is a comment left during a code review.
Path: alembic/env.py
Line: 14-17

Comment:
**Migration targets the wrong database**

When `MigrationManager` receives an `AsyncConnectionManager` with a custom `base_dir`, version checks use that directory while Alembic independently resolves the database from `MCP_MEMORY_DATA_DIR`. The upgrade therefore modifies another database and leaves the requested database unmigrated, causing missing-table or missing-column failures for custom-directory consumers.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Codex

Comment thread shared/migrations.py
Comment on lines +32 to +38
async def get_current_version(self) -> str | None:
conn = await self._cm.get(DB_NAME)
try:
row = await (await conn.execute("SELECT MAX(version) as v FROM migration_log")).fetchone()
return row["v"] if row and row["v"] else 0
except sqlite3.OperationalError:
return 0
row = await (await conn.execute("SELECT version_num FROM alembic_version")).fetchone()
return row["version_num"] if row else None
except Exception:
return None

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Revision type breaks readiness

get_current_version() now returns an Alembic revision string or None, but the readiness endpoint still compares the result with integer 2. That comparison raises TypeError, which the endpoint converts into ready=false and migration_version=0, so health-check-driven deployments never become ready after a successful migration.

Prompt To Fix With AI
This is a comment left during a code review.
Path: shared/migrations.py
Line: 32-38

Comment:
**Revision type breaks readiness**

`get_current_version()` now returns an Alembic revision string or `None`, but the readiness endpoint still compares the result with integer `2`. That comparison raises `TypeError`, which the endpoint converts into `ready=false` and `migration_version=0`, so health-check-driven deployments never become ready after a successful migration.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Codex

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant