feat: add alembic migrations, integration tests, and CI support

- Add alembic dependency and initialize migration framework
- Configure async alembic env.py for SQLAlchemy 2.0
- Create initial migration for PostORM table
- Gate init_db() with SKIP_INIT_DB env var for CI/production
- Add PostgreSQL service to Woodpecker CI pipeline
- Create integration tests for migrations (TC-INT-001..002)
- Create integration tests for SQLAlchemyPostRepository (TC-INT-003..009)
- Add unit test for init_db skip behavior (TC-UNIT-901)
- All 176 tests pass, coverage 72.59%
This commit is contained in:
2026-05-09 21:11:35 +03:00
parent 5ee1decca2
commit 9cc2f6284d
14 changed files with 571 additions and 0 deletions

View File

@@ -0,0 +1,44 @@
from typing import cast
import pytest
from sqlalchemy import inspect
from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession
class TestMigrations:
@pytest.mark.asyncio
async def test_initial_migration_creates_post_table(self, db_session: AsyncSession) -> None:
engine = cast(AsyncEngine, db_session.bind)
async with engine.connect() as conn:
tables = await conn.run_sync(lambda sync_conn: inspect(sync_conn).get_table_names())
assert "posts" in tables
@pytest.mark.asyncio
async def test_posts_table_has_expected_columns(self, db_session: AsyncSession) -> None:
engine = cast(AsyncEngine, db_session.bind)
async with engine.connect() as conn:
columns = await conn.run_sync(lambda sync_conn: inspect(sync_conn).get_columns("posts"))
column_names = [col["name"] for col in columns]
expected = [
"id",
"title",
"content",
"slug",
"author_id",
"published",
"tags",
"created_at",
"updated_at",
]
for col in expected:
assert col in column_names
@pytest.mark.asyncio
async def test_posts_table_has_indexes(self, db_session: AsyncSession) -> None:
engine = cast(AsyncEngine, db_session.bind)
async with engine.connect() as conn:
indexes = await conn.run_sync(lambda sync_conn: inspect(sync_conn).get_indexes("posts"))
index_names = [idx["name"] for idx in indexes]
assert "ix_posts_slug" in index_names
assert "ix_posts_author_id" in index_names
assert "ix_posts_published" in index_names