feat: project skeleton

- infra (k8s, kind, helm, docker) backbone is implemented
- security: implementation + unit tests are done
This commit is contained in:
2025-11-21 12:00:00 -05:00
commit fbe9fbba6e
46 changed files with 3450 additions and 0 deletions

119
migrations/migrate.py Normal file
View File

@@ -0,0 +1,119 @@
"""
Simple migration runner using asyncpg.
Tracks applied migrations in a _migrations table.
Usage:
DATABASE_URL=postgresql://user:pass@localhost/db uv run python migrations/migrate.py apply
DATABASE_URL=postgresql://user:pass@localhost/db uv run python migrations/migrate.py status
"""
import asyncio
import os
import sys
from pathlib import Path
import asyncpg
MIGRATIONS_DIR = Path(__file__).parent
async def ensure_migrations_table(conn: asyncpg.Connection) -> None:
"""Create the migrations tracking table if it doesn't exist."""
await conn.execute("""
CREATE TABLE IF NOT EXISTS _migrations (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL UNIQUE,
applied_at TIMESTAMPTZ NOT NULL DEFAULT now()
)
""")
async def get_applied_migrations(conn: asyncpg.Connection) -> set[str]:
"""Get the set of already applied migration names."""
rows = await conn.fetch("SELECT name FROM _migrations")
return {row["name"] for row in rows}
async def get_pending_migrations(conn: asyncpg.Connection) -> list[Path]:
"""Get list of migration files that haven't been applied yet."""
applied = await get_applied_migrations(conn)
sql_files = sorted(MIGRATIONS_DIR.glob("*.sql"))
return [f for f in sql_files if f.name not in applied]
async def apply_migration(conn: asyncpg.Connection, migration_file: Path) -> None:
"""Apply a single migration file within a transaction."""
sql = migration_file.read_text()
async with conn.transaction():
await conn.execute(sql)
await conn.execute(
"INSERT INTO _migrations (name) VALUES ($1)",
migration_file.name
)
print(f"Applied: {migration_file.name}")
async def migrate(database_url: str) -> None:
"""Apply all pending migrations."""
conn = await asyncpg.connect(database_url)
try:
await ensure_migrations_table(conn)
pending = await get_pending_migrations(conn)
if not pending:
print("No pending migrations.")
return
for migration_file in pending:
await apply_migration(conn, migration_file)
print(f"Applied {len(pending)} migration(s).")
finally:
await conn.close()
async def status(database_url: str) -> None:
"""Show migration status."""
conn = await asyncpg.connect(database_url)
try:
await ensure_migrations_table(conn)
applied = await get_applied_migrations(conn)
pending = await get_pending_migrations(conn)
print("Applied migrations:")
for name in sorted(applied):
print(f" [x] {name}")
print("\nPending migrations:")
for f in pending:
print(f" [ ] {f.name}")
if not applied and not pending:
print(" (none)")
finally:
await conn.close()
def main() -> None:
database_url = os.environ.get("DATABASE_URL")
if not database_url:
print("Error: DATABASE_URL environment variable is required")
sys.exit(1)
if len(sys.argv) < 2:
print("Usage: python migrate.py [apply|status]")
sys.exit(1)
command = sys.argv[1]
if command == "apply":
asyncio.run(migrate(database_url))
elif command == "status":
asyncio.run(status(database_url))
else:
print(f"Unknown command: {command}")
print("Usage: python migrate.py [apply|status]")
sys.exit(1)
if __name__ == "__main__":
main()