Skip to content

server: add SQLAlchemy + Alembic dependencies and skeleton#321

Open
nissessenap wants to merge 1 commit intomozilla-ai:mainfrom
nissessenap:issue-304-alembic-skeleton
Open

server: add SQLAlchemy + Alembic dependencies and skeleton#321
nissessenap wants to merge 1 commit intomozilla-ai:mainfrom
nissessenap:issue-304-alembic-skeleton

Conversation

@nissessenap
Copy link
Copy Markdown

Closes #304. Part of the #257 epic (Phase 1, step 1) — passive
infrastructure only; no migrations, no runtime code imports either
library, app.py / store.py / tables.py untouched.

What's in

  • server/backend/pyproject.toml: sqlalchemy>=2.0.49,<2.1 and
    alembic>=1.18.4,<2 added to runtime deps.
  • server/backend/uv.lock: regenerated. Diff vs main is only the 5
    net-new packages (alembic, mako, sqlalchemy, greenlet, markupsafe);
    no pre-existing entry changed.
  • server/backend/src/cq_server/db_url.py: resolve_database_url()
    helper centralising the precedence CQ_DATABASE_URL
    CQ_DB_PATH (wrapped as sqlite:///…) → default /data/cq.db.
    No runtime callers yet; Wire CQ_DATABASE_URL and store factory #309 will wire it into the store factory.
  • server/backend/alembic.ini + alembic/env.py +
    alembic/script.py.mako + empty versions/: minimal skeleton.
    env.py sets render_as_batch=True in both online and offline
    modes so future migrations run cleanly on SQLite;
    target_metadata=None until Baseline Alembic migration + stamp-on-startup logic #305 adds the baseline.
  • server/backend/README.md: short note explaining the wiring is
    staged-but-unused and documenting the URL precedence.
  • tests/test_db_url.py: four TDD cases covering explicit URL wins,
    CQ_DB_PATH wrapping, the /data/cq.db default, and empty-string
    CQ_DATABASE_URL falling through to CQ_DB_PATH (container
    orchestrators sometimes pass empty env vars).

What's intentionally out

Deferred to the next Phase 1 children per #257's dep graph:

Known follow-up

alembic/env.py routes the resolved URL through
config.set_main_option("sqlalchemy.url", …), which internally uses
ConfigParser% characters are treated as interpolation tokens.
Harmless today (SQLite paths only), but a Postgres URL containing a
URL-encoded password (p%40ss) would blow up. An in-line comment
flags this for #309 to resolve — either by escaping at the boundary
or, cleaner, by dropping the ConfigParser round-trip and passing
the URL straight to context.configure(url=…) / create_engine(…).

Test plan

🤖 Generated with Claude Code

Part of mozilla-ai#257 (Phase 1, step 1) — per RFC mozilla-ai#275 and issue mozilla-ai#304.

Land the dependency + Alembic skeleton so follow-up children (baseline
migration, async Store protocol, SqliteStore, CQ_DATABASE_URL factory)
have something to build on. Passive infrastructure only: no migrations
are defined, no runtime code imports SQLAlchemy or Alembic, and
app.py/store.py/tables.py are untouched.

- server/backend/pyproject.toml: add sqlalchemy>=2.0.49,<2.1 and
  alembic>=1.18.4,<2 to runtime dependencies; uv.lock regenerated.
- server/backend/src/cq_server/db_url.py: resolve_database_url()
  helper centralising the CQ_DATABASE_URL -> CQ_DB_PATH -> default
  precedence. No runtime callers yet; mozilla-ai#309 will wire it into the
  store factory.
- server/backend/alembic.ini + alembic/env.py + script.py.mako +
  versions/.gitkeep: minimal skeleton. env.py sets render_as_batch=True
  in both online and offline modes so future migrations run cleanly on
  SQLite; target_metadata is None until mozilla-ai#305 adds the baseline.
- server/backend/README.md: short note explaining the wiring and the
  URL precedence; full env-var docs land with mozilla-ai#309.
- tests/test_db_url.py: three TDD cases (explicit URL wins, CQ_DB_PATH
  wraps as sqlite:///, default).

Acceptance:
  - alembic current runs cleanly against an existing dev SQLite DB
    (exits 0, no revision printed — no migrations defined yet).
  - Full server test suite green (193 passed).
  - make lint-server-backend clean.
  - No change in server runtime behavior.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Edvin Norling <edvin.norling@kognic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add SQLAlchemy + Alembic dependencies and Alembic skeleton

1 participant