Initial release: rarelens platform skeleton (AGPL-3.0)
ci / api (push) Failing after 10s
ci / terraform (push) Failing after 11s
ci / web (push) Failing after 35s
ci / pipeline (push) Failing after 2m29s
ci / images (api) (push) Skipped
ci / images (ml) (push) Skipped
ci / images (pipeline) (push) Skipped
ci / images (web) (push) Skipped

End-to-end variant interpretation platform for rare genetic disease research:
SvelteKit UI, FastAPI + PostgreSQL API, Nextflow/Ensembl VEP pipeline,
LightGBM pathogenicity scoring with MLflow, K8s/ArgoCD/GCP infrastructure.
Public test data only; no clinical claims.
This commit is contained in:
2026-09-11 16:55:35 +01:00
commit 5463f489a3
74 changed files with 4597 additions and 0 deletions
+32
View File
@@ -0,0 +1,32 @@
import asyncio
from logging.config import fileConfig
from alembic import context
from sqlalchemy.ext.asyncio import async_engine_from_config
from sqlalchemy import pool
from app.config import settings
from app.models import Base
config = context.config
config.set_main_option("sqlalchemy.url", settings.database_url)
if config.config_file_name:
fileConfig(config.config_file_name)
target_metadata = Base.metadata
def run_migrations(connection):
context.configure(connection=connection, target_metadata=target_metadata)
with context.begin_transaction():
context.run_migrations()
async def run_async():
engine = async_engine_from_config(
config.get_section(config.config_ini_section, {}), poolclass=pool.NullPool
)
async with engine.connect() as conn:
await conn.run_sync(run_migrations)
asyncio.run(run_async())
+26
View File
@@ -0,0 +1,26 @@
"""${message}
Revision ID: ${up_revision}
Revises: ${down_revision | comma,n}
Create Date: ${create_date}
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
${imports if imports else ""}
# revision identifiers, used by Alembic.
revision: str = ${repr(up_revision)}
down_revision: Union[str, None] = ${repr(down_revision)}
branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)}
depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)}
def upgrade() -> None:
${upgrades if upgrades else "pass"}
def downgrade() -> None:
${downgrades if downgrades else "pass"}
@@ -0,0 +1,90 @@
"""initial schema
Revision ID: a3e9ead256a5
Revises:
Create Date: 2026-09-11 15:36:04.335440
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
revision: str = 'a3e9ead256a5'
down_revision: Union[str, None] = None
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('samples',
sa.Column('id', sa.UUID(), nullable=False),
sa.Column('name', sa.String(length=120), nullable=False),
sa.Column('vcf_uri', sa.Text(), nullable=False),
sa.Column('assembly', sa.String(length=10), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('name')
)
op.create_table('jobs',
sa.Column('id', sa.UUID(), nullable=False),
sa.Column('sample_id', sa.UUID(), nullable=False),
sa.Column('status', sa.Enum('queued', 'running', 'succeeded', 'failed', name='jobstatus'), nullable=False),
sa.Column('workflow_ref', sa.String(length=200), nullable=True),
sa.Column('vep_version', sa.String(length=40), nullable=True),
sa.Column('log', sa.Text(), nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
sa.Column('finished_at', sa.DateTime(timezone=True), nullable=True),
sa.ForeignKeyConstraint(['sample_id'], ['samples.id'], ondelete='CASCADE'),
sa.PrimaryKeyConstraint('id')
)
op.create_table('variants',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('job_id', sa.UUID(), nullable=False),
sa.Column('chrom', sa.String(length=10), nullable=False),
sa.Column('pos', sa.Integer(), nullable=False),
sa.Column('ref', sa.Text(), nullable=False),
sa.Column('alt', sa.Text(), nullable=False),
sa.Column('gene', sa.String(length=60), nullable=True),
sa.Column('consequence', sa.String(length=120), nullable=True),
sa.Column('impact', sa.String(length=20), nullable=True),
sa.Column('hgvsc', sa.Text(), nullable=True),
sa.Column('hgvsp', sa.Text(), nullable=True),
sa.Column('gnomad_af', sa.Float(), nullable=True),
sa.Column('clinvar_sig', sa.String(length=120), nullable=True),
sa.Column('annotations', postgresql.JSONB(astext_type=sa.Text()), nullable=False),
sa.ForeignKeyConstraint(['job_id'], ['jobs.id'], ondelete='CASCADE'),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_variants_chrom'), 'variants', ['chrom'], unique=False)
op.create_index(op.f('ix_variants_gene'), 'variants', ['gene'], unique=False)
op.create_index(op.f('ix_variants_job_id'), 'variants', ['job_id'], unique=False)
op.create_index(op.f('ix_variants_pos'), 'variants', ['pos'], unique=False)
op.create_table('predictions',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('variant_id', sa.Integer(), nullable=False),
sa.Column('model_name', sa.String(length=80), nullable=False),
sa.Column('model_version', sa.String(length=40), nullable=False),
sa.Column('score', sa.Float(), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
sa.ForeignKeyConstraint(['variant_id'], ['variants.id'], ondelete='CASCADE'),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('variant_id')
)
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('predictions')
op.drop_index(op.f('ix_variants_pos'), table_name='variants')
op.drop_index(op.f('ix_variants_job_id'), table_name='variants')
op.drop_index(op.f('ix_variants_gene'), table_name='variants')
op.drop_index(op.f('ix_variants_chrom'), table_name='variants')
op.drop_table('variants')
op.drop_table('jobs')
op.drop_table('samples')
# ### end Alembic commands ###